/ Hex Artifact Content
Login

Artifact 10f881e4508976d970569fe0e7779bfec17907e5:


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 23 64 65 66 69 6e 65 20 53 51 4c 49 54 45  ..#define SQLITE
0c90: 5f 4d 55 4c 54 49 50 4c 45 58 5f 4a 4f 55 52 4e  _MULTIPLEX_JOURN
0ca0: 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54 20 34 30  AL_8_3_OFFSET 40
0cb0: 30 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  0.../***********
0cc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 53 68  ************* Sh
0cd0: 69 6d 20 44 65 66 69 6e 69 74 69 6f 6e 73 20 2a  im Definitions *
0ce0: 2a 2a 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 2a 2a 2a 2f 0a 0a  *************/..
0d00: 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f 4d  #ifndef SQLITE_M
0d10: 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d  ULTIPLEX_VFS_NAM
0d20: 45 0a 23 20 64 65 66 69 6e 65 20 53 51 4c 49 54  E.# define SQLIT
0d30: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f  E_MULTIPLEX_VFS_
0d40: 4e 41 4d 45 20 22 6d 75 6c 74 69 70 6c 65 78 22  NAME "multiplex"
0d50: 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 54 68 69 73  .#endif../* This
0d60: 20 69 73 20 74 68 65 20 6c 69 6d 69 74 20 6f 6e   is the limit on
0d70: 20 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 2e   the chunk size.
0d80: 20 20 49 74 20 6d 61 79 20 62 65 20 63 68 61 6e    It may be chan
0d90: 67 65 64 20 62 79 20 63 61 6c 6c 69 6e 67 0a 2a  ged by calling.*
0da0: 2a 20 74 68 65 20 78 46 69 6c 65 43 6f 6e 74 72  * the xFileContr
0db0: 6f 6c 28 29 20 69 6e 74 65 72 66 61 63 65 2e 20  ol() interface. 
0dc0: 20 49 74 20 77 69 6c 6c 20 62 65 20 72 6f 75 6e   It will be roun
0dd0: 64 65 64 20 75 70 20 74 6f 20 61 20 0a 2a 2a 20  ded up to a .** 
0de0: 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f  multiple of MAX_
0df0: 50 41 47 45 5f 53 49 5a 45 2e 20 20 57 65 20 64  PAGE_SIZE.  We d
0e00: 65 66 61 75 6c 74 20 69 74 20 68 65 72 65 20 74  efault it here t
0e10: 6f 20 32 47 69 42 20 6c 65 73 73 20 36 34 4b 69  o 2GiB less 64Ki
0e20: 42 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51  B..*/.#ifndef SQ
0e30: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 43  LITE_MULTIPLEX_C
0e40: 48 55 4e 4b 5f 53 49 5a 45 0a 23 20 64 65 66 69  HUNK_SIZE.# defi
0e50: 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50  ne SQLITE_MULTIP
0e60: 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 20 32  LEX_CHUNK_SIZE 2
0e70: 31 34 37 34 31 38 31 31 32 0a 23 65 6e 64 69 66  147418112.#endif
0e80: 0a 0a 2f 2a 20 54 68 69 73 20 75 73 65 64 20 74  ../* This used t
0e90: 6f 20 62 65 20 74 68 65 20 64 65 66 61 75 6c 74  o be the default
0ea0: 20 6c 69 6d 69 74 20 6f 6e 20 6e 75 6d 62 65 72   limit on number
0eb0: 20 6f 66 20 63 68 75 6e 6b 73 2c 20 62 75 74 0a   of chunks, but.
0ec0: 2a 2a 20 69 74 20 69 73 20 6e 6f 20 6c 6f 6e 67  ** it is no long
0ed0: 65 72 20 65 6e 66 6f 72 63 65 64 2e 20 54 68 65  er enforced. The
0ee0: 72 65 20 69 73 20 63 75 72 72 65 6e 74 6c 79 20  re is currently 
0ef0: 6e 6f 20 6c 69 6d 69 74 20 74 6f 20 74 68 65 0a  no limit to the.
0f00: 2a 2a 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75  ** number of chu
0f10: 6e 6b 73 2e 0a 2a 2a 0a 2a 2a 20 4d 61 79 20 62  nks..**.** May b
0f20: 65 20 63 68 61 6e 67 65 64 20 62 79 20 63 61 6c  e changed by cal
0f30: 6c 69 6e 67 20 74 68 65 20 78 46 69 6c 65 43 6f  ling the xFileCo
0f40: 6e 74 72 6f 6c 28 29 20 69 6e 74 65 72 66 61 63  ntrol() interfac
0f50: 65 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51  e..*/.#ifndef SQ
0f60: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4d  LITE_MULTIPLEX_M
0f70: 41 58 5f 43 48 55 4e 4b 53 0a 23 20 64 65 66 69  AX_CHUNKS.# defi
0f80: 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50  ne SQLITE_MULTIP
0f90: 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 20 31  LEX_MAX_CHUNKS 1
0fa0: 32 0a 23 65 6e 64 69 66 0a 0a 2f 2a 2a 2a 2a 2a  2.#endif../*****
0fb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0fc0: 2a 2a 2a 20 4f 62 6a 65 63 74 20 44 65 66 69 6e  *** Object Defin
0fd0: 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a  itions *********
0fe0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0ff0: 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72 77 61  *****/../* Forwa
1000: 72 64 20 64 65 63 6c 61 72 61 74 69 6f 6e 20 6f  rd declaration o
1010: 66 20 61 6c 6c 20 6f 62 6a 65 63 74 20 74 79 70  f all object typ
1020: 65 73 20 2a 2f 0a 74 79 70 65 64 65 66 20 73 74  es */.typedef st
1030: 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 47 72  ruct multiplexGr
1040: 6f 75 70 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  oup multiplexGro
1050: 75 70 3b 0a 74 79 70 65 64 65 66 20 73 74 72 75  up;.typedef stru
1060: 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  ct multiplexConn
1070: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 3b 0a   multiplexConn;.
1080: 0a 2f 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74 69 70  ./*.** A "multip
1090: 6c 65 78 20 67 72 6f 75 70 22 20 69 73 20 61 20  lex group" is a 
10a0: 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f 66 20 66 69  collection of fi
10b0: 6c 65 73 20 74 68 61 74 20 63 6f 6c 6c 65 63 74  les that collect
10c0: 69 76 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75 70 20  ively.** makeup 
10d0: 61 20 73 69 6e 67 6c 65 20 53 51 4c 69 74 65 20  a single SQLite 
10e0: 44 42 20 66 69 6c 65 2e 20 20 54 68 69 73 20 61  DB file.  This a
10f0: 6c 6c 6f 77 73 20 74 68 65 20 73 69 7a 65 20 6f  llows the size o
1100: 66 20 74 68 65 20 44 42 0a 2a 2a 20 74 6f 20 65  f the DB.** to e
1110: 78 63 65 65 64 20 74 68 65 20 6c 69 6d 69 74 73  xceed the limits
1120: 20 69 6d 70 6f 73 65 64 20 62 79 20 74 68 65 20   imposed by the 
1130: 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a 2a 0a  file system..**.
1140: 2a 2a 20 54 68 65 72 65 20 69 73 20 61 6e 20 69  ** There is an i
1150: 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65 20 66  nstance of the f
1160: 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74 20  ollowing object 
1170: 66 6f 72 20 65 61 63 68 20 64 65 66 69 6e 65 64  for each defined
1180: 20 6d 75 6c 74 69 70 6c 65 78 0a 2a 2a 20 67 72   multiplex.** gr
1190: 6f 75 70 2e 0a 2a 2f 0a 73 74 72 75 63 74 20 6d  oup..*/.struct m
11a0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 7b 0a  ultiplexGroup {.
11b0: 20 20 73 74 72 75 63 74 20 6d 75 6c 74 69 70 6c    struct multipl
11c0: 65 78 52 65 61 6c 20 7b 20 20 20 20 20 20 20 20  exReal {        
11d0: 20 20 20 2f 2a 20 46 6f 72 20 65 61 63 68 20 63     /* For each c
11e0: 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 73 71 6c 69  hunk */.    sqli
11f0: 74 65 33 5f 66 69 6c 65 20 2a 70 3b 20 20 20 20  te3_file *p;    
1200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
1210: 20 48 61 6e 64 6c 65 20 66 6f 72 20 74 68 65 20   Handle for the 
1220: 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 63 68 61  chunk */.    cha
1230: 72 20 2a 7a 3b 20 20 20 20 20 20 20 20 20 20 20  r *z;           
1240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
1250: 2a 20 4e 61 6d 65 20 6f 66 20 74 68 69 73 20 63  * Name of this c
1260: 68 75 6e 6b 20 2a 2f 0a 20 20 7d 20 2a 61 52 65  hunk */.  } *aRe
1270: 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  al;             
1280: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6c 69             /* li
1290: 73 74 20 6f 66 20 61 6c 6c 20 63 68 75 6e 6b 73  st of all chunks
12a0: 20 2a 2f 0a 20 20 69 6e 74 20 6e 52 65 61 6c 3b   */.  int nReal;
12b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12c0: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
12d0: 20 6f 66 20 63 68 75 6e 6b 73 20 2a 2f 0a 20 20   of chunks */.  
12e0: 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20  char *zName;    
12f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1300: 20 2f 2a 20 42 61 73 65 20 66 69 6c 65 6e 61 6d   /* Base filenam
1310: 65 20 6f 66 20 74 68 69 73 20 67 72 6f 75 70 20  e of this group 
1320: 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 20  */.  int nName; 
1330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1340: 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68 20        /* Length 
1350: 6f 66 20 62 61 73 65 20 66 69 6c 65 6e 61 6d 65  of base filename
1360: 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 3b   */.  int flags;
1370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1380: 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20         /* Flags 
1390: 75 73 65 64 20 66 6f 72 20 6f 72 69 67 69 6e 61  used for origina
13a0: 6c 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 75  l opening */.  u
13b0: 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43 68  nsigned int szCh
13c0: 75 6e 6b 3b 20 20 20 20 20 20 20 20 20 20 20 20  unk;            
13d0: 2f 2a 20 43 68 75 6e 6b 20 73 69 7a 65 20 75 73  /* Chunk size us
13e0: 65 64 20 66 6f 72 20 74 68 69 73 20 67 72 6f 75  ed for this grou
13f0: 70 20 2a 2f 0a 20 20 69 6e 74 20 62 45 6e 61 62  p */.  int bEnab
1400: 6c 65 64 3b 20 20 20 20 20 20 20 20 20 20 20 20  led;            
1410: 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55 45 20          /* TRUE 
1420: 74 6f 20 75 73 65 20 4d 75 6c 74 69 70 6c 65 78  to use Multiplex
1430: 20 56 46 53 20 66 6f 72 20 74 68 69 73 20 66 69   VFS for this fi
1440: 6c 65 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65  le */.  multiple
1450: 78 47 72 6f 75 70 20 2a 70 4e 65 78 74 2c 20 2a  xGroup *pNext, *
1460: 70 50 72 65 76 3b 20 20 20 2f 2a 20 44 6f 75 62  pPrev;   /* Doub
1470: 6c 79 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20 6f  ly linked list o
1480: 66 20 61 6c 6c 20 67 72 6f 75 70 20 6f 62 6a 65  f all group obje
1490: 63 74 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a  cts */.};../*.**
14a0: 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f 66 20   An instance of 
14b0: 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62  the following ob
14c0: 6a 65 63 74 20 72 65 70 72 65 73 65 6e 74 73 20  ject represents 
14d0: 65 61 63 68 20 6f 70 65 6e 20 63 6f 6e 6e 65 63  each open connec
14e0: 74 69 6f 6e 0a 2a 2a 20 74 6f 20 61 20 66 69 6c  tion.** to a fil
14f0: 65 20 74 68 61 74 20 69 73 20 6d 75 6c 74 69 70  e that is multip
1500: 6c 65 78 27 65 64 2e 20 20 54 68 69 73 20 6f 62  lex'ed.  This ob
1510: 6a 65 63 74 20 69 73 20 61 20 0a 2a 2a 20 73 75  ject is a .** su
1520: 62 63 6c 61 73 73 20 6f 66 20 73 71 6c 69 74 65  bclass of sqlite
1530: 33 5f 66 69 6c 65 2e 20 20 54 68 65 20 73 71 6c  3_file.  The sql
1540: 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74  ite3_file object
1550: 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c 79   for the underly
1560: 69 6e 67 0a 2a 2a 20 56 46 53 20 69 73 20 61 70  ing.** VFS is ap
1570: 70 65 6e 64 65 64 20 74 6f 20 74 68 69 73 20 73  pended to this s
1580: 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 72  tructure..*/.str
1590: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  uct multiplexCon
15a0: 6e 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  n {.  sqlite3_fi
15b0: 6c 65 20 62 61 73 65 3b 20 20 20 20 20 20 20 20  le base;        
15c0: 20 20 20 20 20 20 2f 2a 20 42 61 73 65 20 63 6c        /* Base cl
15d0: 61 73 73 20 2d 20 6d 75 73 74 20 62 65 20 66 69  ass - must be fi
15e0: 72 73 74 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c  rst */.  multipl
15f0: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 3b  exGroup *pGroup;
1600: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20           /* The 
1610: 75 6e 64 65 72 6c 79 69 6e 67 20 67 72 6f 75 70  underlying group
1620: 20 6f 66 20 66 69 6c 65 73 20 2a 2f 0a 7d 3b 0a   of files */.};.
1630: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
1640: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 47 6c 6f 62  *********** Glob
1650: 61 6c 20 56 61 72 69 61 62 6c 65 73 20 2a 2a 2a  al Variables ***
1660: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1670: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f  ***************/
1680: 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f 62 61  ./*.** All globa
1690: 6c 20 76 61 72 69 61 62 6c 65 73 20 75 73 65 64  l variables used
16a0: 20 62 79 20 74 68 69 73 20 66 69 6c 65 20 61 72   by this file ar
16b0: 65 20 63 6f 6e 74 61 69 6e 69 6e 67 20 77 69 74  e containing wit
16c0: 68 69 6e 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e  hin the followin
16d0: 67 0a 2a 2a 20 67 4d 75 6c 74 69 70 6c 65 78 20  g.** gMultiplex 
16e0: 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74  structure..*/.st
16f0: 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a 20 20  atic struct {.  
1700: 2f 2a 20 54 68 65 20 70 4f 72 69 67 56 66 73 20  /* The pOrigVfs 
1710: 69 73 20 74 68 65 20 72 65 61 6c 2c 20 6f 72 69  is the real, ori
1720: 67 69 6e 61 6c 20 75 6e 64 65 72 6c 79 69 6e 67  ginal underlying
1730: 20 56 46 53 20 69 6d 70 6c 65 6d 65 6e 74 61 74   VFS implementat
1740: 69 6f 6e 2e 0a 20 20 2a 2a 20 4d 6f 73 74 20 6f  ion..  ** Most o
1750: 70 65 72 61 74 69 6f 6e 73 20 70 61 73 73 2d 74  perations pass-t
1760: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 72 65  hrough to the re
1770: 61 6c 20 56 46 53 2e 20 20 54 68 69 73 20 76 61  al VFS.  This va
1780: 6c 75 65 20 69 73 20 72 65 61 64 2d 6f 6e 6c 79  lue is read-only
1790: 0a 20 20 2a 2a 20 64 75 72 69 6e 67 20 6f 70 65  .  ** during ope
17a0: 72 61 74 69 6f 6e 2e 20 20 49 74 20 69 73 20 6f  ration.  It is o
17b0: 6e 6c 79 20 6d 6f 64 69 66 69 65 64 20 61 74 20  nly modified at 
17c0: 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 74  start-time and t
17d0: 68 75 73 20 64 6f 65 73 20 6e 6f 74 0a 20 20 2a  hus does not.  *
17e0: 2a 20 72 65 71 75 69 72 65 20 61 20 6d 75 74 65  * require a mute
17f0: 78 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65  x..  */.  sqlite
1800: 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 3b  3_vfs *pOrigVfs;
1810: 0a 0a 20 20 2f 2a 20 54 68 65 20 73 54 68 69 73  ..  /* The sThis
1820: 56 66 73 20 69 73 20 74 68 65 20 56 46 53 20 73  Vfs is the VFS s
1830: 74 72 75 63 74 75 72 65 20 75 73 65 64 20 62 79  tructure used by
1840: 20 74 68 69 73 20 73 68 69 6d 2e 20 20 49 74 20   this shim.  It 
1850: 69 73 20 69 6e 69 74 69 61 6c 69 7a 65 64 0a 20  is initialized. 
1860: 20 2a 2a 20 61 74 20 73 74 61 72 74 2d 74 69 6d   ** at start-tim
1870: 65 20 61 6e 64 20 74 68 75 73 20 64 6f 65 73 20  e and thus does 
1880: 6e 6f 74 20 72 65 71 75 69 72 65 20 61 20 6d 75  not require a mu
1890: 74 65 78 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74  tex.  */.  sqlit
18a0: 65 33 5f 76 66 73 20 73 54 68 69 73 56 66 73 3b  e3_vfs sThisVfs;
18b0: 0a 0a 20 20 2f 2a 20 54 68 65 20 73 49 6f 4d 65  ..  /* The sIoMe
18c0: 74 68 6f 64 73 20 64 65 66 69 6e 65 73 20 74 68  thods defines th
18d0: 65 20 6d 65 74 68 6f 64 73 20 75 73 65 64 20 62  e methods used b
18e0: 79 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f  y sqlite3_file o
18f0: 62 6a 65 63 74 73 20 0a 20 20 2a 2a 20 61 73 73  bjects .  ** ass
1900: 6f 63 69 61 74 65 64 20 77 69 74 68 20 74 68 69  ociated with thi
1910: 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73 20 69  s shim.  It is i
1920: 6e 69 74 69 61 6c 69 7a 65 64 20 61 74 20 73 74  nitialized at st
1930: 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 64 6f 65  art-time and doe
1940: 73 0a 20 20 2a 2a 20 6e 6f 74 20 72 65 71 75 69  s.  ** not requi
1950: 72 65 20 61 20 6d 75 74 65 78 2e 0a 20 20 2a 2a  re a mutex..  **
1960: 0a 20 20 2a 2a 20 57 68 65 6e 20 74 68 65 20 75  .  ** When the u
1970: 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20 69 73  nderlying VFS is
1980: 20 63 61 6c 6c 65 64 20 74 6f 20 6f 70 65 6e 20   called to open 
1990: 61 20 66 69 6c 65 2c 20 69 74 20 6d 69 67 68 74  a file, it might
19a0: 20 72 65 74 75 72 6e 20 0a 20 20 2a 2a 20 65 69   return .  ** ei
19b0: 74 68 65 72 20 61 20 76 65 72 73 69 6f 6e 20 31  ther a version 1
19c0: 20 6f 72 20 61 20 76 65 72 73 69 6f 6e 20 32 20   or a version 2 
19d0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a  sqlite3_file obj
19e0: 65 63 74 2e 20 20 54 68 69 73 20 73 68 69 6d 0a  ect.  This shim.
19f0: 20 20 2a 2a 20 68 61 73 20 74 6f 20 63 72 65 61    ** has to crea
1a00: 74 65 20 61 20 77 72 61 70 70 65 72 20 73 71 6c  te a wrapper sql
1a10: 69 74 65 33 5f 66 69 6c 65 20 6f 66 20 74 68 65  ite3_file of the
1a20: 20 73 61 6d 65 20 76 65 72 73 69 6f 6e 2e 20 20   same version.  
1a30: 48 65 6e 63 65 0a 20 20 2a 2a 20 74 68 65 72 65  Hence.  ** there
1a40: 20 61 72 65 20 74 77 6f 20 49 2f 4f 20 6d 65 74   are two I/O met
1a50: 68 6f 64 20 73 74 72 75 63 74 75 72 65 73 2c 20  hod structures, 
1a60: 6f 6e 65 20 66 6f 72 20 76 65 72 73 69 6f 6e 20  one for version 
1a70: 31 20 61 6e 64 20 74 68 65 20 6f 74 68 65 72 0a  1 and the other.
1a80: 20 20 2a 2a 20 66 6f 72 20 76 65 72 73 69 6f 6e    ** for version
1a90: 20 32 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74   2..  */.  sqlit
1aa0: 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49  e3_io_methods sI
1ab0: 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 73 71  oMethodsV1;.  sq
1ac0: 6c 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73  lite3_io_methods
1ad0: 20 73 49 6f 4d 65 74 68 6f 64 73 56 32 3b 0a 0a   sIoMethodsV2;..
1ae0: 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e 20 74    /* True when t
1af0: 68 69 73 20 73 68 69 6d 20 68 61 73 20 62 65 65  his shim has bee
1b00: 6e 20 69 6e 69 74 69 61 6c 69 7a 65 64 2e 0a 20  n initialized.. 
1b10: 20 2a 2f 0a 20 20 69 6e 74 20 69 73 49 6e 69 74   */.  int isInit
1b20: 69 61 6c 69 7a 65 64 3b 0a 0a 20 20 2f 2a 20 46  ialized;..  /* F
1b30: 6f 72 20 72 75 6e 2d 74 69 6d 65 20 61 63 63 65  or run-time acce
1b40: 73 73 20 61 6e 79 20 6f 66 20 74 68 65 20 6f 74  ss any of the ot
1b50: 68 65 72 20 67 6c 6f 62 61 6c 20 64 61 74 61 20  her global data 
1b60: 73 74 72 75 63 74 75 72 65 73 20 69 6e 20 74 68  structures in th
1b70: 69 73 0a 20 20 2a 2a 20 73 68 69 6d 2c 20 74 68  is.  ** shim, th
1b80: 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6d 75 74 65  e following mute
1b90: 78 20 6d 75 73 74 20 62 65 20 68 65 6c 64 2e 0a  x must be held..
1ba0: 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 6d    */.  sqlite3_m
1bb0: 75 74 65 78 20 2a 70 4d 75 74 65 78 3b 0a 0a 20  utex *pMutex;.. 
1bc0: 20 2f 2a 20 4c 69 73 74 20 6f 66 20 6d 75 6c 74   /* List of mult
1bd0: 69 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a 65 63  iplexGroup objec
1be0: 74 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74 69  ts..  */.  multi
1bf0: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
1c00: 70 73 3b 0a 7d 20 67 4d 75 6c 74 69 70 6c 65 78  ps;.} gMultiplex
1c10: 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;../************
1c20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 55 74  ************* Ut
1c30: 69 6c 69 74 79 20 52 6f 75 74 69 6e 65 73 20 2a  ility Routines *
1c40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1c50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1c60: 2f 0a 2f 2a 0a 2a 2a 20 41 63 71 75 69 72 65 20  /./*.** Acquire 
1c70: 61 6e 64 20 72 65 6c 65 61 73 65 20 74 68 65 20  and release the 
1c80: 6d 75 74 65 78 20 75 73 65 64 20 74 6f 20 73 65  mutex used to se
1c90: 72 69 61 6c 69 7a 65 20 61 63 63 65 73 73 20 74  rialize access t
1ca0: 6f 20 74 68 65 0a 2a 2a 20 6c 69 73 74 20 6f 66  o the.** list of
1cb0: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 73   multiplexGroups
1cc0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
1cd0: 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28   multiplexEnter(
1ce0: 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d  void){ sqlite3_m
1cf0: 75 74 65 78 5f 65 6e 74 65 72 28 67 4d 75 6c 74  utex_enter(gMult
1d00: 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d  iplex.pMutex); }
1d10: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c  .static void mul
1d20: 74 69 70 6c 65 78 4c 65 61 76 65 28 76 6f 69 64  tiplexLeave(void
1d30: 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  ){ sqlite3_mutex
1d40: 5f 6c 65 61 76 65 28 67 4d 75 6c 74 69 70 6c 65  _leave(gMultiple
1d50: 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f 2a  x.pMutex); }../*
1d60: 0a 2a 2a 20 43 6f 6d 70 75 74 65 20 61 20 73 74  .** Compute a st
1d70: 72 69 6e 67 20 6c 65 6e 67 74 68 20 74 68 61 74  ring length that
1d80: 20 69 73 20 6c 69 6d 69 74 65 64 20 74 6f 20 77   is limited to w
1d90: 68 61 74 20 63 61 6e 20 62 65 20 73 74 6f 72 65  hat can be store
1da0: 64 20 69 6e 0a 2a 2a 20 6c 6f 77 65 72 20 33 30  d in.** lower 30
1db0: 20 62 69 74 73 20 6f 66 20 61 20 33 32 2d 62 69   bits of a 32-bi
1dc0: 74 20 73 69 67 6e 65 64 20 69 6e 74 65 67 65 72  t signed integer
1dd0: 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 76 61 6c 75  ..**.** The valu
1de0: 65 20 72 65 74 75 72 6e 65 64 20 77 69 6c 6c 20  e returned will 
1df0: 6e 65 76 65 72 20 62 65 20 6e 65 67 61 74 69 76  never be negativ
1e00: 65 2e 20 20 4e 6f 72 20 77 69 6c 6c 20 69 74 20  e.  Nor will it 
1e10: 65 76 65 72 20 62 65 20 67 72 65 61 74 65 72 0a  ever be greater.
1e20: 2a 2a 20 74 68 61 6e 20 74 68 65 20 61 63 74 75  ** than the actu
1e30: 61 6c 20 6c 65 6e 67 74 68 20 6f 66 20 74 68 65  al length of the
1e40: 20 73 74 72 69 6e 67 2e 20 20 46 6f 72 20 76 65   string.  For ve
1e50: 72 79 20 6c 6f 6e 67 20 73 74 72 69 6e 67 73 20  ry long strings 
1e60: 28 67 72 65 61 74 65 72 0a 2a 2a 20 74 68 61 6e  (greater.** than
1e70: 20 31 47 69 42 29 20 74 68 65 20 76 61 6c 75 65   1GiB) the value
1e80: 20 72 65 74 75 72 6e 65 64 20 6d 69 67 68 74 20   returned might 
1e90: 62 65 20 6c 65 73 73 20 74 68 61 6e 20 74 68 65  be less than the
1ea0: 20 74 72 75 65 20 73 74 72 69 6e 67 20 6c 65 6e   true string len
1eb0: 67 74 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  gth..*/.static i
1ec0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c  nt multiplexStrl
1ed0: 65 6e 33 30 28 63 6f 6e 73 74 20 63 68 61 72 20  en30(const char 
1ee0: 2a 7a 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61  *z){.  const cha
1ef0: 72 20 2a 7a 32 20 3d 20 7a 3b 0a 20 20 69 66 28  r *z2 = z;.  if(
1f00: 20 7a 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30   z==0 ) return 0
1f10: 3b 0a 20 20 77 68 69 6c 65 28 20 2a 7a 32 20 29  ;.  while( *z2 )
1f20: 7b 20 7a 32 2b 2b 3b 20 7d 0a 20 20 72 65 74 75  { z2++; }.  retu
1f30: 72 6e 20 30 78 33 66 66 66 66 66 66 66 20 26 20  rn 0x3fffffff & 
1f40: 28 69 6e 74 29 28 7a 32 20 2d 20 7a 29 3b 0a 7d  (int)(z2 - z);.}
1f50: 0a 0a 2f 2a 20 43 6f 6d 70 75 74 65 20 74 68 65  ../* Compute the
1f60: 20 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 74 68   filename for th
1f70: 65 20 69 43 68 75 6e 6b 2d 74 68 20 63 68 75 6e  e iChunk-th chun
1f80: 6b 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  k.*/.static int 
1f90: 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65  multiplexSubFile
1fa0: 6e 61 6d 65 28 6d 75 6c 74 69 70 6c 65 78 47 72  name(multiplexGr
1fb0: 6f 75 70 20 2a 70 47 72 6f 75 70 2c 20 69 6e 74  oup *pGroup, int
1fc0: 20 69 43 68 75 6e 6b 29 7b 0a 20 20 69 66 28 20   iChunk){.  if( 
1fd0: 69 43 68 75 6e 6b 3e 3d 70 47 72 6f 75 70 2d 3e  iChunk>=pGroup->
1fe0: 6e 52 65 61 6c 20 29 7b 0a 20 20 20 20 73 74 72  nReal ){.    str
1ff0: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 52 65 61  uct multiplexRea
2000: 6c 20 2a 70 3b 0a 20 20 20 20 70 20 3d 20 73 71  l *p;.    p = sq
2010: 6c 69 74 65 33 5f 72 65 61 6c 6c 6f 63 28 70 47  lite3_realloc(pG
2020: 72 6f 75 70 2d 3e 61 52 65 61 6c 2c 20 28 69 43  roup->aReal, (iC
2030: 68 75 6e 6b 2b 31 29 2a 73 69 7a 65 6f 66 28 2a  hunk+1)*sizeof(*
2040: 70 29 29 3b 0a 20 20 20 20 69 66 28 20 70 3d 3d  p));.    if( p==
2050: 30 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72  0 ){.      retur
2060: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
2070: 20 20 20 20 7d 0a 20 20 20 20 6d 65 6d 73 65 74      }.    memset
2080: 28 26 70 5b 70 47 72 6f 75 70 2d 3e 6e 52 65 61  (&p[pGroup->nRea
2090: 6c 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 5b  l], 0, sizeof(p[
20a0: 30 5d 29 2a 28 69 43 68 75 6e 6b 2b 31 2d 70 47  0])*(iChunk+1-pG
20b0: 72 6f 75 70 2d 3e 6e 52 65 61 6c 29 29 3b 0a 20  roup->nReal));. 
20c0: 20 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c     pGroup->aReal
20d0: 20 3d 20 70 3b 0a 20 20 20 20 70 47 72 6f 75 70   = p;.    pGroup
20e0: 2d 3e 6e 52 65 61 6c 20 3d 20 69 43 68 75 6e 6b  ->nReal = iChunk
20f0: 2b 31 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70 47  +1;.  }.  if( pG
2100: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 26 26 20 70  roup->zName && p
2110: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
2120: 75 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20  unk].z==0 ){.   
2130: 20 63 68 61 72 20 2a 7a 3b 0a 20 20 20 20 69 6e   char *z;.    in
2140: 74 20 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 6e 4e  t n = pGroup->nN
2150: 61 6d 65 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  ame;.    pGroup-
2160: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
2170: 20 3d 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d   = z = sqlite3_m
2180: 61 6c 6c 6f 63 28 20 6e 2b 34 20 29 3b 0a 20 20  alloc( n+4 );.  
2190: 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b 0a 20 20    if( z==0 ){.  
21a0: 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54      return SQLIT
21b0: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
21c0: 20 20 20 6d 65 6d 63 70 79 28 7a 2c 20 70 47 72     memcpy(z, pGr
21d0: 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 6e 2b 31 29  oup->zName, n+1)
21e0: 3b 0a 20 20 20 20 69 66 28 20 69 43 68 75 6e 6b  ;.    if( iChunk
21f0: 3e 30 20 29 7b 0a 23 69 66 64 65 66 20 53 51 4c  >0 ){.#ifdef SQL
2200: 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33 5f 4e  ITE_ENABLE_8_3_N
2210: 41 4d 45 53 0a 20 20 20 20 20 20 69 6e 74 20 69  AMES.      int i
2220: 3b 0a 20 20 20 20 20 20 66 6f 72 28 69 3d 6e 2d  ;.      for(i=n-
2230: 31 3b 20 69 3e 30 20 26 26 20 69 3e 3d 6e 2d 34  1; i>0 && i>=n-4
2240: 20 26 26 20 7a 5b 69 5d 21 3d 27 2e 27 3b 20 69   && z[i]!='.'; i
2250: 2d 2d 29 7b 7d 0a 20 20 20 20 20 20 69 66 28 20  --){}.      if( 
2260: 69 3e 3d 6e 2d 34 20 29 20 6e 20 3d 20 69 2b 31  i>=n-4 ) n = i+1
2270: 3b 0a 20 20 20 20 20 20 69 66 28 20 70 47 72 6f  ;.      if( pGro
2280: 75 70 2d 3e 66 6c 61 67 73 20 26 20 28 53 51 4c  up->flags & (SQL
2290: 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a 4f  ITE_OPEN_MAIN_JO
22a0: 55 52 4e 41 4c 7c 53 51 4c 49 54 45 5f 4f 50 45  URNAL|SQLITE_OPE
22b0: 4e 5f 54 45 4d 50 5f 4a 4f 55 52 4e 41 4c 29 20  N_TEMP_JOURNAL) 
22c0: 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 54 68  ){.        /* Th
22d0: 65 20 65 78 74 65 6e 73 69 6f 6e 73 20 6f 6e 20  e extensions on 
22e0: 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 73 20 66  overflow files f
22f0: 6f 72 20 6d 61 69 6e 20 64 61 74 61 62 61 73 65  or main database
2300: 73 20 61 72 65 20 30 30 31 2c 20 30 30 32 2c 0a  s are 001, 002,.
2310: 20 20 20 20 20 20 20 20 2a 2a 20 30 30 33 20 61          ** 003 a
2320: 6e 64 20 73 6f 20 66 6f 72 74 68 2e 20 20 54 6f  nd so forth.  To
2330: 20 61 76 6f 69 64 20 6e 61 6d 65 20 63 6f 6c 6c   avoid name coll
2340: 69 73 69 6f 6e 73 2c 20 61 64 64 20 31 30 30 20  isions, add 100 
2350: 74 6f 20 74 68 65 20 0a 20 20 20 20 20 20 20 20  to the .        
2360: 2a 2a 20 65 78 74 65 6e 73 69 6f 6e 73 20 6f 66  ** extensions of
2370: 20 6a 6f 75 72 6e 61 6c 20 66 69 6c 65 73 20 73   journal files s
2380: 6f 20 74 68 61 74 20 74 68 65 79 20 61 72 65 20  o that they are 
2390: 31 30 31 2c 20 31 30 32 2c 20 31 30 33 2c 20 2e  101, 102, 103, .
23a0: 2e 2e 2e 0a 20 20 20 20 20 20 20 20 2a 2f 0a 20  ....        */. 
23b0: 20 20 20 20 20 20 20 69 43 68 75 6e 6b 20 2b 3d         iChunk +=
23c0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
23d0: 58 5f 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46  X_JOURNAL_8_3_OF
23e0: 46 53 45 54 3b 0a 20 20 20 20 20 20 7d 0a 23 65  FSET;.      }.#e
23f0: 6e 64 69 66 0a 20 20 20 20 20 20 73 71 6c 69 74  ndif.      sqlit
2400: 65 33 5f 73 6e 70 72 69 6e 74 66 28 34 2c 26 7a  e3_snprintf(4,&z
2410: 5b 6e 5d 2c 22 25 30 33 64 22 2c 69 43 68 75 6e  [n],"%03d",iChun
2420: 6b 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  k);.    }.  }.  
2430: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
2440: 3b 0a 7d 0a 0a 2f 2a 20 54 72 61 6e 73 6c 61 74  ;.}../* Translat
2450: 65 20 61 6e 20 73 71 6c 69 74 65 33 5f 66 69 6c  e an sqlite3_fil
2460: 65 2a 20 74 68 61 74 20 69 73 20 72 65 61 6c 6c  e* that is reall
2470: 79 20 61 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  y a multiplexGro
2480: 75 70 2a 20 69 6e 74 6f 0a 2a 2a 20 74 68 65 20  up* into.** the 
2490: 73 71 6c 69 74 65 33 5f 66 69 6c 65 2a 20 66 6f  sqlite3_file* fo
24a0: 72 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67  r the underlying
24b0: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a   original VFS..*
24c0: 2f 0a 73 74 61 74 69 63 20 73 71 6c 69 74 65 33  /.static sqlite3
24d0: 5f 66 69 6c 65 20 2a 6d 75 6c 74 69 70 6c 65 78  _file *multiplex
24e0: 53 75 62 4f 70 65 6e 28 0a 20 20 6d 75 6c 74 69  SubOpen(.  multi
24f0: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
2500: 70 2c 0a 20 20 69 6e 74 20 69 43 68 75 6e 6b 2c  p,.  int iChunk,
2510: 0a 20 20 69 6e 74 20 2a 72 63 2c 0a 20 20 69 6e  .  int *rc,.  in
2520: 74 20 2a 70 4f 75 74 46 6c 61 67 73 0a 29 7b 0a  t *pOutFlags.){.
2530: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
2540: 70 53 75 62 4f 70 65 6e 20 3d 20 30 3b 0a 20 20  pSubOpen = 0;.  
2550: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72  sqlite3_vfs *pOr
2560: 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c  igVfs = gMultipl
2570: 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 20  ex.pOrigVfs;    
2580: 20 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20      /* Real VFS 
2590: 2a 2f 0a 0a 23 69 66 64 65 66 20 53 51 4c 49 54  */..#ifdef SQLIT
25a0: 45 5f 45 4e 41 42 4c 45 5f 38 5f 33 5f 4e 41 4d  E_ENABLE_8_3_NAM
25b0: 45 53 0a 20 20 2f 2a 20 49 66 20 4a 4f 55 52 4e  ES.  /* If JOURN
25c0: 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54 20 69 73  AL_8_3_OFFSET is
25d0: 20 73 65 74 20 74 6f 20 28 73 61 79 29 20 35 30   set to (say) 50
25e0: 30 2c 20 74 68 65 6e 20 61 6e 79 20 6f 76 65 72  0, then any over
25f0: 66 6c 6f 77 20 66 69 6c 65 73 20 61 72 65 20 0a  flow files are .
2600: 20 20 2a 2a 20 70 61 72 74 20 6f 66 20 61 20 64    ** part of a d
2610: 61 74 61 62 61 73 65 20 6a 6f 75 72 6e 61 6c 20  atabase journal 
2620: 61 72 65 20 6e 61 6d 65 64 20 64 62 2e 35 30 31  are named db.501
2630: 2c 20 64 62 2e 35 30 32 2c 20 61 6e 64 20 73 6f  , db.502, and so
2640: 20 6f 6e 2e 20 41 20 0a 20 20 2a 2a 20 64 61 74   on. A .  ** dat
2650: 61 62 61 73 65 20 6d 61 79 20 74 68 65 72 65 66  abase may theref
2660: 6f 72 65 20 6e 6f 74 20 67 72 6f 77 20 74 6f 20  ore not grow to 
2670: 6c 61 72 67 65 72 20 74 68 61 6e 20 35 30 30 20  larger than 500 
2680: 63 68 75 6e 6b 73 2e 20 41 74 74 65 6d 70 74 69  chunks. Attempti
2690: 6e 67 0a 20 20 2a 2a 20 74 6f 20 6f 70 65 6e 20  ng.  ** to open 
26a0: 63 68 75 6e 6b 20 35 30 31 20 69 6e 64 69 63 61  chunk 501 indica
26b0: 74 65 73 20 74 68 65 20 64 61 74 61 62 61 73 65  tes the database
26c0: 20 69 73 20 66 75 6c 6c 2e 20 2a 2f 0a 20 20 69   is full. */.  i
26d0: 66 28 20 69 43 68 75 6e 6b 3e 3d 53 51 4c 49 54  f( iChunk>=SQLIT
26e0: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4a 4f 55 52  E_MULTIPLEX_JOUR
26f0: 4e 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54 20 29  NAL_8_3_OFFSET )
2700: 7b 0a 20 20 20 20 2a 72 63 20 3d 20 53 51 4c 49  {.    *rc = SQLI
2710: 54 45 5f 46 55 4c 4c 3b 0a 20 20 20 20 72 65 74  TE_FULL;.    ret
2720: 75 72 6e 20 30 3b 0a 20 20 7d 0a 23 65 6e 64 69  urn 0;.  }.#endi
2730: 66 0a 0a 20 20 2a 72 63 20 3d 20 6d 75 6c 74 69  f..  *rc = multi
2740: 70 6c 65 78 53 75 62 46 69 6c 65 6e 61 6d 65 28  plexSubFilename(
2750: 70 47 72 6f 75 70 2c 20 69 43 68 75 6e 6b 29 3b  pGroup, iChunk);
2760: 0a 20 20 69 66 28 20 28 2a 72 63 29 3d 3d 53 51  .  if( (*rc)==SQ
2770: 4c 49 54 45 5f 4f 4b 20 26 26 20 28 70 53 75 62  LITE_OK && (pSub
2780: 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61  Open = pGroup->a
2790: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 29 3d  Real[iChunk].p)=
27a0: 3d 30 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70  =0 ){.    pSubOp
27b0: 65 6e 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c  en = sqlite3_mal
27c0: 6c 6f 63 28 20 70 4f 72 69 67 56 66 73 2d 3e 73  loc( pOrigVfs->s
27d0: 7a 4f 73 46 69 6c 65 20 29 3b 0a 20 20 20 20 69  zOsFile );.    i
27e0: 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29  f( pSubOpen==0 )
27f0: 7b 0a 20 20 20 20 20 20 2a 72 63 20 3d 20 53 51  {.      *rc = SQ
2800: 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20  LITE_NOMEM;.    
2810: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20    return 0;.    
2820: 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52  }.    pGroup->aR
2830: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d 20  eal[iChunk].p = 
2840: 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 2a 72  pSubOpen;.    *r
2850: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 4f  c = pOrigVfs->xO
2860: 70 65 6e 28 70 4f 72 69 67 56 66 73 2c 20 70 47  pen(pOrigVfs, pG
2870: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
2880: 6e 6b 5d 2e 7a 2c 20 70 53 75 62 4f 70 65 6e 2c  nk].z, pSubOpen,
2890: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
28a0: 20 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75             pGrou
28b0: 70 2d 3e 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c  p->flags, pOutFl
28c0: 61 67 73 29 3b 0a 20 20 20 20 69 66 28 20 2a 72  ags);.    if( *r
28d0: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c!=SQLITE_OK ){.
28e0: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72        sqlite3_fr
28f0: 65 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  ee(pSubOpen);.  
2900: 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61      pGroup->aRea
2910: 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d 20 30 3b  l[iChunk].p = 0;
2920: 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20 30 3b  .      return 0;
2930: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 72 65 74  .    }.  }.  ret
2940: 75 72 6e 20 70 53 75 62 4f 70 65 6e 3b 0a 7d 0a  urn pSubOpen;.}.
2950: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74  ./*.** This is t
2960: 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f  he implementatio
2970: 6e 20 6f 66 20 74 68 65 20 6d 75 6c 74 69 70 6c  n of the multipl
2980: 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 53 51 4c  ex_control() SQL
2990: 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74   function..*/.st
29a0: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
29b0: 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e 63 28 0a  lexControlFunc(.
29c0: 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78    sqlite3_contex
29d0: 74 20 2a 63 6f 6e 74 65 78 74 2c 0a 20 20 69 6e  t *context,.  in
29e0: 74 20 61 72 67 63 2c 0a 20 20 73 71 6c 69 74 65  t argc,.  sqlite
29f0: 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67 76 0a 29  3_value **argv.)
2a00: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
2a10: 49 54 45 5f 4f 4b 3b 0a 20 20 73 71 6c 69 74 65  ITE_OK;.  sqlite
2a20: 33 20 2a 64 62 20 3d 20 73 71 6c 69 74 65 33 5f  3 *db = sqlite3_
2a30: 63 6f 6e 74 65 78 74 5f 64 62 5f 68 61 6e 64 6c  context_db_handl
2a40: 65 28 63 6f 6e 74 65 78 74 29 3b 0a 20 20 69 6e  e(context);.  in
2a50: 74 20 6f 70 3b 0a 20 20 69 6e 74 20 69 56 61 6c  t op;.  int iVal
2a60: 3b 0a 0a 20 20 69 66 28 20 21 64 62 20 7c 7c 20  ;..  if( !db || 
2a70: 61 72 67 63 21 3d 32 20 29 7b 20 0a 20 20 20 20  argc!=2 ){ .    
2a80: 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f  rc = SQLITE_ERRO
2a90: 52 3b 20 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  R; .  }else{.   
2aa0: 20 2f 2a 20 65 78 74 72 61 63 74 20 70 61 72 61   /* extract para
2ab0: 6d 73 20 2a 2f 0a 20 20 20 20 6f 70 20 3d 20 73  ms */.    op = s
2ac0: 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74  qlite3_value_int
2ad0: 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20 20 69  (argv[0]);.    i
2ae0: 56 61 6c 20 3d 20 73 71 6c 69 74 65 33 5f 76 61  Val = sqlite3_va
2af0: 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 31 5d 29  lue_int(argv[1])
2b00: 3b 0a 20 20 20 20 2f 2a 20 6d 61 70 20 66 75 6e  ;.    /* map fun
2b10: 63 74 69 6f 6e 20 6f 70 20 74 6f 20 66 69 6c 65  ction op to file
2b20: 5f 63 6f 6e 74 72 6f 6c 20 6f 70 20 2a 2f 0a 20  _control op */. 
2b30: 20 20 20 73 77 69 74 63 68 28 20 6f 70 20 29 7b     switch( op ){
2b40: 0a 20 20 20 20 20 20 63 61 73 65 20 31 3a 20 0a  .      case 1: .
2b50: 20 20 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c          op = MUL
2b60: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
2b70: 4c 45 3b 20 0a 20 20 20 20 20 20 20 20 62 72 65  LE; .        bre
2b80: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 32  ak;.      case 2
2b90: 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20 3d 20  : .        op = 
2ba0: 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53  MULTIPLEX_CTRL_S
2bb0: 45 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b 20 0a  ET_CHUNK_SIZE; .
2bc0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
2bd0: 20 20 20 20 20 63 61 73 65 20 33 3a 20 0a 20 20       case 3: .  
2be0: 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c 54 49        op = MULTI
2bf0: 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41  PLEX_CTRL_SET_MA
2c00: 58 5f 43 48 55 4e 4b 53 3b 20 0a 20 20 20 20 20  X_CHUNKS; .     
2c10: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
2c20: 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  default:.       
2c30: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 54   rc = SQLITE_NOT
2c40: 46 4f 55 4e 44 3b 0a 20 20 20 20 20 20 20 20 62  FOUND;.        b
2c50: 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  reak;.    }.  }.
2c60: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
2c70: 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  _OK ){.    rc = 
2c80: 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e  sqlite3_file_con
2c90: 74 72 6f 6c 28 64 62 2c 20 30 2c 20 6f 70 2c 20  trol(db, 0, op, 
2ca0: 26 69 56 61 6c 29 3b 0a 20 20 7d 0a 20 20 73 71  &iVal);.  }.  sq
2cb0: 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72  lite3_result_err
2cc0: 6f 72 5f 63 6f 64 65 28 63 6f 6e 74 65 78 74 2c  or_code(context,
2cd0: 20 72 63 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54   rc);.}../*.** T
2ce0: 68 69 73 20 69 73 20 74 68 65 20 65 6e 74 72 79  his is the entry
2cf0: 20 70 6f 69 6e 74 20 74 6f 20 72 65 67 69 73 74   point to regist
2d00: 65 72 20 74 68 65 20 61 75 74 6f 2d 65 78 74 65  er the auto-exte
2d10: 6e 73 69 6f 6e 20 66 6f 72 20 74 68 65 20 0a 2a  nsion for the .*
2d20: 2a 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74  * multiplex_cont
2d30: 72 6f 6c 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a  rol() function..
2d40: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
2d50: 6c 74 69 70 6c 65 78 46 75 6e 63 49 6e 69 74 28  ltiplexFuncInit(
2d60: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 2c 20  .  sqlite3 *db, 
2d70: 0a 20 20 63 68 61 72 20 2a 2a 70 7a 45 72 72 4d  .  char **pzErrM
2d80: 73 67 2c 20 0a 20 20 63 6f 6e 73 74 20 73 71 6c  sg, .  const sql
2d90: 69 74 65 33 5f 61 70 69 5f 72 6f 75 74 69 6e 65  ite3_api_routine
2da0: 73 20 2a 70 41 70 69 0a 29 7b 0a 20 20 69 6e 74  s *pApi.){.  int
2db0: 20 72 63 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69   rc;.  rc = sqli
2dc0: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
2dd0: 69 6f 6e 28 64 62 2c 20 22 6d 75 6c 74 69 70 6c  ion(db, "multipl
2de0: 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 32 2c 20  ex_control", 2, 
2df0: 53 51 4c 49 54 45 5f 41 4e 59 2c 20 0a 20 20 20  SQLITE_ANY, .   
2e00: 20 20 20 30 2c 20 6d 75 6c 74 69 70 6c 65 78 43     0, multiplexC
2e10: 6f 6e 74 72 6f 6c 46 75 6e 63 2c 20 30 2c 20 30  ontrolFunc, 0, 0
2e20: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
2e30: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20 61  }../*.** Close a
2e40: 20 73 69 6e 67 6c 65 20 73 75 62 2d 66 69 6c 65   single sub-file
2e50: 20 69 6e 20 74 68 65 20 63 6f 6e 6e 65 63 74 69   in the connecti
2e60: 6f 6e 20 67 72 6f 75 70 2e 0a 2a 2f 0a 73 74 61  on group..*/.sta
2e70: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
2e80: 65 78 53 75 62 43 6c 6f 73 65 28 0a 20 20 6d 75  exSubClose(.  mu
2e90: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
2ea0: 72 6f 75 70 2c 0a 20 20 69 6e 74 20 69 43 68 75  roup,.  int iChu
2eb0: 6e 6b 2c 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  nk,.  sqlite3_vf
2ec0: 73 20 2a 70 4f 72 69 67 56 66 73 0a 29 7b 0a 20  s *pOrigVfs.){. 
2ed0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
2ee0: 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70  SubOpen = pGroup
2ef0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
2f00: 70 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  p;.  if( pSubOpe
2f10: 6e 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70 65  n ){.    pSubOpe
2f20: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 43 6c  n->pMethods->xCl
2f30: 6f 73 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20  ose(pSubOpen);. 
2f40: 20 20 20 69 66 28 20 70 4f 72 69 67 56 66 73 20     if( pOrigVfs 
2f50: 29 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c  ) pOrigVfs->xDel
2f60: 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 70 47  ete(pOrigVfs, pG
2f70: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
2f80: 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20 20 73  nk].z, 0);.    s
2f90: 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72 6f  qlite3_free(pGro
2fa0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
2fb0: 5d 2e 70 29 3b 0a 20 20 7d 0a 20 20 73 71 6c 69  ].p);.  }.  sqli
2fc0: 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d  te3_free(pGroup-
2fd0: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
2fe0: 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70 47 72  );.  memset(&pGr
2ff0: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
3000: 6b 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 47  k], 0, sizeof(pG
3010: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3020: 6e 6b 5d 29 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  nk]));.}../*.** 
3030: 44 65 61 6c 6c 6f 63 61 74 65 20 6d 65 6d 6f 72  Deallocate memor
3040: 79 20 68 65 6c 64 20 62 79 20 61 20 6d 75 6c 74  y held by a mult
3050: 69 70 6c 65 78 47 72 6f 75 70 0a 2a 2f 0a 73 74  iplexGroup.*/.st
3060: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
3070: 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74  lexFreeComponent
3080: 73 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  s(multiplexGroup
3090: 20 2a 70 47 72 6f 75 70 29 7b 0a 20 20 69 6e 74   *pGroup){.  int
30a0: 20 69 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69   i;.  for(i=0; i
30b0: 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b 20  <pGroup->nReal; 
30c0: 69 2b 2b 29 7b 20 6d 75 6c 74 69 70 6c 65 78 53  i++){ multiplexS
30d0: 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c 20  ubClose(pGroup, 
30e0: 69 2c 20 30 29 3b 20 7d 0a 20 20 73 71 6c 69 74  i, 0); }.  sqlit
30f0: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d 3e  e3_free(pGroup->
3100: 61 52 65 61 6c 29 3b 0a 20 20 70 47 72 6f 75 70  aReal);.  pGroup
3110: 2d 3e 61 52 65 61 6c 20 3d 20 30 3b 0a 20 20 70  ->aReal = 0;.  p
3120: 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20 30  Group->nReal = 0
3130: 3b 0a 7d 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;.}.../*********
3140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3150: 20 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61 70   VFS Method Wrap
3160: 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  pers ***********
3170: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3180: 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  **/../*.** This 
3190: 69 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65 74  is the xOpen met
31a0: 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68 65  hod used for the
31b0: 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46 53   "multiplex" VFS
31c0: 2e 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66 20  ..**.** Most of 
31d0: 74 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e 65  the work is done
31e0: 20 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79 69   by the underlyi
31f0: 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e  ng original VFS.
3200: 20 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a 2a    This method.**
3210: 20 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74 68   simply links th
3220: 65 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f 20  e new file into 
3230: 74 68 65 20 61 70 70 72 6f 70 72 69 61 74 65 20  the appropriate 
3240: 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 20  multiplex group 
3250: 69 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66 69  if it is a.** fi
3260: 6c 65 20 74 68 61 74 20 6e 65 65 64 73 20 74 6f  le that needs to
3270: 20 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f 0a   be tracked..*/.
3280: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
3290: 70 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c 69  plexOpen(.  sqli
32a0: 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20 20  te3_vfs *pVfs,  
32b0: 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d 75         /* The mu
32c0: 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20  ltiplex VFS */. 
32d0: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61   const char *zNa
32e0: 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 4e  me,         /* N
32f0: 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20 62  ame of file to b
3300: 65 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73 71  e opened */.  sq
3310: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
3320: 6e 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c 6c  n,       /* Fill
3330: 20 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64 65   in this file de
3340: 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69 6e  scriptor */.  in
3350: 74 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20 20  t flags,        
3360: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67           /* Flag
3370: 73 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68 65  s to control the
3380: 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e   opening */.  in
3390: 74 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20 20  t *pOutFlags    
33a0: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67           /* Flag
33b0: 73 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c 74  s showing result
33c0: 73 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a  s of opening */.
33d0: 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  ){.  int rc = SQ
33e0: 4c 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20 20  LITE_OK;        
33f0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73            /* Res
3400: 75 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d 75  ult code */.  mu
3410: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d 75  ltiplexConn *pMu
3420: 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20 20  ltiplexOpen;    
3430: 20 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d 75     /* The new mu
3440: 6c 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65 73  ltiplex file des
3450: 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75 6c  criptor */.  mul
3460: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
3470: 6f 75 70 3b 20 20 20 20 20 20 20 20 20 20 20 20  oup;            
3480: 20 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64 69    /* Correspondi
3490: 6e 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  ng multiplexGrou
34a0: 70 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73 71  p object */.  sq
34b0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
34c0: 4f 70 65 6e 20 3d 20 30 3b 20 20 20 20 20 20 20  Open = 0;       
34d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
34e0: 52 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72 69  Real file descri
34f0: 70 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74 65  ptor */.  sqlite
3500: 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20  3_vfs *pOrigVfs 
3510: 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  = gMultiplex.pOr
3520: 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c  igVfs;   /* Real
3530: 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e   VFS */.  int nN
3540: 61 6d 65 3b 0a 20 20 69 6e 74 20 73 7a 3b 0a 20  ame;.  int sz;. 
3550: 20 63 68 61 72 20 2a 7a 54 6f 46 72 65 65 20 3d   char *zToFree =
3560: 20 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41   0;..  UNUSED_PA
3570: 52 41 4d 45 54 45 52 28 70 56 66 73 29 3b 0a 20  RAMETER(pVfs);. 
3580: 20 6d 65 6d 73 65 74 28 70 43 6f 6e 6e 2c 20 30   memset(pConn, 0
3590: 2c 20 70 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65  , pVfs->szOsFile
35a0: 29 3b 0a 20 20 61 73 73 65 72 74 28 20 7a 4e 61  );.  assert( zNa
35b0: 6d 65 20 7c 7c 20 28 66 6c 61 67 73 20 26 20 53  me || (flags & S
35c0: 51 4c 49 54 45 5f 4f 50 45 4e 5f 44 45 4c 45 54  QLITE_OPEN_DELET
35d0: 45 4f 4e 43 4c 4f 53 45 29 20 29 3b 0a 0a 20 20  EONCLOSE) );..  
35e0: 2f 2a 20 57 65 20 6e 65 65 64 20 74 6f 20 63 72  /* We need to cr
35f0: 65 61 74 65 20 61 20 67 72 6f 75 70 20 73 74 72  eate a group str
3600: 75 63 74 75 72 65 20 61 6e 64 20 6d 61 6e 61 67  ucture and manag
3610: 65 0a 20 20 2a 2a 20 61 63 63 65 73 73 20 74 6f  e.  ** access to
3620: 20 74 68 69 73 20 67 72 6f 75 70 20 6f 66 20 66   this group of f
3630: 69 6c 65 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c  iles..  */.  mul
3640: 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20  tiplexEnter();. 
3650: 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 20   pMultiplexOpen 
3660: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
3670: 2a 29 70 43 6f 6e 6e 3b 0a 0a 20 20 69 66 28 20  *)pConn;..  if( 
3680: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
3690: 0a 20 20 20 20 2f 2a 20 61 6c 6c 6f 63 61 74 65  .    /* allocate
36a0: 20 73 70 61 63 65 20 66 6f 72 20 67 72 6f 75 70   space for group
36b0: 20 2a 2f 0a 20 20 20 20 6e 4e 61 6d 65 20 3d 20   */.    nName = 
36c0: 7a 4e 61 6d 65 20 3f 20 6d 75 6c 74 69 70 6c 65  zName ? multiple
36d0: 78 53 74 72 6c 65 6e 33 30 28 7a 4e 61 6d 65 29  xStrlen30(zName)
36e0: 20 3a 20 30 3b 0a 20 20 20 20 73 7a 20 3d 20 73   : 0;.    sz = s
36f0: 69 7a 65 6f 66 28 6d 75 6c 74 69 70 6c 65 78 47  izeof(multiplexG
3700: 72 6f 75 70 29 20 20 20 20 20 20 20 20 20 20 20  roup)           
3710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3720: 20 20 2f 2a 20 6d 75 6c 74 69 70 6c 65 78 47 72    /* multiplexGr
3730: 6f 75 70 20 2a 2f 0a 20 20 20 20 20 20 20 2b 20  oup */.       + 
3740: 6e 4e 61 6d 65 20 2b 20 31 3b 20 20 20 20 20 20  nName + 1;      
3750: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3770: 20 20 20 2f 2a 20 7a 4e 61 6d 65 20 2a 2f 0a 20     /* zName */. 
3780: 20 20 20 70 47 72 6f 75 70 20 3d 20 73 71 6c 69     pGroup = sqli
3790: 74 65 33 5f 6d 61 6c 6c 6f 63 28 20 73 7a 20 29  te3_malloc( sz )
37a0: 3b 0a 20 20 20 20 69 66 28 20 70 47 72 6f 75 70  ;.    if( pGroup
37b0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20  ==0 ){.      rc 
37c0: 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  = SQLITE_NOMEM;.
37d0: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28      }.  }..  if(
37e0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
37f0: 7b 0a 20 20 20 20 2f 2a 20 61 73 73 69 67 6e 20  {.    /* assign 
3800: 70 6f 69 6e 74 65 72 73 20 74 6f 20 65 78 74 72  pointers to extr
3810: 61 20 73 70 61 63 65 20 61 6c 6c 6f 63 61 74 65  a space allocate
3820: 64 20 2a 2f 0a 20 20 20 20 6d 65 6d 73 65 74 28  d */.    memset(
3830: 70 47 72 6f 75 70 2c 20 30 2c 20 73 7a 29 3b 0a  pGroup, 0, sz);.
3840: 20 20 20 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70      pMultiplexOp
3850: 65 6e 2d 3e 70 47 72 6f 75 70 20 3d 20 70 47 72  en->pGroup = pGr
3860: 6f 75 70 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  oup;.    pGroup-
3870: 3e 62 45 6e 61 62 6c 65 64 20 3d 20 2d 31 3b 0a  >bEnabled = -1;.
3880: 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68      pGroup->szCh
3890: 75 6e 6b 20 3d 20 53 51 4c 49 54 45 5f 4d 55 4c  unk = SQLITE_MUL
38a0: 54 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a  TIPLEX_CHUNK_SIZ
38b0: 45 3b 0a 0a 20 20 20 20 69 66 28 20 7a 4e 61 6d  E;..    if( zNam
38c0: 65 20 29 7b 0a 20 20 20 20 20 20 63 68 61 72 20  e ){.      char 
38d0: 2a 70 20 3d 20 28 63 68 61 72 20 2a 29 26 70 47  *p = (char *)&pG
38e0: 72 6f 75 70 5b 31 5d 3b 0a 20 20 20 20 20 20 69  roup[1];.      i
38f0: 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c 49 54  f( flags & SQLIT
3900: 45 5f 4f 50 45 4e 5f 55 52 49 20 29 7b 0a 20 20  E_OPEN_URI ){.  
3910: 20 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72        const char
3920: 20 2a 7a 43 68 75 6e 6b 53 69 7a 65 3b 0a 20 20   *zChunkSize;.  
3930: 20 20 20 20 20 20 7a 43 68 75 6e 6b 53 69 7a 65        zChunkSize
3940: 20 3d 20 73 71 6c 69 74 65 33 5f 75 72 69 5f 70   = sqlite3_uri_p
3950: 61 72 61 6d 65 74 65 72 28 7a 4e 61 6d 65 2c 20  arameter(zName, 
3960: 22 63 68 75 6e 6b 73 69 7a 65 22 29 3b 0a 20 20  "chunksize");.  
3970: 20 20 20 20 20 20 69 66 28 20 7a 43 68 75 6e 6b        if( zChunk
3980: 53 69 7a 65 20 29 7b 0a 20 20 20 20 20 20 20 20  Size ){.        
3990: 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 6e    unsigned int n
39a0: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 20 20   = 0;.          
39b0: 69 6e 74 20 69 3b 0a 20 20 20 20 20 20 20 20 20  int i;.         
39c0: 20 66 6f 72 28 69 3d 30 3b 20 7a 43 68 75 6e 6b   for(i=0; zChunk
39d0: 53 69 7a 65 5b 69 5d 3e 3d 27 30 27 20 26 26 20  Size[i]>='0' && 
39e0: 7a 43 68 75 6e 6b 53 69 7a 65 5b 69 5d 3c 3d 27  zChunkSize[i]<='
39f0: 39 27 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20  9'; i++){.      
3a00: 20 20 20 20 20 20 6e 20 3d 20 6e 2a 31 30 20 2b        n = n*10 +
3a10: 20 7a 43 68 75 6e 6b 53 69 7a 65 5b 69 5d 20 2d   zChunkSize[i] -
3a20: 20 27 30 27 3b 0a 20 20 20 20 20 20 20 20 20 20   '0';.          
3a30: 7d 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20  }.          if( 
3a40: 6e 3e 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20  n>0 ){.         
3a50: 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75     pGroup->szChu
3a60: 6e 6b 20 3d 20 28 6e 2b 30 78 66 66 66 66 29 26  nk = (n+0xffff)&
3a70: 7e 30 78 66 66 66 66 3b 0a 20 20 20 20 20 20 20  ~0xffff;.       
3a80: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
3a90: 20 20 20 20 20 20 2f 2a 20 41 20 7a 65 72 6f 20        /* A zero 
3aa0: 6f 72 20 6e 65 67 61 74 69 76 65 20 63 68 75 6e  or negative chun
3ab0: 6b 73 69 7a 65 20 64 69 73 61 62 6c 65 64 20 74  ksize disabled t
3ac0: 68 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 2a  he multiplexor *
3ad0: 2f 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 47  /.            pG
3ae0: 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 3d  roup->bEnabled =
3af0: 20 30 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a   0;.          }.
3b00: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
3b10: 7d 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e  }.      pGroup->
3b20: 7a 4e 61 6d 65 20 3d 20 70 3b 0a 20 20 20 20 20  zName = p;.     
3b30: 20 6d 65 6d 63 70 79 28 70 47 72 6f 75 70 2d 3e   memcpy(pGroup->
3b40: 7a 4e 61 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e  zName, zName, nN
3b50: 61 6d 65 2b 31 29 3b 0a 20 20 20 20 20 20 70 47  ame+1);.      pG
3b60: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 20 3d 20 6e 4e  roup->nName = nN
3b70: 61 6d 65 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70  ame;.    }.    p
3b80: 47 72 6f 75 70 2d 3e 66 6c 61 67 73 20 3d 20 66  Group->flags = f
3b90: 6c 61 67 73 3b 0a 20 20 20 20 72 63 20 3d 20 6d  lags;.    rc = m
3ba0: 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e  ultiplexSubFilen
3bb0: 61 6d 65 28 70 47 72 6f 75 70 2c 20 31 29 3b 0a  ame(pGroup, 1);.
3bc0: 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49      if( rc==SQLI
3bd0: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70  TE_OK ){.      p
3be0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
3bf0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
3c00: 70 2c 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46  p, 0, &rc, pOutF
3c10: 6c 61 67 73 29 3b 0a 20 20 20 20 7d 0a 20 20 20  lags);.    }.   
3c20: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
3c30: 0a 20 20 20 20 20 20 69 6e 74 20 65 78 69 73 74  .      int exist
3c40: 73 2c 20 72 63 32 2c 20 72 63 33 3b 0a 20 20 20  s, rc2, rc3;.   
3c50: 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34     sqlite3_int64
3c60: 20 73 7a 3b 0a 0a 20 20 20 20 20 20 72 63 32 20   sz;..      rc2 
3c70: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
3c80: 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28  hods->xFileSize(
3c90: 70 53 75 62 4f 70 65 6e 2c 20 26 73 7a 29 3b 0a  pSubOpen, &sz);.
3ca0: 20 20 20 20 20 20 69 66 28 20 72 63 32 3d 3d 53        if( rc2==S
3cb0: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 7a 4e 61 6d  QLITE_OK && zNam
3cc0: 65 20 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20  e ){.        /* 
3cd0: 49 66 20 74 68 65 20 66 69 72 73 74 20 6f 76 65  If the first ove
3ce0: 72 66 6c 6f 77 20 66 69 6c 65 20 65 78 69 73 74  rflow file exist
3cf0: 73 20 61 6e 64 20 69 66 20 74 68 65 20 73 69 7a  s and if the siz
3d00: 65 20 6f 66 20 74 68 65 20 6d 61 69 6e 20 66 69  e of the main fi
3d10: 6c 65 0a 20 20 20 20 20 20 20 20 2a 2a 20 69 73  le.        ** is
3d20: 20 64 69 66 66 65 72 65 6e 74 20 66 72 6f 6d 20   different from 
3d30: 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 2c 20  the chunk size, 
3d40: 74 68 61 74 20 6d 65 61 6e 73 20 74 68 65 20 63  that means the c
3d50: 68 75 6e 6b 20 73 69 7a 65 20 69 73 20 73 65 74  hunk size is set
3d60: 0a 20 20 20 20 20 20 20 20 2a 2a 20 73 65 74 20  .        ** set 
3d70: 69 6e 63 6f 72 72 65 63 74 6c 79 2e 20 20 53 6f  incorrectly.  So
3d80: 20 66 69 78 20 69 74 2e 0a 20 20 20 20 20 20 20   fix it..       
3d90: 20 2a 2a 0a 20 20 20 20 20 20 20 20 2a 2a 20 4f   **.        ** O
3da0: 72 2c 20 69 66 20 74 68 65 20 66 69 72 73 74 20  r, if the first 
3db0: 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20 64 6f  overflow file do
3dc0: 65 73 20 6e 6f 74 20 65 78 69 73 74 20 61 6e 64  es not exist and
3dd0: 20 74 68 65 20 6d 61 69 6e 20 66 69 6c 65 20 69   the main file i
3de0: 73 0a 20 20 20 20 20 20 20 20 2a 2a 20 6c 61 72  s.        ** lar
3df0: 67 65 72 20 74 68 61 6e 20 74 68 65 20 63 68 75  ger than the chu
3e00: 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74 20 6d 65  nk size, that me
3e10: 61 6e 73 20 74 68 65 20 63 68 75 6e 6b 20 73 69  ans the chunk si
3e20: 7a 65 20 69 73 20 74 6f 6f 20 73 6d 61 6c 6c 2e  ze is too small.
3e30: 0a 20 20 20 20 20 20 20 20 2a 2a 20 42 75 74 20  .        ** But 
3e40: 77 65 20 68 61 76 65 20 6e 6f 20 77 61 79 20 6f  we have no way o
3e50: 66 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68  f determining th
3e60: 65 20 69 6e 74 65 6e 64 65 64 20 63 68 75 6e 6b  e intended chunk
3e70: 20 73 69 7a 65 2c 20 73 6f 20 0a 20 20 20 20 20   size, so .     
3e80: 20 20 20 2a 2a 20 6a 75 73 74 20 64 69 73 61 62     ** just disab
3e90: 6c 65 20 74 68 65 20 6d 75 6c 74 69 70 6c 65 78  le the multiplex
3ea0: 6f 72 20 61 6c 6c 20 74 6f 67 65 74 68 72 65 2e  or all togethre.
3eb0: 0a 20 20 20 20 20 20 20 20 2a 2f 0a 20 20 20 20  .        */.    
3ec0: 20 20 20 20 72 63 33 20 3d 20 70 4f 72 69 67 56      rc3 = pOrigV
3ed0: 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f 72 69  fs->xAccess(pOri
3ee0: 67 56 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61 52  gVfs, pGroup->aR
3ef0: 65 61 6c 5b 31 5d 2e 7a 2c 0a 20 20 20 20 20 20  eal[1].z,.      
3f00: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 41 43 43        SQLITE_ACC
3f10: 45 53 53 5f 45 58 49 53 54 53 2c 20 26 65 78 69  ESS_EXISTS, &exi
3f20: 73 74 73 29 3b 0a 20 20 20 20 20 20 20 20 69 66  sts);.        if
3f30: 28 20 72 63 33 3d 3d 53 51 4c 49 54 45 5f 4f 4b  ( rc3==SQLITE_OK
3f40: 20 26 26 20 65 78 69 73 74 73 20 26 26 20 73 7a   && exists && sz
3f50: 3d 3d 28 73 7a 26 30 78 66 66 66 66 30 30 30 30  ==(sz&0xffff0000
3f60: 29 20 26 26 20 73 7a 3e 30 0a 20 20 20 20 20 20  ) && sz>0.      
3f70: 20 20 20 20 20 20 26 26 20 73 7a 21 3d 70 47 72        && sz!=pGr
3f80: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 29 7b 0a  oup->szChunk ){.
3f90: 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70            pGroup
3fa0: 2d 3e 73 7a 43 68 75 6e 6b 20 3d 20 73 7a 3b 0a  ->szChunk = sz;.
3fb0: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 20 69 66          }else if
3fc0: 28 20 72 63 33 3d 3d 53 51 4c 49 54 45 5f 4f 4b  ( rc3==SQLITE_OK
3fd0: 20 26 26 20 21 65 78 69 73 74 73 20 26 26 20 73   && !exists && s
3fe0: 7a 3e 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  z>pGroup->szChun
3ff0: 6b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70  k ){.          p
4000: 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20  Group->bEnabled 
4010: 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  = 0;.        }. 
4020: 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 69 66       }..      if
4030: 28 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  ( pSubOpen->pMet
4040: 68 6f 64 73 2d 3e 69 56 65 72 73 69 6f 6e 3d 3d  hods->iVersion==
4050: 31 20 29 7b 0a 20 20 20 20 20 20 20 20 70 4d 75  1 ){.        pMu
4060: 6c 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73  ltiplexOpen->bas
4070: 65 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d  e.pMethods = &gM
4080: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
4090: 6f 64 73 56 31 3b 0a 20 20 20 20 20 20 7d 65 6c  odsV1;.      }el
40a0: 73 65 7b 0a 20 20 20 20 20 20 20 20 70 4d 75 6c  se{.        pMul
40b0: 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73 65  tiplexOpen->base
40c0: 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d 75  .pMethods = &gMu
40d0: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
40e0: 64 73 56 32 3b 0a 20 20 20 20 20 20 7d 0a 20 20  dsV2;.      }.  
40f0: 20 20 20 20 2f 2a 20 70 6c 61 63 65 20 74 68 69      /* place thi
4100: 73 20 67 72 6f 75 70 20 61 74 20 74 68 65 20 68  s group at the h
4110: 65 61 64 20 6f 66 20 6f 75 72 20 6c 69 73 74 20  ead of our list 
4120: 2a 2f 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d  */.      pGroup-
4130: 3e 70 4e 65 78 74 20 3d 20 67 4d 75 6c 74 69 70  >pNext = gMultip
4140: 6c 65 78 2e 70 47 72 6f 75 70 73 3b 0a 20 20 20  lex.pGroups;.   
4150: 20 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65     if( gMultiple
4160: 78 2e 70 47 72 6f 75 70 73 20 29 20 67 4d 75 6c  x.pGroups ) gMul
4170: 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 2d 3e  tiplex.pGroups->
4180: 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70 3b 0a  pPrev = pGroup;.
4190: 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65 78        gMultiplex
41a0: 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f 75  .pGroups = pGrou
41b0: 70 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  p;.    }else{.  
41c0: 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46 72 65      multiplexFre
41d0: 65 43 6f 6d 70 6f 6e 65 6e 74 73 28 70 47 72 6f  eComponents(pGro
41e0: 75 70 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74  up);.      sqlit
41f0: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 29 3b  e3_free(pGroup);
4200: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c  .    }.  }.  mul
4210: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
4220: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 7a 54   sqlite3_free(zT
4230: 6f 46 72 65 65 29 3b 0a 20 20 72 65 74 75 72 6e  oFree);.  return
4240: 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68   rc;.}../*.** Th
4250: 69 73 20 69 73 20 74 68 65 20 78 44 65 6c 65 74  is is the xDelet
4260: 65 20 6d 65 74 68 6f 64 20 75 73 65 64 20 66 6f  e method used fo
4270: 72 20 74 68 65 20 22 6d 75 6c 74 69 70 6c 65 78  r the "multiplex
4280: 22 20 56 46 53 2e 0a 2a 2a 20 49 74 20 61 74 74  " VFS..** It att
4290: 65 6d 70 74 73 20 74 6f 20 64 65 6c 65 74 65 20  empts to delete 
42a0: 74 68 65 20 66 69 6c 65 6e 61 6d 65 20 73 70 65  the filename spe
42b0: 63 69 66 69 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  cified..*/.stati
42c0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44  c int multiplexD
42d0: 65 6c 65 74 65 28 0a 20 20 73 71 6c 69 74 65 33  elete(.  sqlite3
42e0: 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20 20 20  _vfs *pVfs,     
42f0: 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69      /* The multi
4300: 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 63 6f  plex VFS */.  co
4310: 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c  nst char *zName,
4320: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
4330: 20 6f 66 20 66 69 6c 65 20 74 6f 20 64 65 6c 65   of file to dele
4340: 74 65 20 2a 2f 0a 20 20 69 6e 74 20 73 79 6e 63  te */.  int sync
4350: 44 69 72 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33  Dir.){.  sqlite3
4360: 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d  _vfs *pOrigVfs =
4370: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
4380: 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20  gVfs;   /* Real 
4390: 56 46 53 20 2a 2f 0a 20 20 72 65 74 75 72 6e 20  VFS */.  return 
43a0: 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c 65 74  pOrigVfs->xDelet
43b0: 65 28 70 4f 72 69 67 56 66 73 2c 20 7a 4e 61 6d  e(pOrigVfs, zNam
43c0: 65 2c 20 73 79 6e 63 44 69 72 29 3b 0a 7d 0a 0a  e, syncDir);.}..
43d0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
43e0: 70 6c 65 78 41 63 63 65 73 73 28 73 71 6c 69 74  plexAccess(sqlit
43f0: 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e 73 74  e3_vfs *a, const
4400: 20 63 68 61 72 20 2a 62 2c 20 69 6e 74 20 63 2c   char *b, int c,
4410: 20 69 6e 74 20 2a 64 29 7b 0a 20 20 72 65 74 75   int *d){.  retu
4420: 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  rn gMultiplex.pO
4430: 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73 28  rigVfs->xAccess(
4440: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4450: 56 66 73 2c 20 62 2c 20 63 2c 20 64 29 3b 0a 7d  Vfs, b, c, d);.}
4460: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
4470: 69 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61 6d  iplexFullPathnam
4480: 65 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  e(sqlite3_vfs *a
4490: 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 62 2c  , const char *b,
44a0: 20 69 6e 74 20 63 2c 20 63 68 61 72 20 2a 64 29   int c, char *d)
44b0: 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74  {.  return gMult
44c0: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e  iplex.pOrigVfs->
44d0: 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 67 4d  xFullPathname(gM
44e0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
44f0: 73 2c 20 62 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73  s, b, c, d);.}.s
4500: 74 61 74 69 63 20 76 6f 69 64 20 2a 6d 75 6c 74  tatic void *mult
4510: 69 70 6c 65 78 44 6c 4f 70 65 6e 28 73 71 6c 69  iplexDlOpen(sqli
4520: 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e 73  te3_vfs *a, cons
4530: 74 20 63 68 61 72 20 2a 62 29 7b 0a 20 20 72 65  t char *b){.  re
4540: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
4550: 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 4f 70 65  pOrigVfs->xDlOpe
4560: 6e 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  n(gMultiplex.pOr
4570: 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61  igVfs, b);.}.sta
4580: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
4590: 65 78 44 6c 45 72 72 6f 72 28 73 71 6c 69 74 65  exDlError(sqlite
45a0: 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 2c  3_vfs *a, int b,
45b0: 20 63 68 61 72 20 2a 63 29 7b 0a 20 20 67 4d 75   char *c){.  gMu
45c0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
45d0: 2d 3e 78 44 6c 45 72 72 6f 72 28 67 4d 75 6c 74  ->xDlError(gMult
45e0: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
45f0: 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20  b, c);.}.static 
4600: 76 6f 69 64 20 28 2a 6d 75 6c 74 69 70 6c 65 78  void (*multiplex
4610: 44 6c 53 79 6d 28 73 71 6c 69 74 65 33 5f 76 66  DlSym(sqlite3_vf
4620: 73 20 2a 61 2c 20 76 6f 69 64 20 2a 62 2c 20 63  s *a, void *b, c
4630: 6f 6e 73 74 20 63 68 61 72 20 2a 63 29 29 28 76  onst char *c))(v
4640: 6f 69 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67  oid){.  return g
4650: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4660: 66 73 2d 3e 78 44 6c 53 79 6d 28 67 4d 75 6c 74  fs->xDlSym(gMult
4670: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
4680: 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20  b, c);.}.static 
4690: 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c  void multiplexDl
46a0: 43 6c 6f 73 65 28 73 71 6c 69 74 65 33 5f 76 66  Close(sqlite3_vf
46b0: 73 20 2a 61 2c 20 76 6f 69 64 20 2a 62 29 7b 0a  s *a, void *b){.
46c0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72    gMultiplex.pOr
46d0: 69 67 56 66 73 2d 3e 78 44 6c 43 6c 6f 73 65 28  igVfs->xDlClose(
46e0: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
46f0: 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69  Vfs, b);.}.stati
4700: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 52  c int multiplexR
4710: 61 6e 64 6f 6d 6e 65 73 73 28 73 71 6c 69 74 65  andomness(sqlite
4720: 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 2c  3_vfs *a, int b,
4730: 20 63 68 61 72 20 2a 63 29 7b 0a 20 20 72 65 74   char *c){.  ret
4740: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
4750: 4f 72 69 67 56 66 73 2d 3e 78 52 61 6e 64 6f 6d  OrigVfs->xRandom
4760: 6e 65 73 73 28 67 4d 75 6c 74 69 70 6c 65 78 2e  ness(gMultiplex.
4770: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
4780: 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  .}.static int mu
4790: 6c 74 69 70 6c 65 78 53 6c 65 65 70 28 73 71 6c  ltiplexSleep(sql
47a0: 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74  ite3_vfs *a, int
47b0: 20 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d   b){.  return gM
47c0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
47d0: 73 2d 3e 78 53 6c 65 65 70 28 67 4d 75 6c 74 69  s->xSleep(gMulti
47e0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
47f0: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20  );.}.static int 
4800: 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e 74  multiplexCurrent
4810: 54 69 6d 65 28 73 71 6c 69 74 65 33 5f 76 66 73  Time(sqlite3_vfs
4820: 20 2a 61 2c 20 64 6f 75 62 6c 65 20 2a 62 29 7b   *a, double *b){
4830: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
4840: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
4850: 43 75 72 72 65 6e 74 54 69 6d 65 28 67 4d 75 6c  CurrentTime(gMul
4860: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
4870: 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e   b);.}.static in
4880: 74 20 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c 61  t multiplexGetLa
4890: 73 74 45 72 72 6f 72 28 73 71 6c 69 74 65 33 5f  stError(sqlite3_
48a0: 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63  vfs *a, int b, c
48b0: 68 61 72 20 2a 63 29 7b 0a 20 20 72 65 74 75 72  har *c){.  retur
48c0: 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  n gMultiplex.pOr
48d0: 69 67 56 66 73 2d 3e 78 47 65 74 4c 61 73 74 45  igVfs->xGetLastE
48e0: 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65 78 2e  rror(gMultiplex.
48f0: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
4900: 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  .}.static int mu
4910: 6c 74 69 70 6c 65 78 43 75 72 72 65 6e 74 54 69  ltiplexCurrentTi
4920: 6d 65 49 6e 74 36 34 28 73 71 6c 69 74 65 33 5f  meInt64(sqlite3_
4930: 76 66 73 20 2a 61 2c 20 73 71 6c 69 74 65 33 5f  vfs *a, sqlite3_
4940: 69 6e 74 36 34 20 2a 62 29 7b 0a 20 20 72 65 74  int64 *b){.  ret
4950: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
4960: 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72 65 6e  OrigVfs->xCurren
4970: 74 54 69 6d 65 49 6e 74 36 34 28 67 4d 75 6c 74  tTimeInt64(gMult
4980: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
4990: 62 29 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  b);.}../********
49a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
49b0: 20 49 2f 4f 20 4d 65 74 68 6f 64 20 57 72 61 70   I/O Method Wrap
49c0: 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  pers ***********
49d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
49e0: 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 78 43 6c 6f 73 65  ****/../* xClose
49f0: 20 72 65 71 75 65 73 74 73 20 67 65 74 20 70 61   requests get pa
4a00: 73 73 65 64 20 74 68 72 6f 75 67 68 20 74 6f 20  ssed through to 
4a10: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
4a20: 2e 0a 2a 2a 20 57 65 20 6c 6f 6f 70 20 6f 76 65  ..** We loop ove
4a30: 72 20 61 6c 6c 20 6f 70 65 6e 20 63 68 75 6e 6b  r all open chunk
4a40: 20 68 61 6e 64 6c 65 73 20 61 6e 64 20 63 6c 6f   handles and clo
4a50: 73 65 20 74 68 65 6d 2e 0a 2a 2a 20 54 68 65 20  se them..** The 
4a60: 67 72 6f 75 70 20 73 74 72 75 63 74 75 72 65 20  group structure 
4a70: 66 6f 72 20 74 68 69 73 20 66 69 6c 65 20 69 73  for this file is
4a80: 20 75 6e 6c 69 6e 6b 65 64 20 66 72 6f 6d 20 0a   unlinked from .
4a90: 2a 2a 20 6f 75 72 20 6c 69 73 74 20 6f 66 20 67  ** our list of g
4aa0: 72 6f 75 70 73 20 61 6e 64 20 66 72 65 65 64 2e  roups and freed.
4ab0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
4ac0: 75 6c 74 69 70 6c 65 78 43 6c 6f 73 65 28 73 71  ultiplexClose(sq
4ad0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
4ae0: 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  n){.  multiplexC
4af0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
4b00: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
4b10: 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70    multiplexGroup
4b20: 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47   *pGroup = p->pG
4b30: 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d  roup;.  int rc =
4b40: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75   SQLITE_OK;.  mu
4b50: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
4b60: 20 20 6d 75 6c 74 69 70 6c 65 78 46 72 65 65 43    multiplexFreeC
4b70: 6f 6d 70 6f 6e 65 6e 74 73 28 70 47 72 6f 75 70  omponents(pGroup
4b80: 29 3b 0a 20 20 2f 2a 20 72 65 6d 6f 76 65 20 66  );.  /* remove f
4b90: 72 6f 6d 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20  rom linked list 
4ba0: 2a 2f 0a 20 20 69 66 28 20 70 47 72 6f 75 70 2d  */.  if( pGroup-
4bb0: 3e 70 4e 65 78 74 20 29 20 70 47 72 6f 75 70 2d  >pNext ) pGroup-
4bc0: 3e 70 4e 65 78 74 2d 3e 70 50 72 65 76 20 3d 20  >pNext->pPrev = 
4bd0: 70 47 72 6f 75 70 2d 3e 70 50 72 65 76 3b 0a 20  pGroup->pPrev;. 
4be0: 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 70 50 72   if( pGroup->pPr
4bf0: 65 76 20 29 7b 0a 20 20 20 20 70 47 72 6f 75 70  ev ){.    pGroup
4c00: 2d 3e 70 50 72 65 76 2d 3e 70 4e 65 78 74 20 3d  ->pPrev->pNext =
4c10: 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a   pGroup->pNext;.
4c20: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 67 4d 75    }else{.    gMu
4c30: 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20  ltiplex.pGroups 
4c40: 3d 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74 3b  = pGroup->pNext;
4c50: 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 66  .  }.  sqlite3_f
4c60: 72 65 65 28 70 47 72 6f 75 70 29 3b 0a 20 20 6d  ree(pGroup);.  m
4c70: 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b  ultiplexLeave();
4c80: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
4c90: 0a 2f 2a 20 50 61 73 73 20 78 52 65 61 64 20 72  ./* Pass xRead r
4ca0: 65 71 75 65 73 74 73 20 74 68 72 75 20 74 6f 20  equests thru to 
4cb0: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
4cc0: 20 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72 6d   after.** determ
4cd0: 69 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65 63  ining the correc
4ce0: 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72 61  t chunk to opera
4cf0: 74 65 20 6f 6e 2e 0a 2a 2a 20 42 72 65 61 6b 20  te on..** Break 
4d00: 75 70 20 72 65 61 64 73 20 61 63 72 6f 73 73 20  up reads across 
4d10: 63 68 75 6e 6b 20 62 6f 75 6e 64 61 72 69 65 73  chunk boundaries
4d20: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
4d30: 6d 75 6c 74 69 70 6c 65 78 52 65 61 64 28 0a 20  multiplexRead(. 
4d40: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
4d50: 43 6f 6e 6e 2c 0a 20 20 76 6f 69 64 20 2a 70 42  Conn,.  void *pB
4d60: 75 66 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c 0a  uf,.  int iAmt,.
4d70: 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20    sqlite3_int64 
4d80: 69 4f 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74 69  iOfst.){.  multi
4d90: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
4da0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
4db0: 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  onn;.  multiplex
4dc0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20  Group *pGroup = 
4dd0: 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74  p->pGroup;.  int
4de0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
4df0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
4e00: 72 28 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f  r();.  if( !pGro
4e10: 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a  up->bEnabled ){.
4e20: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
4e30: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
4e40: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
4e50: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
4e60: 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75  LL);.    if( pSu
4e70: 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20  bOpen==0 ){.    
4e80: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f    rc = SQLITE_IO
4e90: 45 52 52 5f 52 45 41 44 3b 0a 20 20 20 20 7d 65  ERR_READ;.    }e
4ea0: 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  lse{.      rc = 
4eb0: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
4ec0: 64 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70  ds->xRead(pSubOp
4ed0: 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 20  en, pBuf, iAmt, 
4ee0: 69 4f 66 73 74 29 3b 0a 20 20 20 20 7d 0a 20 20  iOfst);.    }.  
4ef0: 7d 65 6c 73 65 7b 0a 20 20 20 20 77 68 69 6c 65  }else{.    while
4f00: 28 20 69 41 6d 74 20 3e 20 30 20 29 7b 0a 20 20  ( iAmt > 0 ){.  
4f10: 20 20 20 20 69 6e 74 20 69 20 3d 20 28 69 6e 74      int i = (int
4f20: 29 28 69 4f 66 73 74 20 2f 20 70 47 72 6f 75 70  )(iOfst / pGroup
4f30: 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20  ->szChunk);.    
4f40: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
4f50: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
4f60: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
4f70: 75 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, i, &rc, NULL
4f80: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70 53 75  );.      if( pSu
4f90: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20 20  bOpen ){.       
4fa0: 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28 28 69   int extra = ((i
4fb0: 6e 74 29 28 69 4f 66 73 74 20 25 20 70 47 72 6f  nt)(iOfst % pGro
4fc0: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20 2b 20 69  up->szChunk) + i
4fd0: 41 6d 74 29 20 2d 20 70 47 72 6f 75 70 2d 3e 73  Amt) - pGroup->s
4fe0: 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20 20 20  zChunk;.        
4ff0: 69 66 28 20 65 78 74 72 61 3c 30 20 29 20 65 78  if( extra<0 ) ex
5000: 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  tra = 0;.       
5010: 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61 3b 0a   iAmt -= extra;.
5020: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
5030: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
5040: 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65 6e 2c  >xRead(pSubOpen,
5050: 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20 20 20   pBuf, iAmt,.   
5060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5080: 20 20 20 20 69 4f 66 73 74 20 25 20 70 47 72 6f      iOfst % pGro
5090: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
50a0: 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51        if( rc!=SQ
50b0: 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b 3b  LITE_OK ) break;
50c0: 0a 20 20 20 20 20 20 20 20 70 42 75 66 20 3d 20  .        pBuf = 
50d0: 28 63 68 61 72 20 2a 29 70 42 75 66 20 2b 20 69  (char *)pBuf + i
50e0: 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 4f 66  Amt;.        iOf
50f0: 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20 20 20  st += iAmt;.    
5100: 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74 72 61      iAmt = extra
5110: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
5120: 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49         rc = SQLI
5130: 54 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b 0a 20  TE_IOERR_READ;. 
5140: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
5150: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
5160: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
5170: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
5180: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 57 72 69  .}../* Pass xWri
5190: 74 65 20 72 65 71 75 65 73 74 73 20 74 68 72 75  te requests thru
51a0: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
51b0: 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64 65   VFS after.** de
51c0: 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f  termining the co
51d0: 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f  rrect chunk to o
51e0: 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20 42 72  perate on..** Br
51f0: 65 61 6b 20 75 70 20 77 72 69 74 65 73 20 61 63  eak up writes ac
5200: 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f 75 6e 64  ross chunk bound
5210: 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  aries..*/.static
5220: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 57 72   int multiplexWr
5230: 69 74 65 28 0a 20 20 73 71 6c 69 74 65 33 5f 66  ite(.  sqlite3_f
5240: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20 20 63 6f  ile *pConn,.  co
5250: 6e 73 74 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a  nst void *pBuf,.
5260: 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71    int iAmt,.  sq
5270: 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73  lite3_int64 iOfs
5280: 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t.){.  multiplex
5290: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
52a0: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
52b0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
52c0: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
52d0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
52e0: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d  = SQLITE_OK;.  m
52f0: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
5300: 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e  .  if( !pGroup->
5310: 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20  bEnabled ){.    
5320: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
5330: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
5340: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
5350: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b  , 0, &rc, NULL);
5360: 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65  .    if( pSubOpe
5370: 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63  n==0 ){.      rc
5380: 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f   = SQLITE_IOERR_
5390: 57 52 49 54 45 3b 0a 20 20 20 20 7d 65 6c 73 65  WRITE;.    }else
53a0: 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75  {.      rc = pSu
53b0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
53c0: 3e 78 57 72 69 74 65 28 70 53 75 62 4f 70 65 6e  >xWrite(pSubOpen
53d0: 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 20 69 4f  , pBuf, iAmt, iO
53e0: 66 73 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65  fst);.    }.  }e
53f0: 6c 73 65 7b 0a 20 20 20 20 77 68 69 6c 65 28 20  lse{.    while( 
5400: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
5410: 20 69 41 6d 74 3e 30 20 29 7b 0a 20 20 20 20 20   iAmt>0 ){.     
5420: 20 69 6e 74 20 69 20 3d 20 28 69 6e 74 29 28 69   int i = (int)(i
5430: 4f 66 73 74 20 2f 20 70 47 72 6f 75 70 2d 3e 73  Ofst / pGroup->s
5440: 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 73  zChunk);.      s
5450: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
5460: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
5470: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
5480: 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   i, &rc, NULL);.
5490: 20 20 20 20 20 20 69 66 28 20 70 53 75 62 4f 70        if( pSubOp
54a0: 65 6e 20 29 7b 0a 20 20 20 20 20 20 20 20 69 6e  en ){.        in
54b0: 74 20 65 78 74 72 61 20 3d 20 28 28 69 6e 74 29  t extra = ((int)
54c0: 28 69 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d  (iOfst % pGroup-
54d0: 3e 73 7a 43 68 75 6e 6b 29 20 2b 20 69 41 6d 74  >szChunk) + iAmt
54e0: 29 20 2d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ) -.            
54f0: 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e          pGroup->
5500: 73 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20 20  szChunk;.       
5510: 20 69 66 28 20 65 78 74 72 61 3c 30 20 29 20 65   if( extra<0 ) e
5520: 78 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20 20  xtra = 0;.      
5530: 20 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61 3b    iAmt -= extra;
5540: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53  .        rc = pS
5550: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
5560: 2d 3e 78 57 72 69 74 65 28 70 53 75 62 4f 70 65  ->xWrite(pSubOpe
5570: 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20  n, pBuf, iAmt,. 
5580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
55a0: 20 20 20 20 20 20 20 69 4f 66 73 74 20 25 20 70         iOfst % p
55b0: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b  Group->szChunk);
55c0: 0a 20 20 20 20 20 20 20 20 70 42 75 66 20 3d 20  .        pBuf = 
55d0: 28 63 68 61 72 20 2a 29 70 42 75 66 20 2b 20 69  (char *)pBuf + i
55e0: 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 4f 66  Amt;.        iOf
55f0: 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20 20 20  st += iAmt;.    
5600: 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74 72 61      iAmt = extra
5610: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  ;.      }.    }.
5620: 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c    }.  multiplexL
5630: 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e  eave();.  return
5640: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
5650: 78 54 72 75 6e 63 61 74 65 20 72 65 71 75 65 73  xTruncate reques
5660: 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f  ts thru to the o
5670: 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65  riginal VFS afte
5680: 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67  r.** determining
5690: 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68 75   the correct chu
56a0: 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e  nk to operate on
56b0: 2e 20 20 44 65 6c 65 74 65 20 61 6e 79 0a 2a 2a  .  Delete any.**
56c0: 20 63 68 75 6e 6b 73 20 61 62 6f 76 65 20 74 68   chunks above th
56d0: 65 20 74 72 75 6e 63 61 74 65 20 6d 61 72 6b 2e  e truncate mark.
56e0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
56f0: 75 6c 74 69 70 6c 65 78 54 72 75 6e 63 61 74 65  ultiplexTruncate
5700: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
5710: 43 6f 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69 6e  Conn, sqlite3_in
5720: 74 36 34 20 73 69 7a 65 29 7b 0a 20 20 6d 75 6c  t64 size){.  mul
5730: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
5740: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
5750: 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c  pConn;.  multipl
5760: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20  exGroup *pGroup 
5770: 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69  = p->pGroup;.  i
5780: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
5790: 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  K;.  multiplexEn
57a0: 74 65 72 28 29 3b 0a 20 20 69 66 28 20 21 70 47  ter();.  if( !pG
57b0: 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 29  roup->bEnabled )
57c0: 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69  {.    sqlite3_fi
57d0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
57e0: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
57f0: 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20  pGroup, 0, &rc, 
5800: 4e 55 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20 70  NULL);.    if( p
5810: 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20  SubOpen==0 ){.  
5820: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
5830: 49 4f 45 52 52 5f 54 52 55 4e 43 41 54 45 3b 0a  IOERR_TRUNCATE;.
5840: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
5850: 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e   rc = pSubOpen->
5860: 70 4d 65 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63  pMethods->xTrunc
5870: 61 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 73 69  ate(pSubOpen, si
5880: 7a 65 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c  ze);.    }.  }el
5890: 73 65 20 69 66 28 20 28 70 47 72 6f 75 70 2d 3e  se if( (pGroup->
58a0: 66 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f  flags & SQLITE_O
58b0: 50 45 4e 5f 4d 41 49 4e 5f 44 42 29 3d 3d 30 20  PEN_MAIN_DB)==0 
58c0: 29 7b 0a 20 20 20 20 69 6e 74 20 72 63 32 3b 0a  ){.    int rc2;.
58d0: 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 73      int i;.    s
58e0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
58f0: 62 4f 70 65 6e 3b 0a 20 20 20 20 73 71 6c 69 74  bOpen;.    sqlit
5900: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
5910: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f   = gMultiplex.pO
5920: 72 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61  rigVfs;   /* Rea
5930: 6c 20 56 46 53 20 2a 2f 0a 20 20 20 20 2f 2a 20  l VFS */.    /* 
5940: 64 65 6c 65 74 65 20 74 68 65 20 63 68 75 6e 6b  delete the chunk
5950: 73 20 61 62 6f 76 65 20 74 68 65 20 74 72 75 6e  s above the trun
5960: 63 61 74 65 20 6c 69 6d 69 74 20 2a 2f 0a 20 20  cate limit */.  
5970: 20 20 66 6f 72 28 69 3d 28 69 6e 74 29 28 73 69    for(i=(int)(si
5980: 7a 65 20 2f 20 70 47 72 6f 75 70 2d 3e 73 7a 43  ze / pGroup->szC
5990: 68 75 6e 6b 29 2b 31 3b 20 69 3c 70 47 72 6f 75  hunk)+1; i<pGrou
59a0: 70 2d 3e 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a  p->nReal; i++){.
59b0: 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 53        multiplexS
59c0: 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c 20  ubClose(pGroup, 
59d0: 69 2c 20 70 4f 72 69 67 56 66 73 29 3b 0a 20 20  i, pOrigVfs);.  
59e0: 20 20 7d 0a 20 20 20 20 70 53 75 62 4f 70 65 6e    }.    pSubOpen
59f0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
5a00: 70 65 6e 28 70 47 72 6f 75 70 2c 20 28 69 6e 74  pen(pGroup, (int
5a10: 29 28 73 69 7a 65 2f 70 47 72 6f 75 70 2d 3e 73  )(size/pGroup->s
5a20: 7a 43 68 75 6e 6b 29 2c 20 26 72 63 32 2c 30 29  zChunk), &rc2,0)
5a30: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
5a40: 65 6e 20 29 7b 0a 20 20 20 20 20 20 72 63 32 20  en ){.      rc2 
5a50: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
5a60: 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28  hods->xTruncate(
5a70: 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 20 25  pSubOpen, size %
5a80: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
5a90: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 32  );.      if( rc2
5aa0: 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63  !=SQLITE_OK ) rc
5ab0: 20 3d 20 72 63 32 3b 0a 20 20 20 20 7d 65 6c 73   = rc2;.    }els
5ac0: 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51  e{.      rc = SQ
5ad0: 4c 49 54 45 5f 49 4f 45 52 52 5f 54 52 55 4e 43  LITE_IOERR_TRUNC
5ae0: 41 54 45 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20  ATE;.    }.  }. 
5af0: 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28   multiplexLeave(
5b00: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
5b10: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 79 6e 63  }../* Pass xSync
5b20: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
5b30: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
5b40: 6c 20 56 46 53 20 77 69 74 68 6f 75 74 20 63 68  l VFS without ch
5b50: 61 6e 67 65 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ange.*/.static i
5b60: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63  nt multiplexSync
5b70: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
5b80: 43 6f 6e 6e 2c 20 69 6e 74 20 66 6c 61 67 73 29  Conn, int flags)
5b90: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
5ba0: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
5bb0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
5bc0: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
5bd0: 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f  pGroup = p->pGro
5be0: 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  up;.  int rc = S
5bf0: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
5c00: 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  i;.  multiplexEn
5c10: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 69 3d 30  ter();.  for(i=0
5c20: 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61  ; i<pGroup->nRea
5c30: 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 73 71 6c  l; i++){.    sql
5c40: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
5c50: 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52  pen = pGroup->aR
5c60: 65 61 6c 5b 69 5d 2e 70 3b 0a 20 20 20 20 69 66  eal[i].p;.    if
5c70: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
5c80: 20 20 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53      int rc2 = pS
5c90: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
5ca0: 2d 3e 78 53 79 6e 63 28 70 53 75 62 4f 70 65 6e  ->xSync(pSubOpen
5cb0: 2c 20 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20  , flags);.      
5cc0: 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f  if( rc2!=SQLITE_
5cd0: 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a 20  OK ) rc = rc2;. 
5ce0: 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69     }.  }.  multi
5cf0: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
5d00: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
5d10: 50 61 73 73 20 78 46 69 6c 65 53 69 7a 65 20 72  Pass xFileSize r
5d20: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
5d30: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
5d40: 56 46 53 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74  VFS..** Aggregat
5d50: 65 20 74 68 65 20 73 69 7a 65 20 6f 66 20 61 6c  e the size of al
5d60: 6c 20 74 68 65 20 63 68 75 6e 6b 73 20 62 65 66  l the chunks bef
5d70: 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a  ore returning..*
5d80: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
5d90: 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 28 73  tiplexFileSize(s
5da0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
5db0: 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36  nn, sqlite3_int6
5dc0: 34 20 2a 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c  4 *pSize){.  mul
5dd0: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
5de0: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
5df0: 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c  pConn;.  multipl
5e00: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20  exGroup *pGroup 
5e10: 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69  = p->pGroup;.  i
5e20: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
5e30: 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75  K;.  int i;.  mu
5e40: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
5e50: 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62    if( !pGroup->b
5e60: 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73  Enabled ){.    s
5e70: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
5e80: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
5e90: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
5ea0: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
5eb0: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
5ec0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20  ==0 ){.      rc 
5ed0: 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 46  = SQLITE_IOERR_F
5ee0: 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  STAT;.    }else{
5ef0: 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62  .      rc = pSub
5f00: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
5f10: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70  xFileSize(pSubOp
5f20: 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20 20 20 20  en, pSize);.    
5f30: 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 73  }.  }else{.    s
5f40: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69  qlite3_vfs *pOri
5f50: 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65  gVfs = gMultiple
5f60: 78 2e 70 4f 72 69 67 56 66 73 3b 0a 20 20 20 20  x.pOrigVfs;.    
5f70: 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20 20 20  *pSize = 0;.    
5f80: 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53 51 4c  for(i=0; rc==SQL
5f90: 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a 20 20  ITE_OK; i++){.  
5fa0: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
5fb0: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 30 3b 0a   *pSubOpen = 0;.
5fc0: 20 20 20 20 20 20 69 6e 74 20 65 78 69 73 74 73        int exists
5fd0: 20 3d 20 30 3b 0a 20 20 20 20 20 20 72 63 20 3d   = 0;.      rc =
5fe0: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c   multiplexSubFil
5ff0: 65 6e 61 6d 65 28 70 47 72 6f 75 70 2c 20 69 29  ename(pGroup, i)
6000: 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 21 3d  ;.      if( rc!=
6010: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61  SQLITE_OK ) brea
6020: 6b 3b 0a 20 20 20 20 20 20 69 66 28 20 70 47 72  k;.      if( pGr
6030: 6f 75 70 2d 3e 6e 52 65 61 6c 3e 69 20 26 26 20  oup->nReal>i && 
6040: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 5d  pGroup->aReal[i]
6050: 2e 70 21 3d 30 20 29 7b 0a 20 20 20 20 20 20 20  .p!=0 ){.       
6060: 20 65 78 69 73 74 73 20 3d 20 31 3b 0a 20 20 20   exists = 1;.   
6070: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 28 70 47     }else if( (pG
6080: 72 6f 75 70 2d 3e 66 6c 61 67 73 20 26 20 53 51  roup->flags & SQ
6090: 4c 49 54 45 5f 4f 50 45 4e 5f 44 45 4c 45 54 45  LITE_OPEN_DELETE
60a0: 4f 4e 43 4c 4f 53 45 29 3d 3d 30 20 29 7b 0a 20  ONCLOSE)==0 ){. 
60b0: 20 20 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61         const cha
60c0: 72 20 2a 7a 52 65 61 6c 20 3d 20 70 47 72 6f 75  r *zReal = pGrou
60d0: 70 2d 3e 61 52 65 61 6c 5b 69 5d 2e 7a 3b 0a 20  p->aReal[i].z;. 
60e0: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
60f0: 67 56 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f  gVfs->xAccess(pO
6100: 72 69 67 56 66 73 2c 20 7a 52 65 61 6c 2c 20 53  rigVfs, zReal, S
6110: 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49  QLITE_ACCESS_EXI
6120: 53 54 53 2c 20 26 65 78 69 73 74 73 29 3b 0a 20  STS, &exists);. 
6130: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69 66 28       }.      if(
6140: 20 65 78 69 73 74 73 3d 3d 30 20 29 7b 0a 20 20   exists==0 ){.  
6150: 20 20 20 20 20 20 2f 2a 20 73 74 6f 70 20 61 74        /* stop at
6160: 20 66 69 72 73 74 20 22 67 61 70 22 20 6f 72 20   first "gap" or 
6170: 49 4f 20 65 72 72 6f 72 2e 20 2a 2f 0a 20 20 20  IO error. */.   
6180: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
6190: 20 20 7d 0a 20 20 20 20 20 20 69 66 28 20 72 63    }.      if( rc
61a0: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
61b0: 20 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20         pSubOpen 
61c0: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
61d0: 65 6e 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72  en(pGroup, i, &r
61e0: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20  c, NULL);.      
61f0: 7d 0a 20 20 20 20 20 20 61 73 73 65 72 74 28 20  }.      assert( 
6200: 70 53 75 62 4f 70 65 6e 20 7c 7c 20 72 63 21 3d  pSubOpen || rc!=
6210: 53 51 4c 49 54 45 5f 4f 4b 20 29 3b 0a 20 20 20  SQLITE_OK );.   
6220: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
6230: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  E_OK ){.        
6240: 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 7a  sqlite3_int64 sz
6250: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 72 63   = 0;.        rc
6260: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
6270: 74 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65  thods->xFileSize
6280: 28 70 53 75 62 4f 70 65 6e 2c 20 26 73 7a 29 3b  (pSubOpen, &sz);
6290: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d  .        if( rc=
62a0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 73 7a  =SQLITE_OK && sz
62b0: 3e 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b  >pGroup->szChunk
62c0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
62d0: 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f   = SQLITE_IOERR_
62e0: 46 53 54 41 54 3b 0a 20 20 20 20 20 20 20 20 7d  FSTAT;.        }
62f0: 0a 20 20 20 20 20 20 20 20 2a 70 53 69 7a 65 20  .        *pSize 
6300: 2b 3d 20 73 7a 3b 0a 20 20 20 20 20 20 7d 0a 20  += sz;.      }. 
6310: 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69     }.  }.  multi
6320: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
6330: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
6340: 50 61 73 73 20 78 4c 6f 63 6b 20 72 65 71 75 65  Pass xLock reque
6350: 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74  sts through to t
6360: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
6370: 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74  unchanged..*/.st
6380: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
6390: 65 78 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66  exLock(sqlite3_f
63a0: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20  ile *pConn, int 
63b0: 6c 6f 63 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  lock){.  multipl
63c0: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
63d0: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
63e0: 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73  n;.  int rc;.  s
63f0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
6400: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
6410: 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f  xSubOpen(p->pGro
6420: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
6430: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
6440: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
6450: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
6460: 64 73 2d 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70  ds->xLock(pSubOp
6470: 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20  en, lock);.  }. 
6480: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42   return SQLITE_B
6490: 55 53 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  USY;.}../* Pass 
64a0: 78 55 6e 6c 6f 63 6b 20 72 65 71 75 65 73 74 73  xUnlock requests
64b0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
64c0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
64d0: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
64e0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55  c int multiplexU
64f0: 6e 6c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69  nlock(sqlite3_fi
6500: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c  le *pConn, int l
6510: 6f 63 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  ock){.  multiple
6520: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
6530: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
6540: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
6550: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
6560: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
6570: 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75  SubOpen(p->pGrou
6580: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29  p, 0, &rc, NULL)
6590: 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e  ;.  if( pSubOpen
65a0: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70   ){.    return p
65b0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
65c0: 73 2d 3e 78 55 6e 6c 6f 63 6b 28 70 53 75 62 4f  s->xUnlock(pSubO
65d0: 70 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a  pen, lock);.  }.
65e0: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
65f0: 49 4f 45 52 52 5f 55 4e 4c 4f 43 4b 3b 0a 7d 0a  IOERR_UNLOCK;.}.
6600: 0a 2f 2a 20 50 61 73 73 20 78 43 68 65 63 6b 52  ./* Pass xCheckR
6610: 65 73 65 72 76 65 64 4c 6f 63 6b 20 72 65 71 75  eservedLock requ
6620: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
6630: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
6640: 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73   unchanged..*/.s
6650: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6660: 6c 65 78 43 68 65 63 6b 52 65 73 65 72 76 65 64  lexCheckReserved
6670: 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c  Lock(sqlite3_fil
6680: 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 2a 70  e *pConn, int *p
6690: 52 65 73 4f 75 74 29 7b 0a 20 20 6d 75 6c 74 69  ResOut){.  multi
66a0: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
66b0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
66c0: 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  onn;.  int rc;. 
66d0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
66e0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
66f0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47  lexSubOpen(p->pG
6700: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
6710: 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f  LL);.  if( pSubO
6720: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
6730: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
6740: 68 6f 64 73 2d 3e 78 43 68 65 63 6b 52 65 73 65  hods->xCheckRese
6750: 72 76 65 64 4c 6f 63 6b 28 70 53 75 62 4f 70 65  rvedLock(pSubOpe
6760: 6e 2c 20 70 52 65 73 4f 75 74 29 3b 0a 20 20 7d  n, pResOut);.  }
6770: 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45  .  return SQLITE
6780: 5f 49 4f 45 52 52 5f 43 48 45 43 4b 52 45 53 45  _IOERR_CHECKRESE
6790: 52 56 45 44 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 20  RVEDLOCK;.}../* 
67a0: 50 61 73 73 20 78 46 69 6c 65 43 6f 6e 74 72 6f  Pass xFileContro
67b0: 6c 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  l requests throu
67c0: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
67d0: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
67e0: 2c 0a 2a 2a 20 65 78 63 65 70 74 20 66 6f 72 20  ,.** except for 
67f0: 61 6e 79 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  any MULTIPLEX_CT
6800: 52 4c 5f 2a 20 72 65 71 75 65 73 74 73 20 68 65  RL_* requests he
6810: 72 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  re..*/.static in
6820: 74 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 43  t multiplexFileC
6830: 6f 6e 74 72 6f 6c 28 73 71 6c 69 74 65 33 5f 66  ontrol(sqlite3_f
6840: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20  ile *pConn, int 
6850: 6f 70 2c 20 76 6f 69 64 20 2a 70 41 72 67 29 7b  op, void *pArg){
6860: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
6870: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
6880: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d  Conn*)pConn;.  m
6890: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
68a0: 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75  Group = p->pGrou
68b0: 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  p;.  int rc = SQ
68c0: 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20 73 71  LITE_ERROR;.  sq
68d0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
68e0: 4f 70 65 6e 3b 0a 0a 20 20 69 66 28 20 21 67 4d  Open;..  if( !gM
68f0: 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69  ultiplex.isIniti
6900: 61 6c 69 7a 65 64 20 29 20 72 65 74 75 72 6e 20  alized ) return 
6910: 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20  SQLITE_MISUSE;. 
6920: 20 73 77 69 74 63 68 28 20 6f 70 20 29 7b 0a 20   switch( op ){. 
6930: 20 20 20 63 61 73 65 20 4d 55 4c 54 49 50 4c 45     case MULTIPLE
6940: 58 5f 43 54 52 4c 5f 45 4e 41 42 4c 45 3a 0a 20  X_CTRL_ENABLE:. 
6950: 20 20 20 20 20 69 66 28 20 70 41 72 67 20 29 20       if( pArg ) 
6960: 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 62 45  {.        int bE
6970: 6e 61 62 6c 65 64 20 3d 20 2a 28 69 6e 74 20 2a  nabled = *(int *
6980: 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20 20 70  )pArg;.        p
6990: 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20  Group->bEnabled 
69a0: 3d 20 62 45 6e 61 62 6c 65 64 3b 0a 20 20 20 20  = bEnabled;.    
69b0: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
69c0: 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  OK;.      }.    
69d0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73    break;.    cas
69e0: 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c  e MULTIPLEX_CTRL
69f0: 5f 53 45 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3a  _SET_CHUNK_SIZE:
6a00: 0a 20 20 20 20 20 20 69 66 28 20 70 41 72 67 20  .      if( pArg 
6a10: 29 20 7b 0a 20 20 20 20 20 20 20 20 75 6e 73 69  ) {.        unsi
6a20: 67 6e 65 64 20 69 6e 74 20 73 7a 43 68 75 6e 6b  gned int szChunk
6a30: 20 3d 20 2a 28 75 6e 73 69 67 6e 65 64 2a 29 70   = *(unsigned*)p
6a40: 41 72 67 3b 0a 20 20 20 20 20 20 20 20 69 66 28  Arg;.        if(
6a50: 20 73 7a 43 68 75 6e 6b 3c 31 20 29 7b 0a 20 20   szChunk<1 ){.  
6a60: 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c          rc = SQL
6a70: 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 20 20  ITE_MISUSE;.    
6a80: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
6a90: 20 20 20 20 20 2f 2a 20 52 6f 75 6e 64 20 75 70       /* Round up
6aa0: 20 74 6f 20 6e 65 61 72 65 73 74 20 6d 75 6c 74   to nearest mult
6ab0: 69 70 6c 65 20 6f 66 20 4d 41 58 5f 50 41 47 45  iple of MAX_PAGE
6ac0: 5f 53 49 5a 45 2e 20 2a 2f 0a 20 20 20 20 20 20  _SIZE. */.      
6ad0: 20 20 20 20 73 7a 43 68 75 6e 6b 20 3d 20 28 73      szChunk = (s
6ae0: 7a 43 68 75 6e 6b 20 2b 20 28 4d 41 58 5f 50 41  zChunk + (MAX_PA
6af0: 47 45 5f 53 49 5a 45 2d 31 29 29 3b 0a 20 20 20  GE_SIZE-1));.   
6b00: 20 20 20 20 20 20 20 73 7a 43 68 75 6e 6b 20 26         szChunk &
6b10: 3d 20 7e 28 4d 41 58 5f 50 41 47 45 5f 53 49 5a  = ~(MAX_PAGE_SIZ
6b20: 45 2d 31 29 3b 0a 20 20 20 20 20 20 20 20 20 20  E-1);.          
6b30: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20  pGroup->szChunk 
6b40: 3d 20 73 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20  = szChunk;.     
6b50: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
6b60: 5f 4f 4b 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  _OK;.        }. 
6b70: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65       }.      bre
6b80: 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 4d 55 4c  ak;.    case MUL
6b90: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f  TIPLEX_CTRL_SET_
6ba0: 4d 41 58 5f 43 48 55 4e 4b 53 3a 0a 20 20 20 20  MAX_CHUNKS:.    
6bb0: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b    rc = SQLITE_OK
6bc0: 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  ;.      break;. 
6bd0: 20 20 20 63 61 73 65 20 53 51 4c 49 54 45 5f 46     case SQLITE_F
6be0: 43 4e 54 4c 5f 53 49 5a 45 5f 48 49 4e 54 3a 0a  CNTL_SIZE_HINT:.
6bf0: 20 20 20 20 63 61 73 65 20 53 51 4c 49 54 45 5f      case SQLITE_
6c00: 46 43 4e 54 4c 5f 43 48 55 4e 4b 5f 53 49 5a 45  FCNTL_CHUNK_SIZE
6c10: 3a 0a 20 20 20 20 20 20 2f 2a 20 6e 6f 2d 6f 70  :.      /* no-op
6c20: 20 74 68 65 73 65 20 2a 2f 0a 20 20 20 20 20 20   these */.      
6c30: 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  rc = SQLITE_OK;.
6c40: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
6c50: 20 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20   default:.      
6c60: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
6c70: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
6c80: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
6c90: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70 53 75  );.      if( pSu
6ca0: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20 20  bOpen ){.       
6cb0: 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e   rc = pSubOpen->
6cc0: 70 4d 65 74 68 6f 64 73 2d 3e 78 46 69 6c 65 43  pMethods->xFileC
6cd0: 6f 6e 74 72 6f 6c 28 70 53 75 62 4f 70 65 6e 2c  ontrol(pSubOpen,
6ce0: 20 6f 70 2c 20 70 41 72 67 29 3b 0a 20 20 20 20   op, pArg);.    
6cf0: 20 20 7d 0a 20 20 20 20 20 20 62 72 65 61 6b 3b    }.      break;
6d00: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 72 63  .  }.  return rc
6d10: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 65  ;.}../* Pass xSe
6d20: 63 74 6f 72 53 69 7a 65 20 72 65 71 75 65 73 74  ctorSize request
6d30: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
6d40: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
6d50: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
6d60: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6d70: 53 65 63 74 6f 72 53 69 7a 65 28 73 71 6c 69 74  SectorSize(sqlit
6d80: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b  e3_file *pConn){
6d90: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
6da0: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
6db0: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69  Conn*)pConn;.  i
6dc0: 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33  nt rc;.  sqlite3
6dd0: 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20  _file *pSubOpen 
6de0: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
6df0: 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c  en(p->pGroup, 0,
6e00: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69   &rc, NULL);.  i
6e10: 66 28 20 70 53 75 62 4f 70 65 6e 20 26 26 20 70  f( pSubOpen && p
6e20: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6e30: 73 2d 3e 78 53 65 63 74 6f 72 53 69 7a 65 20 29  s->xSectorSize )
6e40: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75  {.    return pSu
6e50: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
6e60: 3e 78 53 65 63 74 6f 72 53 69 7a 65 28 70 53 75  >xSectorSize(pSu
6e70: 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65  bOpen);.  }.  re
6e80: 74 75 72 6e 20 44 45 46 41 55 4c 54 5f 53 45 43  turn DEFAULT_SEC
6e90: 54 4f 52 5f 53 49 5a 45 3b 0a 7d 0a 0a 2f 2a 20  TOR_SIZE;.}../* 
6ea0: 50 61 73 73 20 78 44 65 76 69 63 65 43 68 61 72  Pass xDeviceChar
6eb0: 61 63 74 65 72 69 73 74 69 63 73 20 72 65 71 75  acteristics requ
6ec0: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
6ed0: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
6ee0: 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73   unchanged..*/.s
6ef0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6f00: 6c 65 78 44 65 76 69 63 65 43 68 61 72 61 63 74  lexDeviceCharact
6f10: 65 72 69 73 74 69 63 73 28 73 71 6c 69 74 65 33  eristics(sqlite3
6f20: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20  _file *pConn){. 
6f30: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
6f40: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
6f50: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
6f60: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
6f70: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
6f80: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
6f90: 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26  (p->pGroup, 0, &
6fa0: 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28  rc, NULL);.  if(
6fb0: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
6fc0: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
6fd0: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 44 65 76  ->pMethods->xDev
6fe0: 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69  iceCharacteristi
6ff0: 63 73 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  cs(pSubOpen);.  
7000: 7d 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a  }.  return 0;.}.
7010: 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 4d 61 70  ./* Pass xShmMap
7020: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
7030: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
7040: 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e  l VFS unchanged.
7050: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
7060: 75 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70 28 0a  ultiplexShmMap(.
7070: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
7080: 70 43 6f 6e 6e 2c 20 20 20 20 20 20 20 20 20 20  pConn,          
7090: 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6f 70 65 6e    /* Handle open
70a0: 20 6f 6e 20 64 61 74 61 62 61 73 65 20 66 69 6c   on database fil
70b0: 65 20 2a 2f 0a 20 20 69 6e 74 20 69 52 65 67 69  e */.  int iRegi
70c0: 6f 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  on,             
70d0: 20 20 20 20 20 20 20 2f 2a 20 52 65 67 69 6f 6e         /* Region
70e0: 20 74 6f 20 72 65 74 72 69 65 76 65 20 2a 2f 0a   to retrieve */.
70f0: 20 20 69 6e 74 20 73 7a 52 65 67 69 6f 6e 2c 20    int szRegion, 
7100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7110: 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 72 65 67    /* Size of reg
7120: 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74 20 62 45  ions */.  int bE
7130: 78 74 65 6e 64 2c 20 20 20 20 20 20 20 20 20 20  xtend,          
7140: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72 75            /* Tru
7150: 65 20 74 6f 20 65 78 74 65 6e 64 20 66 69 6c 65  e to extend file
7160: 20 69 66 20 6e 65 63 65 73 73 61 72 79 20 2a 2f   if necessary */
7170: 0a 20 20 76 6f 69 64 20 76 6f 6c 61 74 69 6c 65  .  void volatile
7180: 20 2a 2a 70 70 20 20 20 20 20 20 20 20 20 20 20   **pp           
7190: 20 20 20 2f 2a 20 4f 55 54 3a 20 4d 61 70 70 65     /* OUT: Mappe
71a0: 64 20 6d 65 6d 6f 72 79 20 2a 2f 0a 29 7b 0a 20  d memory */.){. 
71b0: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
71c0: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
71d0: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
71e0: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
71f0: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
7200: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
7210: 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26  (p->pGroup, 0, &
7220: 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28  rc, NULL);.  if(
7230: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
7240: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
7250: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d  ->pMethods->xShm
7260: 4d 61 70 28 70 53 75 62 4f 70 65 6e 2c 20 69 52  Map(pSubOpen, iR
7270: 65 67 69 6f 6e 2c 20 73 7a 52 65 67 69 6f 6e 2c  egion, szRegion,
7280: 20 62 45 78 74 65 6e 64 2c 70 70 29 3b 0a 20 20   bExtend,pp);.  
7290: 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  }.  return SQLIT
72a0: 45 5f 49 4f 45 52 52 3b 0a 7d 0a 0a 2f 2a 20 50  E_IOERR;.}../* P
72b0: 61 73 73 20 78 53 68 6d 4c 6f 63 6b 20 72 65 71  ass xShmLock req
72c0: 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f  uests through to
72d0: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
72e0: 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a  S unchanged..*/.
72f0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
7300: 70 6c 65 78 53 68 6d 4c 6f 63 6b 28 0a 20 20 73  plexShmLock(.  s
7310: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
7320: 6e 6e 2c 20 20 20 20 20 20 20 2f 2a 20 44 61 74  nn,       /* Dat
7330: 61 62 61 73 65 20 66 69 6c 65 20 68 6f 6c 64 69  abase file holdi
7340: 6e 67 20 74 68 65 20 73 68 61 72 65 64 20 6d 65  ng the shared me
7350: 6d 6f 72 79 20 2a 2f 0a 20 20 69 6e 74 20 6f 66  mory */.  int of
7360: 73 74 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  st,             
7370: 20 20 20 20 20 2f 2a 20 46 69 72 73 74 20 6c 6f       /* First lo
7380: 63 6b 20 74 6f 20 61 63 71 75 69 72 65 20 6f 72  ck to acquire or
7390: 20 72 65 6c 65 61 73 65 20 2a 2f 0a 20 20 69 6e   release */.  in
73a0: 74 20 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20  t n,            
73b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62           /* Numb
73c0: 65 72 20 6f 66 20 6c 6f 63 6b 73 20 74 6f 20 61  er of locks to a
73d0: 63 71 75 69 72 65 20 6f 72 20 72 65 6c 65 61 73  cquire or releas
73e0: 65 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73  e */.  int flags
73f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7400: 20 20 2f 2a 20 57 68 61 74 20 74 6f 20 64 6f 20    /* What to do 
7410: 77 69 74 68 20 74 68 65 20 6c 6f 63 6b 20 2a 2f  with the lock */
7420: 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  .){.  multiplexC
7430: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
7440: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
7450: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
7460: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
7470: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
7480: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
7490: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
74a0: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
74b0: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75  {.    return pSu
74c0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
74d0: 3e 78 53 68 6d 4c 6f 63 6b 28 70 53 75 62 4f 70  >xShmLock(pSubOp
74e0: 65 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20 66 6c 61  en, ofst, n, fla
74f0: 67 73 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  gs);.  }.  retur
7500: 6e 20 53 51 4c 49 54 45 5f 42 55 53 59 3b 0a 7d  n SQLITE_BUSY;.}
7510: 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 42 61  ../* Pass xShmBa
7520: 72 72 69 65 72 20 72 65 71 75 65 73 74 73 20 74  rrier requests t
7530: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7540: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7550: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7560: 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 53 68  void multiplexSh
7570: 6d 42 61 72 72 69 65 72 28 73 71 6c 69 74 65 33  mBarrier(sqlite3
7580: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20  _file *pConn){. 
7590: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
75a0: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
75b0: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
75c0: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
75d0: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
75e0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
75f0: 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26  (p->pGroup, 0, &
7600: 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28  rc, NULL);.  if(
7610: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
7620: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7630: 6f 64 73 2d 3e 78 53 68 6d 42 61 72 72 69 65 72  ods->xShmBarrier
7640: 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a  (pSubOpen);.  }.
7650: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 55  }../* Pass xShmU
7660: 6e 6d 61 70 20 72 65 71 75 65 73 74 73 20 74 68  nmap requests th
7670: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
7680: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
7690: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
76a0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 55  nt multiplexShmU
76b0: 6e 6d 61 70 28 73 71 6c 69 74 65 33 5f 66 69 6c  nmap(sqlite3_fil
76c0: 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 64 65  e *pConn, int de
76d0: 6c 65 74 65 46 6c 61 67 29 7b 0a 20 20 6d 75 6c  leteFlag){.  mul
76e0: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
76f0: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
7700: 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b  pConn;.  int rc;
7710: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
7720: 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74  *pSubOpen = mult
7730: 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e  iplexSubOpen(p->
7740: 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20  pGroup, 0, &rc, 
7750: 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75  NULL);.  if( pSu
7760: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74  bOpen ){.    ret
7770: 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  urn pSubOpen->pM
7780: 65 74 68 6f 64 73 2d 3e 78 53 68 6d 55 6e 6d 61  ethods->xShmUnma
7790: 70 28 70 53 75 62 4f 70 65 6e 2c 20 64 65 6c 65  p(pSubOpen, dele
77a0: 74 65 46 6c 61 67 29 3b 0a 20 20 7d 0a 20 20 72  teFlag);.  }.  r
77b0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
77c0: 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .}../***********
77d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
77e0: 50 75 62 6c 69 63 20 49 6e 74 65 72 66 61 63 65  Public Interface
77f0: 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  s **************
7800: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f  ***************/
7810: 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20 49 6e 69  ./*.** CAPI: Ini
7820: 74 69 61 6c 69 7a 65 20 74 68 65 20 6d 75 6c 74  tialize the mult
7830: 69 70 6c 65 78 20 56 46 53 20 73 68 69 6d 20 2d  iplex VFS shim -
7840: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
7850: 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 29 0a  ex_initialize().
7860: 2a 2a 0a 2a 2a 20 55 73 65 20 74 68 65 20 56 46  **.** Use the VF
7870: 53 20 6e 61 6d 65 64 20 7a 4f 72 69 67 56 66 73  S named zOrigVfs
7880: 4e 61 6d 65 20 61 73 20 74 68 65 20 56 46 53 20  Name as the VFS 
7890: 74 68 61 74 20 64 6f 65 73 20 74 68 65 20 61 63  that does the ac
78a0: 74 75 61 6c 20 77 6f 72 6b 2e 20 20 0a 2a 2a 20  tual work.  .** 
78b0: 55 73 65 20 74 68 65 20 64 65 66 61 75 6c 74 20  Use the default 
78c0: 69 66 20 7a 4f 72 69 67 56 66 73 4e 61 6d 65 3d  if zOrigVfsName=
78d0: 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a 0a 2a 2a 20 54  =NULL.  .**.** T
78e0: 68 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53  he multiplex VFS
78f0: 20 73 68 69 6d 20 69 73 20 6e 61 6d 65 64 20 22   shim is named "
7900: 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20 49 74 20  multiplex".  It 
7910: 77 69 6c 6c 20 62 65 63 6f 6d 65 20 74 68 65 20  will become the 
7920: 64 65 66 61 75 6c 74 0a 2a 2a 20 56 46 53 20 69  default.** VFS i
7930: 66 20 6d 61 6b 65 44 65 66 61 75 6c 74 20 69 73  f makeDefault is
7940: 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a 2a 2a 0a 2a 2a   non-zero..**.**
7950: 20 54 48 49 53 20 52 4f 55 54 49 4e 45 20 49 53   THIS ROUTINE IS
7960: 20 4e 4f 54 20 54 48 52 45 41 44 53 41 46 45 2e   NOT THREADSAFE.
7970: 20 20 43 61 6c 6c 20 74 68 69 73 20 72 6f 75 74    Call this rout
7980: 69 6e 65 20 65 78 61 63 74 6c 79 20 6f 6e 63 65  ine exactly once
7990: 0a 2a 2a 20 64 75 72 69 6e 67 20 73 74 61 72 74  .** during start
79a0: 2d 75 70 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69  -up..*/.int sqli
79b0: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e  te3_multiplex_in
79c0: 69 74 69 61 6c 69 7a 65 28 63 6f 6e 73 74 20 63  itialize(const c
79d0: 68 61 72 20 2a 7a 4f 72 69 67 56 66 73 4e 61 6d  har *zOrigVfsNam
79e0: 65 2c 20 69 6e 74 20 6d 61 6b 65 44 65 66 61 75  e, int makeDefau
79f0: 6c 74 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 76  lt){.  sqlite3_v
7a00: 66 73 20 2a 70 4f 72 69 67 56 66 73 3b 0a 20 20  fs *pOrigVfs;.  
7a10: 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69  if( gMultiplex.i
7a20: 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 29 20 72  sInitialized ) r
7a30: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53  eturn SQLITE_MIS
7a40: 55 53 45 3b 0a 20 20 70 4f 72 69 67 56 66 73 20  USE;.  pOrigVfs 
7a50: 3d 20 73 71 6c 69 74 65 33 5f 76 66 73 5f 66 69  = sqlite3_vfs_fi
7a60: 6e 64 28 7a 4f 72 69 67 56 66 73 4e 61 6d 65 29  nd(zOrigVfsName)
7a70: 3b 0a 20 20 69 66 28 20 70 4f 72 69 67 56 66 73  ;.  if( pOrigVfs
7a80: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 53 51 4c  ==0 ) return SQL
7a90: 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20 61 73 73  ITE_ERROR;.  ass
7aa0: 65 72 74 28 20 70 4f 72 69 67 56 66 73 21 3d 26  ert( pOrigVfs!=&
7ab0: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
7ac0: 56 66 73 20 29 3b 0a 20 20 67 4d 75 6c 74 69 70  Vfs );.  gMultip
7ad0: 6c 65 78 2e 70 4d 75 74 65 78 20 3d 20 73 71 6c  lex.pMutex = sql
7ae0: 69 74 65 33 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63  ite3_mutex_alloc
7af0: 28 53 51 4c 49 54 45 5f 4d 55 54 45 58 5f 46 41  (SQLITE_MUTEX_FA
7b00: 53 54 29 3b 0a 20 20 69 66 28 20 21 67 4d 75 6c  ST);.  if( !gMul
7b10: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20 29 7b  tiplex.pMutex ){
7b20: 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49  .    return SQLI
7b30: 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d 0a 20 20  TE_NOMEM;.  }.  
7b40: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75  gMultiplex.pGrou
7b50: 70 73 20 3d 20 4e 55 4c 4c 3b 0a 20 20 67 4d 75  ps = NULL;.  gMu
7b60: 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61  ltiplex.isInitia
7b70: 6c 69 7a 65 64 20 3d 20 31 3b 0a 20 20 67 4d 75  lized = 1;.  gMu
7b80: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
7b90: 20 3d 20 70 4f 72 69 67 56 66 73 3b 0a 20 20 67   = pOrigVfs;.  g
7ba0: 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56  Multiplex.sThisV
7bb0: 66 73 20 3d 20 2a 70 4f 72 69 67 56 66 73 3b 0a  fs = *pOrigVfs;.
7bc0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
7bd0: 69 73 56 66 73 2e 73 7a 4f 73 46 69 6c 65 20 2b  isVfs.szOsFile +
7be0: 3d 20 73 69 7a 65 6f 66 28 6d 75 6c 74 69 70 6c  = sizeof(multipl
7bf0: 65 78 43 6f 6e 6e 29 3b 0a 20 20 67 4d 75 6c 74  exConn);.  gMult
7c00: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 7a  iplex.sThisVfs.z
7c10: 4e 61 6d 65 20 3d 20 53 51 4c 49 54 45 5f 4d 55  Name = SQLITE_MU
7c20: 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d 45  LTIPLEX_VFS_NAME
7c30: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
7c40: 54 68 69 73 56 66 73 2e 78 4f 70 65 6e 20 3d 20  ThisVfs.xOpen = 
7c50: 6d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 0a 20  multiplexOpen;. 
7c60: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
7c70: 73 56 66 73 2e 78 44 65 6c 65 74 65 20 3d 20 6d  sVfs.xDelete = m
7c80: 75 6c 74 69 70 6c 65 78 44 65 6c 65 74 65 3b 0a  ultiplexDelete;.
7c90: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
7ca0: 69 73 56 66 73 2e 78 41 63 63 65 73 73 20 3d 20  isVfs.xAccess = 
7cb0: 6d 75 6c 74 69 70 6c 65 78 41 63 63 65 73 73 3b  multiplexAccess;
7cc0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
7cd0: 68 69 73 56 66 73 2e 78 46 75 6c 6c 50 61 74 68  hisVfs.xFullPath
7ce0: 6e 61 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  name = multiplex
7cf0: 46 75 6c 6c 50 61 74 68 6e 61 6d 65 3b 0a 20 20  FullPathname;.  
7d00: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
7d10: 56 66 73 2e 78 44 6c 4f 70 65 6e 20 3d 20 6d 75  Vfs.xDlOpen = mu
7d20: 6c 74 69 70 6c 65 78 44 6c 4f 70 65 6e 3b 0a 20  ltiplexDlOpen;. 
7d30: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
7d40: 73 56 66 73 2e 78 44 6c 45 72 72 6f 72 20 3d 20  sVfs.xDlError = 
7d50: 6d 75 6c 74 69 70 6c 65 78 44 6c 45 72 72 6f 72  multiplexDlError
7d60: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
7d70: 54 68 69 73 56 66 73 2e 78 44 6c 53 79 6d 20 3d  ThisVfs.xDlSym =
7d80: 20 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79 6d 3b   multiplexDlSym;
7d90: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
7da0: 68 69 73 56 66 73 2e 78 44 6c 43 6c 6f 73 65 20  hisVfs.xDlClose 
7db0: 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f  = multiplexDlClo
7dc0: 73 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  se;.  gMultiplex
7dd0: 2e 73 54 68 69 73 56 66 73 2e 78 52 61 6e 64 6f  .sThisVfs.xRando
7de0: 6d 6e 65 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65  mness = multiple
7df0: 78 52 61 6e 64 6f 6d 6e 65 73 73 3b 0a 20 20 67  xRandomness;.  g
7e00: 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56  Multiplex.sThisV
7e10: 66 73 2e 78 53 6c 65 65 70 20 3d 20 6d 75 6c 74  fs.xSleep = mult
7e20: 69 70 6c 65 78 53 6c 65 65 70 3b 0a 20 20 67 4d  iplexSleep;.  gM
7e30: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
7e40: 73 2e 78 43 75 72 72 65 6e 74 54 69 6d 65 20 3d  s.xCurrentTime =
7e50: 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e   multiplexCurren
7e60: 74 54 69 6d 65 3b 0a 20 20 67 4d 75 6c 74 69 70  tTime;.  gMultip
7e70: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 47 65  lex.sThisVfs.xGe
7e80: 74 4c 61 73 74 45 72 72 6f 72 20 3d 20 6d 75 6c  tLastError = mul
7e90: 74 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72 72  tiplexGetLastErr
7ea0: 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  or;.  gMultiplex
7eb0: 2e 73 54 68 69 73 56 66 73 2e 78 43 75 72 72 65  .sThisVfs.xCurre
7ec0: 6e 74 54 69 6d 65 49 6e 74 36 34 20 3d 20 6d 75  ntTimeInt64 = mu
7ed0: 6c 74 69 70 6c 65 78 43 75 72 72 65 6e 74 54 69  ltiplexCurrentTi
7ee0: 6d 65 49 6e 74 36 34 3b 0a 0a 20 20 67 4d 75 6c  meInt64;..  gMul
7ef0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
7f00: 73 56 31 2e 69 56 65 72 73 69 6f 6e 20 3d 20 31  sV1.iVersion = 1
7f10: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
7f20: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 43 6c 6f  IoMethodsV1.xClo
7f30: 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 6c  se = multiplexCl
7f40: 6f 73 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ose;.  gMultiple
7f50: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
7f60: 52 65 61 64 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Read = multiplex
7f70: 52 65 61 64 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Read;.  gMultipl
7f80: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
7f90: 78 57 72 69 74 65 20 3d 20 6d 75 6c 74 69 70 6c  xWrite = multipl
7fa0: 65 78 57 72 69 74 65 3b 0a 20 20 67 4d 75 6c 74  exWrite;.  gMult
7fb0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
7fc0: 56 31 2e 78 54 72 75 6e 63 61 74 65 20 3d 20 6d  V1.xTruncate = m
7fd0: 75 6c 74 69 70 6c 65 78 54 72 75 6e 63 61 74 65  ultiplexTruncate
7fe0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
7ff0: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53 79 6e  IoMethodsV1.xSyn
8000: 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e  c = multiplexSyn
8010: 63 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  c;.  gMultiplex.
8020: 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46 69  sIoMethodsV1.xFi
8030: 6c 65 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c  leSize = multipl
8040: 65 78 46 69 6c 65 53 69 7a 65 3b 0a 20 20 67 4d  exFileSize;.  gM
8050: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8060: 6f 64 73 56 31 2e 78 4c 6f 63 6b 20 3d 20 6d 75  odsV1.xLock = mu
8070: 6c 74 69 70 6c 65 78 4c 6f 63 6b 3b 0a 20 20 67  ltiplexLock;.  g
8080: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
8090: 68 6f 64 73 56 31 2e 78 55 6e 6c 6f 63 6b 20 3d  hodsV1.xUnlock =
80a0: 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c 6f 63 6b   multiplexUnlock
80b0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
80c0: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 43 68 65  IoMethodsV1.xChe
80d0: 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 20 3d  ckReservedLock =
80e0: 20 6d 75 6c 74 69 70 6c 65 78 43 68 65 63 6b 52   multiplexCheckR
80f0: 65 73 65 72 76 65 64 4c 6f 63 6b 3b 0a 20 20 67  eservedLock;.  g
8100: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
8110: 68 6f 64 73 56 31 2e 78 46 69 6c 65 43 6f 6e 74  hodsV1.xFileCont
8120: 72 6f 6c 20 3d 20 6d 75 6c 74 69 70 6c 65 78 46  rol = multiplexF
8130: 69 6c 65 43 6f 6e 74 72 6f 6c 3b 0a 20 20 67 4d  ileControl;.  gM
8140: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8150: 6f 64 73 56 31 2e 78 53 65 63 74 6f 72 53 69 7a  odsV1.xSectorSiz
8160: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 65 63  e = multiplexSec
8170: 74 6f 72 53 69 7a 65 3b 0a 20 20 67 4d 75 6c 74  torSize;.  gMult
8180: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
8190: 56 31 2e 78 44 65 76 69 63 65 43 68 61 72 61 63  V1.xDeviceCharac
81a0: 74 65 72 69 73 74 69 63 73 20 3d 0a 20 20 20 20  teristics =.    
81b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
81c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
81d0: 20 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65          multiple
81e0: 78 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72  xDeviceCharacter
81f0: 69 73 74 69 63 73 3b 0a 20 20 67 4d 75 6c 74 69  istics;.  gMulti
8200: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
8210: 32 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  2 = gMultiplex.s
8220: 49 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 67  IoMethodsV1;.  g
8230: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
8240: 68 6f 64 73 56 32 2e 69 56 65 72 73 69 6f 6e 20  hodsV2.iVersion 
8250: 3d 20 32 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  = 2;.  gMultiple
8260: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78  x.sIoMethodsV2.x
8270: 53 68 6d 4d 61 70 20 3d 20 6d 75 6c 74 69 70 6c  ShmMap = multipl
8280: 65 78 53 68 6d 4d 61 70 3b 0a 20 20 67 4d 75 6c  exShmMap;.  gMul
8290: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
82a0: 73 56 32 2e 78 53 68 6d 4c 6f 63 6b 20 3d 20 6d  sV2.xShmLock = m
82b0: 75 6c 74 69 70 6c 65 78 53 68 6d 4c 6f 63 6b 3b  ultiplexShmLock;
82c0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
82d0: 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 42  oMethodsV2.xShmB
82e0: 61 72 72 69 65 72 20 3d 20 6d 75 6c 74 69 70 6c  arrier = multipl
82f0: 65 78 53 68 6d 42 61 72 72 69 65 72 3b 0a 20 20  exShmBarrier;.  
8300: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
8310: 74 68 6f 64 73 56 32 2e 78 53 68 6d 55 6e 6d 61  thodsV2.xShmUnma
8320: 70 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  p = multiplexShm
8330: 55 6e 6d 61 70 3b 0a 20 20 73 71 6c 69 74 65 33  Unmap;.  sqlite3
8340: 5f 76 66 73 5f 72 65 67 69 73 74 65 72 28 26 67  _vfs_register(&g
8350: 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56  Multiplex.sThisV
8360: 66 73 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29  fs, makeDefault)
8370: 3b 0a 0a 20 20 73 71 6c 69 74 65 33 5f 61 75 74  ;..  sqlite3_aut
8380: 6f 5f 65 78 74 65 6e 73 69 6f 6e 28 28 76 6f 69  o_extension((voi
8390: 64 2a 29 6d 75 6c 74 69 70 6c 65 78 46 75 6e 63  d*)multiplexFunc
83a0: 49 6e 69 74 29 3b 0a 0a 20 20 72 65 74 75 72 6e  Init);..  return
83b0: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f   SQLITE_OK;.}../
83c0: 2a 0a 2a 2a 20 43 41 50 49 3a 20 53 68 75 74 64  *.** CAPI: Shutd
83d0: 6f 77 6e 20 74 68 65 20 6d 75 6c 74 69 70 6c 65  own the multiple
83e0: 78 20 73 79 73 74 65 6d 20 2d 20 73 71 6c 69 74  x system - sqlit
83f0: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  e3_multiplex_shu
8400: 74 64 6f 77 6e 28 29 0a 2a 2a 0a 2a 2a 20 41 6c  tdown().**.** Al
8410: 6c 20 53 51 4c 69 74 65 20 64 61 74 61 62 61 73  l SQLite databas
8420: 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 6d 75  e connections mu
8430: 73 74 20 62 65 20 63 6c 6f 73 65 64 20 62 65 66  st be closed bef
8440: 6f 72 65 20 63 61 6c 6c 69 6e 67 20 74 68 69 73  ore calling this
8450: 0a 2a 2a 20 72 6f 75 74 69 6e 65 2e 0a 2a 2a 0a  .** routine..**.
8460: 2a 2a 20 54 48 49 53 20 52 4f 55 54 49 4e 45 20  ** THIS ROUTINE 
8470: 49 53 20 4e 4f 54 20 54 48 52 45 41 44 53 41 46  IS NOT THREADSAF
8480: 45 2e 20 20 43 61 6c 6c 20 74 68 69 73 20 72 6f  E.  Call this ro
8490: 75 74 69 6e 65 20 65 78 61 63 74 6c 79 20 6f 6e  utine exactly on
84a0: 63 65 20 77 68 69 6c 65 0a 2a 2a 20 73 68 75 74  ce while.** shut
84b0: 74 69 6e 67 20 64 6f 77 6e 20 69 6e 20 6f 72 64  ting down in ord
84c0: 65 72 20 74 6f 20 66 72 65 65 20 61 6c 6c 20 72  er to free all r
84d0: 65 6d 61 69 6e 69 6e 67 20 6d 75 6c 74 69 70 6c  emaining multipl
84e0: 65 78 20 67 72 6f 75 70 73 2e 0a 2a 2f 0a 69 6e  ex groups..*/.in
84f0: 74 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  t sqlite3_multip
8500: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 76 6f 69  lex_shutdown(voi
8510: 64 29 7b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69  d){.  if( gMulti
8520: 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a  plex.isInitializ
8530: 65 64 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 53  ed==0 ) return S
8540: 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20  QLITE_MISUSE;.  
8550: 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  if( gMultiplex.p
8560: 47 72 6f 75 70 73 20 29 20 72 65 74 75 72 6e 20  Groups ) return 
8570: 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20  SQLITE_MISUSE;. 
8580: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e   gMultiplex.isIn
8590: 69 74 69 61 6c 69 7a 65 64 20 3d 20 30 3b 0a 20  itialized = 0;. 
85a0: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 66   sqlite3_mutex_f
85b0: 72 65 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70  ree(gMultiplex.p
85c0: 4d 75 74 65 78 29 3b 0a 20 20 73 71 6c 69 74 65  Mutex);.  sqlite
85d0: 33 5f 76 66 73 5f 75 6e 72 65 67 69 73 74 65 72  3_vfs_unregister
85e0: 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68  (&gMultiplex.sTh
85f0: 69 73 56 66 73 29 3b 0a 20 20 6d 65 6d 73 65 74  isVfs);.  memset
8600: 28 26 67 4d 75 6c 74 69 70 6c 65 78 2c 20 30 2c  (&gMultiplex, 0,
8610: 20 73 69 7a 65 6f 66 28 67 4d 75 6c 74 69 70 6c   sizeof(gMultipl
8620: 65 78 29 29 3b 0a 20 20 72 65 74 75 72 6e 20 53  ex));.  return S
8630: 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a  QLITE_OK;.}../**
8640: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8650: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 54 65 73 74  *********** Test
8660: 20 43 6f 64 65 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a   Code **********
8670: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8680: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 23 69 66 64 65  *********/.#ifde
8690: 66 20 53 51 4c 49 54 45 5f 54 45 53 54 0a 23 69  f SQLITE_TEST.#i
86a0: 6e 63 6c 75 64 65 20 3c 74 63 6c 2e 68 3e 0a 65  nclude <tcl.h>.e
86b0: 78 74 65 72 6e 20 63 6f 6e 73 74 20 63 68 61 72  xtern const char
86c0: 20 2a 73 71 6c 69 74 65 33 54 65 73 74 45 72 72   *sqlite3TestErr
86d0: 6f 72 4e 61 6d 65 28 69 6e 74 29 3b 0a 0a 0a 2f  orName(int);.../
86e0: 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71 6c  *.** tclcmd: sql
86f0: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69  ite3_multiplex_i
8700: 6e 69 74 69 61 6c 69 7a 65 20 4e 41 4d 45 20 4d  nitialize NAME M
8710: 41 4b 45 44 45 46 41 55 4c 54 0a 2a 2f 0a 73 74  AKEDEFAULT.*/.st
8720: 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75  atic int test_mu
8730: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
8740: 7a 65 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c 69  ze(.  void * cli
8750: 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49  entData,.  Tcl_I
8760: 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20  nterp *interp,. 
8770: 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c   int objc,.  Tcl
8780: 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76  _Obj *CONST objv
8790: 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68  [].){.  const ch
87a0: 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20 20  ar *zName;      
87b0: 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65 20          /* Name 
87c0: 6f 66 20 6e 65 77 20 6d 75 6c 74 69 70 6c 65 78  of new multiplex
87d0: 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6d 61   VFS */.  int ma
87e0: 6b 65 44 65 66 61 75 6c 74 3b 20 20 20 20 20 20  keDefault;      
87f0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72 75            /* Tru
8800: 65 20 74 6f 20 6d 61 6b 65 20 74 68 65 20 6e 65  e to make the ne
8810: 77 20 56 46 53 20 74 68 65 20 64 65 66 61 75 6c  w VFS the defaul
8820: 74 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20 20  t */.  int rc;  
8830: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8840: 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20         /* Value 
8850: 72 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c 74  returned by mult
8860: 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65  iplex_initialize
8870: 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45 44 5f  () */..  UNUSED_
8880: 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e 74  PARAMETER(client
8890: 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 50 72 6f  Data);..  /* Pro
88a0: 63 65 73 73 20 61 72 67 75 6d 65 6e 74 73 20 2a  cess arguments *
88b0: 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 33 20  /.  if( objc!=3 
88c0: 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67  ){.    Tcl_Wrong
88d0: 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20  NumArgs(interp, 
88e0: 31 2c 20 6f 62 6a 76 2c 20 22 4e 41 4d 45 20 4d  1, objv, "NAME M
88f0: 41 4b 45 44 45 46 41 55 4c 54 22 29 3b 0a 20 20  AKEDEFAULT");.  
8900: 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52    return TCL_ERR
8910: 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e 61 6d 65 20  OR;.  }.  zName 
8920: 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 28  = Tcl_GetString(
8930: 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20 69 66 28 20  objv[1]);.  if( 
8940: 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61 6e 46 72  Tcl_GetBooleanFr
8950: 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f 62  omObj(interp, ob
8960: 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65 44 65 66 61  jv[2], &makeDefa
8970: 75 6c 74 29 20 29 20 72 65 74 75 72 6e 20 54 43  ult) ) return TC
8980: 4c 5f 45 52 52 4f 52 3b 0a 20 20 69 66 28 20 7a  L_ERROR;.  if( z
8990: 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30 27 20 29 20  Name[0]=='\0' ) 
89a0: 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a 20 20 2f 2a  zName = 0;..  /*
89b0: 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d 75   Call sqlite3_mu
89c0: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
89d0: 7a 65 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20 73  ze() */.  rc = s
89e0: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
89f0: 5f 69 6e 69 74 69 61 6c 69 7a 65 28 7a 4e 61 6d  _initialize(zNam
8a00: 65 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29 3b  e, makeDefault);
8a10: 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c 74  .  Tcl_SetResult
8a20: 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20 2a  (interp, (char *
8a30: 29 73 71 6c 69 74 65 33 54 65 73 74 45 72 72 6f  )sqlite3TestErro
8a40: 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f 53  rName(rc), TCL_S
8a50: 54 41 54 49 43 29 3b 0a 0a 20 20 72 65 74 75 72  TATIC);..  retur
8a60: 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a  n TCL_OK;.}../*.
8a70: 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71 6c 69 74  ** tclcmd: sqlit
8a80: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  e3_multiplex_shu
8a90: 74 64 6f 77 6e 0a 2a 2f 0a 73 74 61 74 69 63 20  tdown.*/.static 
8aa0: 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  int test_multipl
8ab0: 65 78 5f 73 68 75 74 64 6f 77 6e 28 0a 20 20 76  ex_shutdown(.  v
8ac0: 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74 61  oid * clientData
8ad0: 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a  ,.  Tcl_Interp *
8ae0: 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62  interp,.  int ob
8af0: 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43  jc,.  Tcl_Obj *C
8b00: 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20  ONST objv[].){. 
8b10: 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20   int rc;        
8b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8b30: 20 2f 2a 20 56 61 6c 75 65 20 72 65 74 75 72 6e   /* Value return
8b40: 65 64 20 62 79 20 6d 75 6c 74 69 70 6c 65 78 5f  ed by multiplex_
8b50: 73 68 75 74 64 6f 77 6e 28 29 20 2a 2f 0a 0a 20  shutdown() */.. 
8b60: 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45   UNUSED_PARAMETE
8b70: 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b 0a 0a  R(clientData);..
8b80: 20 20 69 66 28 20 6f 62 6a 63 21 3d 31 20 29 7b    if( objc!=1 ){
8b90: 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75  .    Tcl_WrongNu
8ba0: 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c  mArgs(interp, 1,
8bb0: 20 6f 62 6a 76 2c 20 22 22 29 3b 0a 20 20 20 20   objv, "");.    
8bc0: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
8bd0: 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 61 6c 6c  ;.  }..  /* Call
8be0: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
8bf0: 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a 2f  ex_shutdown() */
8c00: 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f  .  rc = sqlite3_
8c10: 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f  multiplex_shutdo
8c20: 77 6e 28 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52  wn();.  Tcl_SetR
8c30: 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63  esult(interp, (c
8c40: 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73  har *)sqlite3Tes
8c50: 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20  tErrorName(rc), 
8c60: 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20 20  TCL_STATIC);..  
8c70: 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d  return TCL_OK;.}
8c80: 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20  ../*.** tclcmd: 
8c90: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
8ca0: 65 78 5f 64 75 6d 70 0a 2a 2f 0a 73 74 61 74 69  ex_dump.*/.stati
8cb0: 63 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69  c int test_multi
8cc0: 70 6c 65 78 5f 64 75 6d 70 28 0a 20 20 76 6f 69  plex_dump(.  voi
8cd0: 64 20 2a 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a  d * clientData,.
8ce0: 20 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e    Tcl_Interp *in
8cf0: 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63  terp,.  int objc
8d00: 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e  ,.  Tcl_Obj *CON
8d10: 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 54  ST objv[].){.  T
8d20: 63 6c 5f 4f 62 6a 20 2a 70 52 65 73 75 6c 74 3b  cl_Obj *pResult;
8d30: 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 47 72 6f  .  Tcl_Obj *pGro
8d40: 75 70 54 65 72 6d 3b 0a 20 20 6d 75 6c 74 69 70  upTerm;.  multip
8d50: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
8d60: 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74  ;.  int i;.  int
8d70: 20 6e 43 68 75 6e 6b 73 20 3d 20 30 3b 0a 0a 20   nChunks = 0;.. 
8d80: 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45   UNUSED_PARAMETE
8d90: 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b 0a 20  R(clientData);. 
8da0: 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45   UNUSED_PARAMETE
8db0: 52 28 6f 62 6a 63 29 3b 0a 20 20 55 4e 55 53 45  R(objc);.  UNUSE
8dc0: 44 5f 50 41 52 41 4d 45 54 45 52 28 6f 62 6a 76  D_PARAMETER(objv
8dd0: 29 3b 0a 0a 20 20 70 52 65 73 75 6c 74 20 3d 20  );..  pResult = 
8de0: 54 63 6c 5f 4e 65 77 4f 62 6a 28 29 3b 0a 20 20  Tcl_NewObj();.  
8df0: 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29  multiplexEnter()
8e00: 3b 0a 20 20 66 6f 72 28 70 47 72 6f 75 70 3d 67  ;.  for(pGroup=g
8e10: 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70  Multiplex.pGroup
8e20: 73 3b 20 70 47 72 6f 75 70 3b 20 70 47 72 6f 75  s; pGroup; pGrou
8e30: 70 3d 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74 29  p=pGroup->pNext)
8e40: 7b 0a 20 20 20 20 70 47 72 6f 75 70 54 65 72 6d  {.    pGroupTerm
8e50: 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28 29 3b   = Tcl_NewObj();
8e60: 0a 0a 20 20 20 20 69 66 28 20 70 47 72 6f 75 70  ..    if( pGroup
8e70: 2d 3e 7a 4e 61 6d 65 20 29 7b 0a 20 20 20 20 20  ->zName ){.     
8e80: 20 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 5b 70   pGroup->zName[p
8e90: 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 5d 20 3d 20  Group->nName] = 
8ea0: 27 5c 30 27 3b 0a 20 20 20 20 20 20 54 63 6c 5f  '\0';.      Tcl_
8eb0: 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65  ListObjAppendEle
8ec0: 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72  ment(interp, pGr
8ed0: 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20  oupTerm,.       
8ee0: 20 20 20 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67     Tcl_NewString
8ef0: 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d  Obj(pGroup->zNam
8f00: 65 2c 20 2d 31 29 29 3b 0a 20 20 20 20 7d 65 6c  e, -1));.    }el
8f10: 73 65 7b 0a 20 20 20 20 20 20 54 63 6c 5f 4c 69  se{.      Tcl_Li
8f20: 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65  stObjAppendEleme
8f30: 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75  nt(interp, pGrou
8f40: 70 54 65 72 6d 2c 20 54 63 6c 5f 4e 65 77 4f 62  pTerm, Tcl_NewOb
8f50: 6a 28 29 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  j());.    }.    
8f60: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
8f70: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
8f80: 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20   pGroupTerm,.   
8f90: 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e         Tcl_NewIn
8fa0: 74 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 6e 4e 61  tObj(pGroup->nNa
8fb0: 6d 65 29 29 3b 0a 20 20 20 20 54 63 6c 5f 4c 69  me));.    Tcl_Li
8fc0: 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65  stObjAppendEleme
8fd0: 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75  nt(interp, pGrou
8fe0: 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20  pTerm,.         
8ff0: 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70   Tcl_NewIntObj(p
9000: 47 72 6f 75 70 2d 3e 66 6c 61 67 73 29 29 3b 0a  Group->flags));.
9010: 0a 20 20 20 20 2f 2a 20 63 6f 75 6e 74 20 6e 75  .    /* count nu
9020: 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73 20 77  mber of chunks w
9030: 69 74 68 20 6f 70 65 6e 20 68 61 6e 64 6c 65 73  ith open handles
9040: 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b   */.    for(i=0;
9050: 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c   i<pGroup->nReal
9060: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 69 66  ; i++){.      if
9070: 28 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b  ( pGroup->aReal[
9080: 69 5d 2e 70 21 3d 30 20 29 20 6e 43 68 75 6e 6b  i].p!=0 ) nChunk
9090: 73 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20 20 20 54  s++;.    }.    T
90a0: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
90b0: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
90c0: 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20  pGroupTerm,.    
90d0: 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74        Tcl_NewInt
90e0: 4f 62 6a 28 6e 43 68 75 6e 6b 73 29 29 3b 0a 0a  Obj(nChunks));..
90f0: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
9100: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
9110: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
9120: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
9130: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
9140: 3e 73 7a 43 68 75 6e 6b 29 29 3b 0a 20 20 20 20  >szChunk));.    
9150: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
9160: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
9170: 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20   pGroupTerm,.   
9180: 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e         Tcl_NewIn
9190: 74 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 6e 52 65  tObj(pGroup->nRe
91a0: 61 6c 29 29 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c  al));..    Tcl_L
91b0: 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d  istObjAppendElem
91c0: 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 52 65 73  ent(interp, pRes
91d0: 75 6c 74 2c 20 70 47 72 6f 75 70 54 65 72 6d 29  ult, pGroupTerm)
91e0: 3b 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  ;.  }.  multiple
91f0: 78 4c 65 61 76 65 28 29 3b 0a 20 20 54 63 6c 5f  xLeave();.  Tcl_
9200: 53 65 74 4f 62 6a 52 65 73 75 6c 74 28 69 6e 74  SetObjResult(int
9210: 65 72 70 2c 20 70 52 65 73 75 6c 74 29 3b 0a 20  erp, pResult);. 
9220: 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a   return TCL_OK;.
9230: 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63 6c 63 6d 64 3a  }../*.** Tclcmd:
9240: 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f   test_multiplex_
9250: 63 6f 6e 74 72 6f 6c 20 48 41 4e 44 4c 45 20 44  control HANDLE D
9260: 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41 4e  BNAME SUB-COMMAN
9270: 44 20 3f 49 4e 54 2d 56 41 4c 55 45 3f 0a 2a 2f  D ?INT-VALUE?.*/
9280: 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74  .static int test
9290: 5f 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72  _multiplex_contr
92a0: 6f 6c 28 0a 20 20 43 6c 69 65 6e 74 44 61 74 61  ol(.  ClientData
92b0: 20 63 64 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72   cd,.  Tcl_Inter
92c0: 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74  p *interp,.  int
92d0: 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a   objc,.  Tcl_Obj
92e0: 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29   *CONST objv[].)
92f0: 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20  {.  int rc;     
9300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9310: 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f      /* Return co
9320: 64 65 20 66 72 6f 6d 20 66 69 6c 65 5f 63 6f 6e  de from file_con
9330: 74 72 6f 6c 28 29 20 2a 2f 0a 20 20 69 6e 74 20  trol() */.  int 
9340: 69 64 78 3b 20 20 20 20 20 20 20 20 20 20 20 20  idx;            
9350: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49              /* I
9360: 6e 64 65 78 20 69 6e 20 61 53 75 62 5b 5d 20 2a  ndex in aSub[] *
9370: 2f 0a 20 20 54 63 6c 5f 43 6d 64 49 6e 66 6f 20  /.  Tcl_CmdInfo 
9380: 63 6d 64 49 6e 66 6f 3b 20 20 20 20 20 20 20 20  cmdInfo;        
9390: 20 20 20 20 2f 2a 20 43 6f 6d 6d 61 6e 64 20 69      /* Command i
93a0: 6e 66 6f 20 73 74 72 75 63 74 75 72 65 20 66 6f  nfo structure fo
93b0: 72 20 48 41 4e 44 4c 45 20 2a 2f 0a 20 20 73 71  r HANDLE */.  sq
93c0: 6c 69 74 65 33 20 2a 64 62 3b 20 20 20 20 20 20  lite3 *db;      
93d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
93e0: 20 55 6e 64 65 72 6c 79 69 6e 67 20 64 62 20 68   Underlying db h
93f0: 61 6e 64 6c 65 20 66 6f 72 20 48 41 4e 44 4c 45  andle for HANDLE
9400: 20 2a 2f 0a 20 20 69 6e 74 20 69 56 61 6c 75 65   */.  int iValue
9410: 20 3d 20 30 3b 0a 20 20 76 6f 69 64 20 2a 70 41   = 0;.  void *pA
9420: 72 67 20 3d 20 30 3b 0a 0a 20 20 73 74 72 75 63  rg = 0;..  struc
9430: 74 20 53 75 62 43 6f 6d 6d 61 6e 64 20 7b 0a 20  t SubCommand {. 
9440: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a     const char *z
9450: 4e 61 6d 65 3b 0a 20 20 20 20 69 6e 74 20 6f 70  Name;.    int op
9460: 3b 0a 20 20 20 20 69 6e 74 20 61 72 67 74 79 70  ;.    int argtyp
9470: 65 3b 0a 20 20 7d 20 61 53 75 62 5b 5d 20 3d 20  e;.  } aSub[] = 
9480: 7b 0a 20 20 20 20 7b 20 22 65 6e 61 62 6c 65 22  {.    { "enable"
9490: 2c 20 20 20 20 20 20 20 4d 55 4c 54 49 50 4c 45  ,       MULTIPLE
94a0: 58 5f 43 54 52 4c 5f 45 4e 41 42 4c 45 2c 20 20  X_CTRL_ENABLE,  
94b0: 20 20 20 20 20 20 20 20 20 31 20 7d 2c 0a 20 20           1 },.  
94c0: 20 20 7b 20 22 63 68 75 6e 6b 5f 73 69 7a 65 22    { "chunk_size"
94d0: 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  ,   MULTIPLEX_CT
94e0: 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f 53 49 5a  RL_SET_CHUNK_SIZ
94f0: 45 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b 20  E,   1 },.    { 
9500: 22 6d 61 78 5f 63 68 75 6e 6b 73 22 2c 20 20 20  "max_chunks",   
9510: 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53  MULTIPLEX_CTRL_S
9520: 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 2c 20 20  ET_MAX_CHUNKS,  
9530: 20 31 20 7d 2c 0a 20 20 20 20 7b 20 30 2c 20 30   1 },.    { 0, 0
9540: 2c 20 30 20 7d 0a 20 20 7d 3b 0a 0a 20 20 69 66  , 0 }.  };..  if
9550: 28 20 6f 62 6a 63 21 3d 35 20 29 7b 0a 20 20 20  ( objc!=5 ){.   
9560: 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67   Tcl_WrongNumArg
9570: 73 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a  s(interp, 1, obj
9580: 76 2c 20 22 48 41 4e 44 4c 45 20 44 42 4e 41 4d  v, "HANDLE DBNAM
9590: 45 20 53 55 42 2d 43 4f 4d 4d 41 4e 44 20 49 4e  E SUB-COMMAND IN
95a0: 54 2d 56 41 4c 55 45 22 29 3b 0a 20 20 20 20 72  T-VALUE");.    r
95b0: 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b  eturn TCL_ERROR;
95c0: 0a 20 20 7d 0a 0a 20 20 69 66 28 20 30 3d 3d 54  .  }..  if( 0==T
95d0: 63 6c 5f 47 65 74 43 6f 6d 6d 61 6e 64 49 6e 66  cl_GetCommandInf
95e0: 6f 28 69 6e 74 65 72 70 2c 20 54 63 6c 5f 47 65  o(interp, Tcl_Ge
95f0: 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 31 5d 29  tString(objv[1])
9600: 2c 20 26 63 6d 64 49 6e 66 6f 29 20 29 7b 0a 20  , &cmdInfo) ){. 
9610: 20 20 20 54 63 6c 5f 41 70 70 65 6e 64 52 65 73     Tcl_AppendRes
9620: 75 6c 74 28 69 6e 74 65 72 70 2c 20 22 65 78 70  ult(interp, "exp
9630: 65 63 74 65 64 20 64 61 74 61 62 61 73 65 20 68  ected database h
9640: 61 6e 64 6c 65 2c 20 67 6f 74 20 5c 22 22 2c 20  andle, got \"", 
9650: 30 29 3b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65  0);.    Tcl_Appe
9660: 6e 64 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  ndResult(interp,
9670: 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 28 6f   Tcl_GetString(o
9680: 62 6a 76 5b 31 5d 29 2c 20 22 5c 22 22 2c 20 30  bjv[1]), "\"", 0
9690: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43  );.    return TC
96a0: 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 65 6c 73 65  L_ERROR;.  }else
96b0: 7b 0a 20 20 20 20 64 62 20 3d 20 2a 28 73 71 6c  {.    db = *(sql
96c0: 69 74 65 33 20 2a 2a 29 63 6d 64 49 6e 66 6f 2e  ite3 **)cmdInfo.
96d0: 6f 62 6a 43 6c 69 65 6e 74 44 61 74 61 3b 0a 20  objClientData;. 
96e0: 20 7d 0a 0a 20 20 72 63 20 3d 20 54 63 6c 5f 47   }..  rc = Tcl_G
96f0: 65 74 49 6e 64 65 78 46 72 6f 6d 4f 62 6a 53 74  etIndexFromObjSt
9700: 72 75 63 74 28 0a 20 20 20 20 20 20 69 6e 74 65  ruct(.      inte
9710: 72 70 2c 20 6f 62 6a 76 5b 33 5d 2c 20 61 53 75  rp, objv[3], aSu
9720: 62 2c 20 73 69 7a 65 6f 66 28 61 53 75 62 5b 30  b, sizeof(aSub[0
9730: 5d 29 2c 20 22 73 75 62 2d 63 6f 6d 6d 61 6e 64  ]), "sub-command
9740: 22 2c 20 30 2c 20 26 69 64 78 0a 20 20 29 3b 0a  ", 0, &idx.  );.
9750: 20 20 69 66 28 20 72 63 21 3d 54 43 4c 5f 4f 4b    if( rc!=TCL_OK
9760: 20 29 20 72 65 74 75 72 6e 20 72 63 3b 0a 0a 20   ) return rc;.. 
9770: 20 73 77 69 74 63 68 28 20 61 53 75 62 5b 69 64   switch( aSub[id
9780: 78 5d 2e 61 72 67 74 79 70 65 20 29 7b 0a 20 20  x].argtype ){.  
9790: 20 20 63 61 73 65 20 31 3a 0a 20 20 20 20 20 20    case 1:.      
97a0: 69 66 28 20 54 63 6c 5f 47 65 74 49 6e 74 46 72  if( Tcl_GetIntFr
97b0: 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f 62  omObj(interp, ob
97c0: 6a 76 5b 34 5d 2c 20 26 69 56 61 6c 75 65 29 20  jv[4], &iValue) 
97d0: 29 7b 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ){.        retur
97e0: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 20  n TCL_ERROR;.   
97f0: 20 20 20 7d 0a 20 20 20 20 20 20 70 41 72 67 20     }.      pArg 
9800: 3d 20 28 76 6f 69 64 20 2a 29 26 69 56 61 6c 75  = (void *)&iValu
9810: 65 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  e;.      break;.
9820: 20 20 20 20 64 65 66 61 75 6c 74 3a 0a 20 20 20      default:.   
9830: 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41     Tcl_WrongNumA
9840: 72 67 73 28 69 6e 74 65 72 70 2c 20 34 2c 20 6f  rgs(interp, 4, o
9850: 62 6a 76 2c 20 22 53 55 42 2d 43 4f 4d 4d 41 4e  bjv, "SUB-COMMAN
9860: 44 22 29 3b 0a 20 20 20 20 20 20 72 65 74 75 72  D");.      retur
9870: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d  n TCL_ERROR;.  }
9880: 0a 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33  ..  rc = sqlite3
9890: 5f 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 64 62  _file_control(db
98a0: 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 28  , Tcl_GetString(
98b0: 6f 62 6a 76 5b 32 5d 29 2c 20 61 53 75 62 5b 69  objv[2]), aSub[i
98c0: 64 78 5d 2e 6f 70 2c 20 70 41 72 67 29 3b 0a 20  dx].op, pArg);. 
98d0: 20 54 63 6c 5f 53 65 74 52 65 73 75 6c 74 28 69   Tcl_SetResult(i
98e0: 6e 74 65 72 70 2c 20 28 63 68 61 72 20 2a 29 73  nterp, (char *)s
98f0: 71 6c 69 74 65 33 54 65 73 74 45 72 72 6f 72 4e  qlite3TestErrorN
9900: 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f 53 54 41  ame(rc), TCL_STA
9910: 54 49 43 29 3b 0a 20 20 72 65 74 75 72 6e 20 28  TIC);.  return (
9920: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 29 20 3f  rc==SQLITE_OK) ?
9930: 20 54 43 4c 5f 4f 4b 20 3a 20 54 43 4c 5f 45 52   TCL_OK : TCL_ER
9940: 52 4f 52 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68  ROR;.}../*.** Th
9950: 69 73 20 72 6f 75 74 69 6e 65 20 72 65 67 69 73  is routine regis
9960: 74 65 72 73 20 74 68 65 20 63 75 73 74 6f 6d 20  ters the custom 
9970: 54 43 4c 20 63 6f 6d 6d 61 6e 64 73 20 64 65 66  TCL commands def
9980: 69 6e 65 64 20 69 6e 20 74 68 69 73 0a 2a 2a 20  ined in this.** 
9990: 6d 6f 64 75 6c 65 2e 20 20 54 68 69 73 20 73 68  module.  This sh
99a0: 6f 75 6c 64 20 62 65 20 74 68 65 20 6f 6e 6c 79  ould be the only
99b0: 20 70 72 6f 63 65 64 75 72 65 20 76 69 73 69 62   procedure visib
99c0: 6c 65 20 66 72 6f 6d 20 6f 75 74 73 69 64 65 0a  le from outside.
99d0: 2a 2a 20 6f 66 20 74 68 69 73 20 6d 6f 64 75 6c  ** of this modul
99e0: 65 2e 0a 2a 2f 0a 69 6e 74 20 53 71 6c 69 74 65  e..*/.int Sqlite
99f0: 6d 75 6c 74 69 70 6c 65 78 5f 49 6e 69 74 28 54  multiplex_Init(T
9a00: 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72  cl_Interp *inter
9a10: 70 29 7b 0a 20 20 73 74 61 74 69 63 20 73 74 72  p){.  static str
9a20: 75 63 74 20 7b 0a 20 20 20 20 20 63 68 61 72 20  uct {.     char 
9a30: 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 20 54 63 6c  *zName;.     Tcl
9a40: 5f 4f 62 6a 43 6d 64 50 72 6f 63 20 2a 78 50 72  _ObjCmdProc *xPr
9a50: 6f 63 3b 0a 20 20 7d 20 61 43 6d 64 5b 5d 20 3d  oc;.  } aCmd[] =
9a60: 20 7b 0a 20 20 20 20 7b 20 22 73 71 6c 69 74 65   {.    { "sqlite
9a70: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  3_multiplex_init
9a80: 69 61 6c 69 7a 65 22 2c 20 74 65 73 74 5f 6d 75  ialize", test_mu
9a90: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
9aa0: 7a 65 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c  ze },.    { "sql
9ab0: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73  ite3_multiplex_s
9ac0: 68 75 74 64 6f 77 6e 22 2c 20 74 65 73 74 5f 6d  hutdown", test_m
9ad0: 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77  ultiplex_shutdow
9ae0: 6e 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c 69  n },.    { "sqli
9af0: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75  te3_multiplex_du
9b00: 6d 70 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70  mp", test_multip
9b10: 6c 65 78 5f 64 75 6d 70 20 7d 2c 0a 20 20 20 20  lex_dump },.    
9b20: 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69  { "sqlite3_multi
9b30: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 74  plex_control", t
9b40: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 63 6f  est_multiplex_co
9b50: 6e 74 72 6f 6c 20 7d 2c 0a 20 20 7d 3b 0a 20 20  ntrol },.  };.  
9b60: 69 6e 74 20 69 3b 0a 0a 20 20 66 6f 72 28 69 3d  int i;..  for(i=
9b70: 30 3b 20 69 3c 73 69 7a 65 6f 66 28 61 43 6d 64  0; i<sizeof(aCmd
9b80: 29 2f 73 69 7a 65 6f 66 28 61 43 6d 64 5b 30 5d  )/sizeof(aCmd[0]
9b90: 29 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 54 63 6c  ); i++){.    Tcl
9ba0: 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d 6d 61 6e  _CreateObjComman
9bb0: 64 28 69 6e 74 65 72 70 2c 20 61 43 6d 64 5b 69  d(interp, aCmd[i
9bc0: 5d 2e 7a 4e 61 6d 65 2c 20 61 43 6d 64 5b 69 5d  ].zName, aCmd[i]
9bd0: 2e 78 50 72 6f 63 2c 20 30 2c 20 30 29 3b 0a 20  .xProc, 0, 0);. 
9be0: 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c   }..  return TCL
9bf0: 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64 69 66 0a        _OK;.}.#endif.