/ Hex Artifact Content
Login

Artifact 731fb740a9fd4b11cb7b1990c62fc88d01c90dfd:


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 31 20 47 69 42 20 70 69 65  p into 1 GiB pie
0710: 63 65 73 2c 20 73 6f 20 74 68 61 74 20 74 68 65  ces, so that the
0720: 79 20 77 69 6c 6c 20 77 6f 72 6b 20 65 76 65 6e  y will work even
0730: 20 6f 6e 20 66 69 6c 65 73 79 73 74 65 6d 73 0a   on filesystems.
0740: 2a 2a 20 74 68 61 74 20 64 6f 20 6e 6f 74 20 73  ** that do not s
0750: 75 70 70 6f 72 74 20 6c 61 72 67 65 20 66 69 6c  upport large fil
0760: 65 73 2e 0a 2a 2f 0a 23 69 6e 63 6c 75 64 65 20  es..*/.#include 
0770: 22 73 71 6c 69 74 65 33 2e 68 22 0a 23 69 6e 63  "sqlite3.h".#inc
0780: 6c 75 64 65 20 3c 73 74 72 69 6e 67 2e 68 3e 0a  lude <string.h>.
0790: 23 69 6e 63 6c 75 64 65 20 3c 61 73 73 65 72 74  #include <assert
07a0: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 73 74  .h>.#include <st
07b0: 64 6c 69 62 2e 68 3e 0a 23 69 6e 63 6c 75 64 65  dlib.h>.#include
07c0: 20 22 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78   "test_multiplex
07d0: 2e 68 22 0a 0a 23 69 66 6e 64 65 66 20 53 51 4c  .h"..#ifndef SQL
07e0: 49 54 45 5f 43 4f 52 45 0a 20 20 23 64 65 66 69  ITE_CORE.  #defi
07f0: 6e 65 20 53 51 4c 49 54 45 5f 43 4f 52 45 20 31  ne SQLITE_CORE 1
0800: 20 20 2f 2a 20 44 69 73 61 62 6c 65 20 74 68 65    /* Disable the
0810: 20 41 50 49 20 72 65 64 65 66 69 6e 69 74 69 6f   API redefinitio
0820: 6e 20 69 6e 20 73 71 6c 69 74 65 33 65 78 74 2e  n in sqlite3ext.
0830: 68 20 2a 2f 0a 23 65 6e 64 69 66 0a 23 69 6e 63  h */.#endif.#inc
0840: 6c 75 64 65 20 22 73 71 6c 69 74 65 33 65 78 74  lude "sqlite3ext
0850: 2e 68 22 0a 0a 2f 2a 20 0a 2a 2a 20 54 68 65 73  .h"../* .** Thes
0860: 65 20 73 68 6f 75 6c 64 20 62 65 20 64 65 66 69  e should be defi
0870: 6e 65 64 20 74 6f 20 62 65 20 74 68 65 20 73 61  ned to be the sa
0880: 6d 65 20 61 73 20 74 68 65 20 76 61 6c 75 65 73  me as the values
0890: 20 69 6e 20 0a 2a 2a 20 73 71 6c 69 74 65 49 6e   in .** sqliteIn
08a0: 74 2e 68 2e 20 20 54 68 65 79 20 61 72 65 20 64  t.h.  They are d
08b0: 65 66 69 6e 65 64 20 73 65 70 65 72 61 74 65 6c  efined seperatel
08c0: 79 20 68 65 72 65 20 73 6f 20 74 68 61 74 0a 2a  y here so that.*
08d0: 2a 20 74 68 65 20 6d 75 6c 74 69 70 6c 65 78 20  * the multiplex 
08e0: 56 46 53 20 73 68 69 6d 20 63 61 6e 20 62 65 20  VFS shim can be 
08f0: 62 75 69 6c 74 20 61 73 20 61 20 6c 6f 61 64 61  built as a loada
0900: 62 6c 65 20 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 0a  ble .** module..
0910: 2a 2f 0a 23 64 65 66 69 6e 65 20 55 4e 55 53 45  */.#define UNUSE
0920: 44 5f 50 41 52 41 4d 45 54 45 52 28 78 29 20 28  D_PARAMETER(x) (
0930: 76 6f 69 64 29 28 78 29 0a 23 64 65 66 69 6e 65  void)(x).#define
0940: 20 4d 41 58 5f 50 41 47 45 5f 53 49 5a 45 20 20   MAX_PAGE_SIZE  
0950: 20 20 20 20 20 30 78 31 30 30 30 30 0a 23 64 65       0x10000.#de
0960: 66 69 6e 65 20 44 45 46 41 55 4c 54 5f 53 45 43  fine DEFAULT_SEC
0970: 54 4f 52 5f 53 49 5a 45 20 30 78 31 30 30 30 0a  TOR_SIZE 0x1000.
0980: 0a 2f 2a 0a 2a 2a 20 46 6f 72 20 61 20 62 75 69  ./*.** For a bui
0990: 6c 64 20 77 69 74 68 6f 75 74 20 6d 75 74 65 78  ld without mutex
09a0: 65 73 2c 20 6e 6f 2d 6f 70 20 74 68 65 20 6d 75  es, no-op the mu
09b0: 74 65 78 20 63 61 6c 6c 73 2e 0a 2a 2f 0a 23 69  tex calls..*/.#i
09c0: 66 20 64 65 66 69 6e 65 64 28 53 51 4c 49 54 45  f defined(SQLITE
09d0: 5f 54 48 52 45 41 44 53 41 46 45 29 20 26 26 20  _THREADSAFE) && 
09e0: 53 51 4c 49 54 45 5f 54 48 52 45 41 44 53 41 46  SQLITE_THREADSAF
09f0: 45 3d 3d 30 0a 23 64 65 66 69 6e 65 20 73 71 6c  E==0.#define sql
0a00: 69 74 65 33 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63  ite3_mutex_alloc
0a10: 28 58 29 20 20 20 20 28 28 73 71 6c 69 74 65 33  (X)    ((sqlite3
0a20: 5f 6d 75 74 65 78 2a 29 38 29 0a 23 64 65 66 69  _mutex*)8).#defi
0a30: 6e 65 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  ne sqlite3_mutex
0a40: 5f 66 72 65 65 28 58 29 0a 23 64 65 66 69 6e 65  _free(X).#define
0a50: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 65   sqlite3_mutex_e
0a60: 6e 74 65 72 28 58 29 0a 23 64 65 66 69 6e 65 20  nter(X).#define 
0a70: 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 74 72  sqlite3_mutex_tr
0a80: 79 28 58 29 20 20 20 20 20 20 53 51 4c 49 54 45  y(X)      SQLITE
0a90: 5f 4f 4b 0a 23 64 65 66 69 6e 65 20 73 71 6c 69  _OK.#define sqli
0aa0: 74 65 33 5f 6d 75 74 65 78 5f 6c 65 61 76 65 28  te3_mutex_leave(
0ab0: 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74  X).#define sqlit
0ac0: 65 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28 58 29  e3_mutex_held(X)
0ad0: 20 20 20 20 20 28 28 76 6f 69 64 29 28 58 29 2c       ((void)(X),
0ae0: 31 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74  1).#define sqlit
0af0: 65 33 5f 6d 75 74 65 78 5f 6e 6f 74 68 65 6c 64  e3_mutex_notheld
0b00: 28 58 29 20 20 28 28 76 6f 69 64 29 28 58 29 2c  (X)  ((void)(X),
0b10: 31 29 0a 23 65 6e 64 69 66 20 2f 2a 20 53 51 4c  1).#endif /* SQL
0b20: 49 54 45 5f 54 48 52 45 41 44 53 41 46 45 3d 3d  ITE_THREADSAFE==
0b30: 30 20 2a 2f 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  0 */.../********
0b40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0b50: 20 53 68 69 6d 20 44 65 66 69 6e 69 74 69 6f 6e   Shim Definition
0b60: 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  s **************
0b70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0b80: 2f 0a 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54  /..#ifndef SQLIT
0b90: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f  E_MULTIPLEX_VFS_
0ba0: 4e 41 4d 45 0a 23 20 64 65 66 69 6e 65 20 53 51  NAME.# define SQ
0bb0: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56  LITE_MULTIPLEX_V
0bc0: 46 53 5f 4e 41 4d 45 20 22 6d 75 6c 74 69 70 6c  FS_NAME "multipl
0bd0: 65 78 22 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 54  ex".#endif../* T
0be0: 68 69 73 20 69 73 20 74 68 65 20 6c 69 6d 69 74  his is the limit
0bf0: 20 6f 6e 20 74 68 65 20 63 68 75 6e 6b 20 73 69   on the chunk si
0c00: 7a 65 2e 20 20 49 74 20 6d 61 79 20 62 65 20 63  ze.  It may be c
0c10: 68 61 6e 67 65 64 20 62 79 20 63 61 6c 6c 69 6e  hanged by callin
0c20: 67 0a 2a 2a 20 74 68 65 20 78 46 69 6c 65 43 6f  g.** the xFileCo
0c30: 6e 74 72 6f 6c 28 29 20 69 6e 74 65 72 66 61 63  ntrol() interfac
0c40: 65 2e 20 20 49 74 20 77 69 6c 6c 20 62 65 20 72  e.  It will be r
0c50: 6f 75 6e 64 65 64 20 75 70 20 74 6f 20 61 20 0a  ounded up to a .
0c60: 2a 2a 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d  ** multiple of M
0c70: 41 58 5f 50 41 47 45 5f 53 49 5a 45 2e 20 20 57  AX_PAGE_SIZE.  W
0c80: 65 20 64 65 66 61 75 6c 74 20 69 74 20 68 65 72  e default it her
0c90: 65 20 74 6f 20 32 47 69 42 20 6c 65 73 73 20 36  e to 2GiB less 6
0ca0: 34 4b 69 42 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66  4KiB..*/.#ifndef
0cb0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0cc0: 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 0a 23 20 64  X_CHUNK_SIZE.# d
0cd0: 65 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c  efine SQLITE_MUL
0ce0: 54 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a  TIPLEX_CHUNK_SIZ
0cf0: 45 20 32 31 34 37 34 31 38 31 31 32 0a 23 65 6e  E 2147418112.#en
0d00: 64 69 66 0a 0a 2f 2a 20 44 65 66 61 75 6c 74 20  dif../* Default 
0d10: 6c 69 6d 69 74 20 6f 6e 20 6e 75 6d 62 65 72 20  limit on number 
0d20: 6f 66 20 63 68 75 6e 6b 73 2e 20 20 43 61 72 65  of chunks.  Care
0d30: 20 73 68 6f 75 6c 64 20 62 65 20 74 61 6b 65 6e   should be taken
0d40: 0a 2a 2a 20 73 6f 20 74 68 61 74 20 76 61 6c 75  .** so that valu
0d50: 65 73 20 66 6f 72 20 63 68 75 6e 6b 73 20 6e 75  es for chunks nu
0d60: 6d 62 65 72 73 20 66 69 74 20 69 6e 20 74 68 65  mbers fit in the
0d70: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0d80: 58 5f 45 58 54 5f 46 4d 54 0a 2a 2a 20 66 6f 72  X_EXT_FMT.** for
0d90: 6d 61 74 20 73 70 65 63 69 66 69 65 72 2e 20 49  mat specifier. I
0da0: 74 20 6d 61 79 20 62 65 20 63 68 61 6e 67 65 64  t may be changed
0db0: 20 62 79 20 63 61 6c 6c 69 6e 67 0a 2a 2a 20 74   by calling.** t
0dc0: 68 65 20 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28  he xFileControl(
0dd0: 29 20 69 6e 74 65 72 66 61 63 65 2e 0a 2a 2f 0a  ) interface..*/.
0de0: 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f 4d  #ifndef SQLITE_M
0df0: 55 4c 54 49 50 4c 45 58 5f 4d 41 58 5f 43 48 55  ULTIPLEX_MAX_CHU
0e00: 4e 4b 53 0a 23 20 64 65 66 69 6e 65 20 53 51 4c  NKS.# define SQL
0e10: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4d 41  ITE_MULTIPLEX_MA
0e20: 58 5f 43 48 55 4e 4b 53 20 33 32 0a 23 65 6e 64  X_CHUNKS 32.#end
0e30: 69 66 0a 0a 2f 2a 20 49 66 20 53 51 4c 49 54 45  if../* If SQLITE
0e40: 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 4f  _MULTIPLEX_EXT_O
0e50: 56 57 52 20 69 73 20 64 65 66 69 6e 65 64 2c 20  VWR is defined, 
0e60: 74 68 65 20 0a 2a 2a 20 6c 61 73 74 20 53 51 4c  the .** last SQL
0e70: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
0e80: 54 5f 53 5a 20 63 68 61 72 61 63 74 65 72 73 20  T_SZ characters 
0e90: 6f 66 20 74 68 65 20 0a 2a 2a 20 66 69 6c 65 6e  of the .** filen
0ea0: 61 6d 65 20 77 69 6c 6c 20 62 65 20 6f 76 65 72  ame will be over
0eb0: 77 72 69 74 74 65 6e 2c 20 6f 74 68 65 72 77 69  written, otherwi
0ec0: 73 65 2c 20 74 68 65 20 0a 2a 2a 20 6d 75 6c 74  se, the .** mult
0ed0: 69 70 6c 65 78 20 65 78 74 65 6e 73 69 6f 6e 20  iplex extension 
0ee0: 69 73 20 73 69 6d 70 6c 79 20 61 70 70 65 6e 64  is simply append
0ef0: 65 64 20 74 6f 20 74 68 65 20 66 69 6c 65 6e 61  ed to the filena
0f00: 6d 65 2e 0a 2a 2a 20 45 78 2e 20 20 28 75 6e 64  me..** Ex.  (und
0f10: 65 66 69 6e 65 64 29 20 74 65 73 74 2e 64 62 20  efined) test.db 
0f20: 2d 3e 20 74 65 73 74 2e 64 62 30 31 0a 2a 2a 20  -> test.db01.** 
0f30: 20 20 20 20 20 28 64 65 66 69 6e 65 64 29 20 20       (defined)  
0f40: 20 74 65 73 74 2e 64 62 20 2d 3e 20 74 65 73 74   test.db -> test
0f50: 2e 30 31 0a 2a 2a 20 43 68 75 6e 6b 20 30 20 64  .01.** Chunk 0 d
0f60: 6f 65 73 20 6e 6f 74 20 68 61 76 65 20 61 20 6d  oes not have a m
0f70: 6f 64 69 66 69 65 64 20 65 78 74 65 6e 73 69 6f  odified extensio
0f80: 6e 2e 0a 2a 2f 0a 23 64 65 66 69 6e 65 20 53 51  n..*/.#define SQ
0f90: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
0fa0: 58 54 5f 46 4d 54 20 20 20 20 22 25 30 32 64 22  XT_FMT    "%02d"
0fb0: 0a 23 64 65 66 69 6e 65 20 53 51 4c 49 54 45 5f  .#define SQLITE_
0fc0: 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a  MULTIPLEX_EXT_SZ
0fd0: 20 20 20 20 20 32 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a       2../*******
0fe0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0ff0: 2a 20 4f 62 6a 65 63 74 20 44 65 66 69 6e 69 74  * Object Definit
1000: 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ions ***********
1010: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1020: 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72 77 61 72 64  ***/../* Forward
1030: 20 64 65 63 6c 61 72 61 74 69 6f 6e 20 6f 66 20   declaration of 
1040: 61 6c 6c 20 6f 62 6a 65 63 74 20 74 79 70 65 73  all object types
1050: 20 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72 75   */.typedef stru
1060: 63 74 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  ct multiplexGrou
1070: 70 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  p multiplexGroup
1080: 3b 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74  ;.typedef struct
1090: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 6d   multiplexConn m
10a0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 3b 0a 0a 2f  ultiplexConn;../
10b0: 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74 69 70 6c 65  *.** A "multiple
10c0: 78 20 67 72 6f 75 70 22 20 69 73 20 61 20 63 6f  x group" is a co
10d0: 6c 6c 65 63 74 69 6f 6e 20 6f 66 20 66 69 6c 65  llection of file
10e0: 73 20 74 68 61 74 20 63 6f 6c 6c 65 63 74 69 76  s that collectiv
10f0: 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75 70 20 61 20  ely.** makeup a 
1100: 73 69 6e 67 6c 65 20 53 51 4c 69 74 65 20 44 42  single SQLite DB
1110: 20 66 69 6c 65 2e 20 20 54 68 69 73 20 61 6c 6c   file.  This all
1120: 6f 77 73 20 74 68 65 20 73 69 7a 65 20 6f 66 20  ows the size of 
1130: 74 68 65 20 44 42 0a 2a 2a 20 74 6f 20 65 78 63  the DB.** to exc
1140: 65 65 64 20 74 68 65 20 6c 69 6d 69 74 73 20 69  eed the limits i
1150: 6d 70 6f 73 65 64 20 62 79 20 74 68 65 20 66 69  mposed by the fi
1160: 6c 65 20 73 79 73 74 65 6d 2e 0a 2a 2a 0a 2a 2a  le system..**.**
1170: 20 54 68 65 72 65 20 69 73 20 61 6e 20 69 6e 73   There is an ins
1180: 74 61 6e 63 65 20 6f 66 20 74 68 65 20 66 6f 6c  tance of the fol
1190: 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74 20 66 6f  lowing object fo
11a0: 72 20 65 61 63 68 20 64 65 66 69 6e 65 64 20 6d  r each defined m
11b0: 75 6c 74 69 70 6c 65 78 0a 2a 2a 20 67 72 6f 75  ultiplex.** grou
11c0: 70 2e 0a 2a 2f 0a 73 74 72 75 63 74 20 6d 75 6c  p..*/.struct mul
11d0: 74 69 70 6c 65 78 47 72 6f 75 70 20 7b 0a 20 20  tiplexGroup {.  
11e0: 73 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78  struct multiplex
11f0: 52 65 61 6c 20 7b 20 20 20 20 20 20 20 20 20 20  Real {          
1200: 20 2f 2a 20 46 6f 72 20 65 61 63 68 20 63 68 75   /* For each chu
1210: 6e 6b 20 2a 2f 0a 20 20 20 20 73 71 6c 69 74 65  nk */.    sqlite
1220: 33 5f 66 69 6c 65 20 2a 70 3b 20 20 20 20 20 20  3_file *p;      
1230: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48              /* H
1240: 61 6e 64 6c 65 20 66 6f 72 20 74 68 65 20 63 68  andle for the ch
1250: 75 6e 6b 20 2a 2f 0a 20 20 20 20 63 68 61 72 20  unk */.    char 
1260: 2a 7a 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  *z;             
1270: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
1280: 4e 61 6d 65 20 6f 66 20 74 68 69 73 20 63 68 75  Name of this chu
1290: 6e 6b 20 2a 2f 0a 20 20 7d 20 2a 61 52 65 61 6c  nk */.  } *aReal
12a0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
12b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 6c 69 73 74           /* list
12c0: 20 6f 66 20 61 6c 6c 20 63 68 75 6e 6b 73 20 2a   of all chunks *
12d0: 2f 0a 20 20 69 6e 74 20 6e 52 65 61 6c 3b 20 20  /.  int nReal;  
12e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12f0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
1300: 66 20 63 68 75 6e 6b 73 20 2a 2f 0a 20 20 63 68  f chunks */.  ch
1310: 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20 20  ar *zName;      
1320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
1330: 2a 20 42 61 73 65 20 66 69 6c 65 6e 61 6d 65 20  * Base filename 
1340: 6f 66 20 74 68 69 73 20 67 72 6f 75 70 20 2a 2f  of this group */
1350: 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 20 20 20  .  int nName;   
1360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1370: 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66      /* Length of
1380: 20 62 61 73 65 20 66 69 6c 65 6e 61 6d 65 20 2a   base filename *
1390: 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 3b 20 20  /.  int flags;  
13a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13b0: 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20 75 73       /* Flags us
13c0: 65 64 20 66 6f 72 20 6f 72 69 67 69 6e 61 6c 20  ed for original 
13d0: 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 75 6e 73  opening */.  uns
13e0: 69 67 6e 65 64 20 69 6e 74 20 73 7a 43 68 75 6e  igned int szChun
13f0: 6b 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  k;            /*
1400: 20 43 68 75 6e 6b 20 73 69 7a 65 20 75 73 65 64   Chunk size used
1410: 20 66 6f 72 20 74 68 69 73 20 67 72 6f 75 70 20   for this group 
1420: 2a 2f 0a 20 20 69 6e 74 20 62 45 6e 61 62 6c 65  */.  int bEnable
1430: 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d;              
1440: 20 20 20 20 20 20 2f 2a 20 54 52 55 45 20 74 6f        /* TRUE to
1450: 20 75 73 65 20 4d 75 6c 74 69 70 6c 65 78 20 56   use Multiplex V
1460: 46 53 20 66 6f 72 20 74 68 69 73 20 66 69 6c 65  FS for this file
1470: 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47   */.  multiplexG
1480: 72 6f 75 70 20 2a 70 4e 65 78 74 2c 20 2a 70 50  roup *pNext, *pP
1490: 72 65 76 3b 20 20 20 2f 2a 20 44 6f 75 62 6c 79  rev;   /* Doubly
14a0: 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20 6f 66 20   linked list of 
14b0: 61 6c 6c 20 67 72 6f 75 70 20 6f 62 6a 65 63 74  all group object
14c0: 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41  s */.};../*.** A
14d0: 6e 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68  n instance of th
14e0: 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65  e following obje
14f0: 63 74 20 72 65 70 72 65 73 65 6e 74 73 20 65 61  ct represents ea
1500: 63 68 20 6f 70 65 6e 20 63 6f 6e 6e 65 63 74 69  ch open connecti
1510: 6f 6e 0a 2a 2a 20 74 6f 20 61 20 66 69 6c 65 20  on.** to a file 
1520: 74 68 61 74 20 69 73 20 6d 75 6c 74 69 70 6c 65  that is multiple
1530: 78 27 65 64 2e 20 20 54 68 69 73 20 6f 62 6a 65  x'ed.  This obje
1540: 63 74 20 69 73 20 61 20 0a 2a 2a 20 73 75 62 63  ct is a .** subc
1550: 6c 61 73 73 20 6f 66 20 73 71 6c 69 74 65 33 5f  lass of sqlite3_
1560: 66 69 6c 65 2e 20 20 54 68 65 20 73 71 6c 69 74  file.  The sqlit
1570: 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74 20 66  e3_file object f
1580: 6f 72 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e  or the underlyin
1590: 67 0a 2a 2a 20 56 46 53 20 69 73 20 61 70 70 65  g.** VFS is appe
15a0: 6e 64 65 64 20 74 6f 20 74 68 69 73 20 73 74 72  nded to this str
15b0: 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 72 75 63  ucture..*/.struc
15c0: 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20  t multiplexConn 
15d0: 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  {.  sqlite3_file
15e0: 20 62 61 73 65 3b 20 20 20 20 20 20 20 20 20 20   base;          
15f0: 20 20 20 20 2f 2a 20 42 61 73 65 20 63 6c 61 73      /* Base clas
1600: 73 20 2d 20 6d 75 73 74 20 62 65 20 66 69 72 73  s - must be firs
1610: 74 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t */.  multiplex
1620: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 3b 20 20  Group *pGroup;  
1630: 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 75 6e         /* The un
1640: 64 65 72 6c 79 69 6e 67 20 67 72 6f 75 70 20 6f  derlying group o
1650: 66 20 66 69 6c 65 73 20 2a 2f 0a 7d 3b 0a 0a 2f  f files */.};../
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 20 47 6c 6f 62 61 6c  ********* Global
1680: 20 56 61 72 69 61 62 6c 65 73 20 2a 2a 2a 2a 2a   Variables *****
1690: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
16a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f  *************/./
16b0: 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f 62 61 6c 20  *.** All global 
16c0: 76 61 72 69 61 62 6c 65 73 20 75 73 65 64 20 62  variables used b
16d0: 79 20 74 68 69 73 20 66 69 6c 65 20 61 72 65 20  y this file are 
16e0: 63 6f 6e 74 61 69 6e 69 6e 67 20 77 69 74 68 69  containing withi
16f0: 6e 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 0a  n the following.
1700: 2a 2a 20 67 4d 75 6c 74 69 70 6c 65 78 20 73 74  ** gMultiplex st
1710: 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 61 74  ructure..*/.stat
1720: 69 63 20 73 74 72 75 63 74 20 7b 0a 20 20 2f 2a  ic struct {.  /*
1730: 20 54 68 65 20 70 4f 72 69 67 56 66 73 20 69 73   The pOrigVfs is
1740: 20 74 68 65 20 72 65 61 6c 2c 20 6f 72 69 67 69   the real, origi
1750: 6e 61 6c 20 75 6e 64 65 72 6c 79 69 6e 67 20 56  nal underlying V
1760: 46 53 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f  FS implementatio
1770: 6e 2e 0a 20 20 2a 2a 20 4d 6f 73 74 20 6f 70 65  n..  ** Most ope
1780: 72 61 74 69 6f 6e 73 20 70 61 73 73 2d 74 68 72  rations pass-thr
1790: 6f 75 67 68 20 74 6f 20 74 68 65 20 72 65 61 6c  ough to the real
17a0: 20 56 46 53 2e 20 20 54 68 69 73 20 76 61 6c 75   VFS.  This valu
17b0: 65 20 69 73 20 72 65 61 64 2d 6f 6e 6c 79 0a 20  e is read-only. 
17c0: 20 2a 2a 20 64 75 72 69 6e 67 20 6f 70 65 72 61   ** during opera
17d0: 74 69 6f 6e 2e 20 20 49 74 20 69 73 20 6f 6e 6c  tion.  It is onl
17e0: 79 20 6d 6f 64 69 66 69 65 64 20 61 74 20 73 74  y modified at st
17f0: 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 74 68 75  art-time and thu
1800: 73 20 64 6f 65 73 20 6e 6f 74 0a 20 20 2a 2a 20  s does not.  ** 
1810: 72 65 71 75 69 72 65 20 61 20 6d 75 74 65 78 2e  require a mutex.
1820: 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f  .  */.  sqlite3_
1830: 76 66 73 20 2a 70 4f 72 69 67 56 66 73 3b 0a 0a  vfs *pOrigVfs;..
1840: 20 20 2f 2a 20 54 68 65 20 73 54 68 69 73 56 66    /* The sThisVf
1850: 73 20 69 73 20 74 68 65 20 56 46 53 20 73 74 72  s is the VFS str
1860: 75 63 74 75 72 65 20 75 73 65 64 20 62 79 20 74  ucture used by t
1870: 68 69 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73  his shim.  It is
1880: 20 69 6e 69 74 69 61 6c 69 7a 65 64 0a 20 20 2a   initialized.  *
1890: 2a 20 61 74 20 73 74 61 72 74 2d 74 69 6d 65 20  * at start-time 
18a0: 61 6e 64 20 74 68 75 73 20 64 6f 65 73 20 6e 6f  and thus does no
18b0: 74 20 72 65 71 75 69 72 65 20 61 20 6d 75 74 65  t require a mute
18c0: 78 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  x.  */.  sqlite3
18d0: 5f 76 66 73 20 73 54 68 69 73 56 66 73 3b 0a 0a  _vfs sThisVfs;..
18e0: 20 20 2f 2a 20 54 68 65 20 73 49 6f 4d 65 74 68    /* The sIoMeth
18f0: 6f 64 73 20 64 65 66 69 6e 65 73 20 74 68 65 20  ods defines the 
1900: 6d 65 74 68 6f 64 73 20 75 73 65 64 20 62 79 20  methods used by 
1910: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a  sqlite3_file obj
1920: 65 63 74 73 20 0a 20 20 2a 2a 20 61 73 73 6f 63  ects .  ** assoc
1930: 69 61 74 65 64 20 77 69 74 68 20 74 68 69 73 20  iated with this 
1940: 73 68 69 6d 2e 20 20 49 74 20 69 73 20 69 6e 69  shim.  It is ini
1950: 74 69 61 6c 69 7a 65 64 20 61 74 20 73 74 61 72  tialized at star
1960: 74 2d 74 69 6d 65 20 61 6e 64 20 64 6f 65 73 0a  t-time and does.
1970: 20 20 2a 2a 20 6e 6f 74 20 72 65 71 75 69 72 65    ** not require
1980: 20 61 20 6d 75 74 65 78 2e 0a 20 20 2a 2a 0a 20   a mutex..  **. 
1990: 20 2a 2a 20 57 68 65 6e 20 74 68 65 20 75 6e 64   ** When the und
19a0: 65 72 6c 79 69 6e 67 20 56 46 53 20 69 73 20 63  erlying VFS is c
19b0: 61 6c 6c 65 64 20 74 6f 20 6f 70 65 6e 20 61 20  alled to open a 
19c0: 66 69 6c 65 2c 20 69 74 20 6d 69 67 68 74 20 72  file, it might r
19d0: 65 74 75 72 6e 20 0a 20 20 2a 2a 20 65 69 74 68  eturn .  ** eith
19e0: 65 72 20 61 20 76 65 72 73 69 6f 6e 20 31 20 6f  er a version 1 o
19f0: 72 20 61 20 76 65 72 73 69 6f 6e 20 32 20 73 71  r a version 2 sq
1a00: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63  lite3_file objec
1a10: 74 2e 20 20 54 68 69 73 20 73 68 69 6d 0a 20 20  t.  This shim.  
1a20: 2a 2a 20 68 61 73 20 74 6f 20 63 72 65 61 74 65  ** has to create
1a30: 20 61 20 77 72 61 70 70 65 72 20 73 71 6c 69 74   a wrapper sqlit
1a40: 65 33 5f 66 69 6c 65 20 6f 66 20 74 68 65 20 73  e3_file of the s
1a50: 61 6d 65 20 76 65 72 73 69 6f 6e 2e 20 20 48 65  ame version.  He
1a60: 6e 63 65 0a 20 20 2a 2a 20 74 68 65 72 65 20 61  nce.  ** there a
1a70: 72 65 20 74 77 6f 20 49 2f 4f 20 6d 65 74 68 6f  re two I/O metho
1a80: 64 20 73 74 72 75 63 74 75 72 65 73 2c 20 6f 6e  d structures, on
1a90: 65 20 66 6f 72 20 76 65 72 73 69 6f 6e 20 31 20  e for version 1 
1aa0: 61 6e 64 20 74 68 65 20 6f 74 68 65 72 0a 20 20  and the other.  
1ab0: 2a 2a 20 66 6f 72 20 76 65 72 73 69 6f 6e 20 32  ** for version 2
1ac0: 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  ..  */.  sqlite3
1ad0: 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49 6f 4d  _io_methods sIoM
1ae0: 65 74 68 6f 64 73 56 31 3b 0a 20 20 73 71 6c 69  ethodsV1;.  sqli
1af0: 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73  te3_io_methods s
1b00: 49 6f 4d 65 74 68 6f 64 73 56 32 3b 0a 0a 20 20  IoMethodsV2;..  
1b10: 2f 2a 20 54 72 75 65 20 77 68 65 6e 20 74 68 69  /* True when thi
1b20: 73 20 73 68 69 6d 20 68 61 73 20 62 65 65 6e 20  s shim has been 
1b30: 69 6e 69 74 69 61 6c 69 7a 65 64 2e 0a 20 20 2a  initialized..  *
1b40: 2f 0a 20 20 69 6e 74 20 69 73 49 6e 69 74 69 61  /.  int isInitia
1b50: 6c 69 7a 65 64 3b 0a 0a 20 20 2f 2a 20 46 6f 72  lized;..  /* For
1b60: 20 72 75 6e 2d 74 69 6d 65 20 61 63 63 65 73 73   run-time access
1b70: 20 61 6e 79 20 6f 66 20 74 68 65 20 6f 74 68 65   any of the othe
1b80: 72 20 67 6c 6f 62 61 6c 20 64 61 74 61 20 73 74  r global data st
1b90: 72 75 63 74 75 72 65 73 20 69 6e 20 74 68 69 73  ructures in this
1ba0: 0a 20 20 2a 2a 20 73 68 69 6d 2c 20 74 68 65 20  .  ** shim, the 
1bb0: 66 6f 6c 6c 6f 77 69 6e 67 20 6d 75 74 65 78 20  following mutex 
1bc0: 6d 75 73 74 20 62 65 20 68 65 6c 64 2e 0a 20 20  must be held..  
1bd0: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74  */.  sqlite3_mut
1be0: 65 78 20 2a 70 4d 75 74 65 78 3b 0a 0a 20 20 2f  ex *pMutex;..  /
1bf0: 2a 20 4c 69 73 74 20 6f 66 20 6d 75 6c 74 69 70  * List of multip
1c00: 6c 65 78 47 72 6f 75 70 20 6f 62 6a 65 63 74 73  lexGroup objects
1c10: 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c  ..  */.  multipl
1c20: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 73  exGroup *pGroups
1c30: 3b 0a 7d 20 67 4d 75 6c 74 69 70 6c 65 78 3b 0a  ;.} gMultiplex;.
1c40: 0a 2f 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 20 55 74 69 6c  *********** Util
1c60: 69 74 79 20 52 6f 75 74 69 6e 65 73 20 2a 2a 2a  ity Routines ***
1c70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1c80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
1c90: 2f 2a 0a 2a 2a 20 41 63 71 75 69 72 65 20 61 6e  /*.** Acquire an
1ca0: 64 20 72 65 6c 65 61 73 65 20 74 68 65 20 6d 75  d release the mu
1cb0: 74 65 78 20 75 73 65 64 20 74 6f 20 73 65 72 69  tex used to seri
1cc0: 61 6c 69 7a 65 20 61 63 63 65 73 73 20 74 6f 20  alize access to 
1cd0: 74 68 65 0a 2a 2a 20 6c 69 73 74 20 6f 66 20 6d  the.** list of m
1ce0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 73 2e 0a  ultiplexGroups..
1cf0: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  */.static void m
1d00: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 76 6f  ultiplexEnter(vo
1d10: 69 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74  id){ sqlite3_mut
1d20: 65 78 5f 65 6e 74 65 72 28 67 4d 75 6c 74 69 70  ex_enter(gMultip
1d30: 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 73  lex.pMutex); }.s
1d40: 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69  tatic void multi
1d50: 70 6c 65 78 4c 65 61 76 65 28 76 6f 69 64 29 7b  plexLeave(void){
1d60: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 6c   sqlite3_mutex_l
1d70: 65 61 76 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e  eave(gMultiplex.
1d80: 70 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f 2a 0a 2a  pMutex); }../*.*
1d90: 2a 20 43 6f 6d 70 75 74 65 20 61 20 73 74 72 69  * Compute a stri
1da0: 6e 67 20 6c 65 6e 67 74 68 20 74 68 61 74 20 69  ng length that i
1db0: 73 20 6c 69 6d 69 74 65 64 20 74 6f 20 77 68 61  s limited to wha
1dc0: 74 20 63 61 6e 20 62 65 20 73 74 6f 72 65 64 20  t can be stored 
1dd0: 69 6e 0a 2a 2a 20 6c 6f 77 65 72 20 33 30 20 62  in.** lower 30 b
1de0: 69 74 73 20 6f 66 20 61 20 33 32 2d 62 69 74 20  its of a 32-bit 
1df0: 73 69 67 6e 65 64 20 69 6e 74 65 67 65 72 2e 0a  signed integer..
1e00: 2a 2a 0a 2a 2a 20 54 68 65 20 76 61 6c 75 65 20  **.** The value 
1e10: 72 65 74 75 72 6e 65 64 20 77 69 6c 6c 20 6e 65  returned will ne
1e20: 76 65 72 20 62 65 20 6e 65 67 61 74 69 76 65 2e  ver be negative.
1e30: 20 20 4e 6f 72 20 77 69 6c 6c 20 69 74 20 65 76    Nor will it ev
1e40: 65 72 20 62 65 20 67 72 65 61 74 65 72 0a 2a 2a  er be greater.**
1e50: 20 74 68 61 6e 20 74 68 65 20 61 63 74 75 61 6c   than the actual
1e60: 20 6c 65 6e 67 74 68 20 6f 66 20 74 68 65 20 73   length of the s
1e70: 74 72 69 6e 67 2e 20 20 46 6f 72 20 76 65 72 79  tring.  For very
1e80: 20 6c 6f 6e 67 20 73 74 72 69 6e 67 73 20 28 67   long strings (g
1e90: 72 65 61 74 65 72 0a 2a 2a 20 74 68 61 6e 20 31  reater.** than 1
1ea0: 47 69 42 29 20 74 68 65 20 76 61 6c 75 65 20 72  GiB) the value r
1eb0: 65 74 75 72 6e 65 64 20 6d 69 67 68 74 20 62 65  eturned might be
1ec0: 20 6c 65 73 73 20 74 68 61 6e 20 74 68 65 20 74   less than the t
1ed0: 72 75 65 20 73 74 72 69 6e 67 20 6c 65 6e 67 74  rue string lengt
1ee0: 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  h..*/.static int
1ef0: 20 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c 65 6e   multiplexStrlen
1f00: 33 30 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  30(const char *z
1f10: 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  ){.  const char 
1f20: 2a 7a 32 20 3d 20 7a 3b 0a 20 20 69 66 28 20 7a  *z2 = z;.  if( z
1f30: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a  ==0 ) return 0;.
1f40: 20 20 77 68 69 6c 65 28 20 2a 7a 32 20 29 7b 20    while( *z2 ){ 
1f50: 7a 32 2b 2b 3b 20 7d 0a 20 20 72 65 74 75 72 6e  z2++; }.  return
1f60: 20 30 78 33 66 66 66 66 66 66 66 20 26 20 28 69   0x3fffffff & (i
1f70: 6e 74 29 28 7a 32 20 2d 20 7a 29 3b 0a 7d 0a 0a  nt)(z2 - z);.}..
1f80: 2f 2a 0a 2a 2a 20 43 72 65 61 74 65 20 61 20 74  /*.** Create a t
1f90: 65 6d 70 6f 72 61 72 79 20 66 69 6c 65 20 6e 61  emporary file na
1fa0: 6d 65 20 69 6e 20 7a 42 75 66 2e 20 20 7a 42 75  me in zBuf.  zBu
1fb0: 66 20 6d 75 73 74 20 62 65 20 62 69 67 20 65 6e  f must be big en
1fc0: 6f 75 67 68 20 74 6f 0a 2a 2a 20 68 6f 6c 64 20  ough to.** hold 
1fd0: 61 74 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  at pOrigVfs->mxP
1fe0: 61 74 68 6e 61 6d 65 20 63 68 61 72 61 63 74 65  athname characte
1ff0: 72 73 2e 20 20 54 68 69 73 20 66 75 6e 63 74 69  rs.  This functi
2000: 6f 6e 20 64 65 70 61 72 74 73 0a 2a 2a 20 66 72  on departs.** fr
2010: 6f 6d 20 74 68 65 20 74 72 61 64 69 74 69 6f 6e  om the tradition
2020: 61 6c 20 74 65 6d 70 6f 72 61 72 79 20 6e 61 6d  al temporary nam
2030: 65 20 67 65 6e 65 72 61 74 69 6f 6e 20 69 6e 20  e generation in 
2040: 74 68 65 20 6f 73 5f 77 69 6e 0a 2a 2a 20 61 6e  the os_win.** an
2050: 64 20 6f 73 5f 75 6e 69 78 20 56 46 53 20 69 6e  d os_unix VFS in
2060: 20 73 65 76 65 72 61 6c 20 77 61 79 73 2c 20 62   several ways, b
2070: 75 74 20 69 73 20 6e 65 63 65 73 73 61 72 79 20  ut is necessary 
2080: 73 6f 20 74 68 61 74 20 0a 2a 2a 20 74 68 65 20  so that .** the 
2090: 66 69 6c 65 20 6e 61 6d 65 20 69 73 20 6b 6e 6f  file name is kno
20a0: 77 6e 20 66 6f 72 20 74 65 6d 70 6f 72 61 72 79  wn for temporary
20b0: 20 66 69 6c 65 73 20 28 6c 69 6b 65 20 74 68 6f   files (like tho
20c0: 73 65 20 75 73 65 64 20 0a 2a 2a 20 64 75 72 69  se used .** duri
20d0: 6e 67 20 76 61 63 75 75 6d 2e 29 0a 2a 2a 0a 2a  ng vacuum.).**.*
20e0: 2a 20 4e 2e 42 2e 20 54 68 69 73 20 72 6f 75 74  * N.B. This rout
20f0: 69 6e 65 20 61 73 73 75 6d 65 73 20 79 6f 75 72  ine assumes your
2100: 20 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20   underlying VFS 
2110: 69 73 20 6f 6b 20 77 69 74 68 20 75 73 69 6e 67  is ok with using
2120: 0a 2a 2a 20 22 2f 22 20 61 73 20 61 20 64 69 72  .** "/" as a dir
2130: 65 63 74 6f 72 79 20 73 65 70 65 72 61 74 6f 72  ectory seperator
2140: 2e 20 20 54 68 69 73 20 69 73 20 74 68 65 20 64  .  This is the d
2150: 65 66 61 75 6c 74 20 66 6f 72 20 55 4e 49 58 73  efault for UNIXs
2160: 0a 2a 2a 20 61 6e 64 20 69 73 20 61 6c 6c 6f 77  .** and is allow
2170: 65 64 20 28 65 76 65 6e 20 6d 69 78 65 64 29 20  ed (even mixed) 
2180: 66 6f 72 20 6d 6f 73 74 20 76 65 72 73 69 6f 6e  for most version
2190: 73 20 6f 66 20 57 69 6e 64 6f 77 73 2e 0a 2a 2f  s of Windows..*/
21a0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
21b0: 69 70 6c 65 78 47 65 74 54 65 6d 70 6e 61 6d 65  iplexGetTempname
21c0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f  (sqlite3_vfs *pO
21d0: 72 69 67 56 66 73 2c 20 69 6e 74 20 6e 42 75 66  rigVfs, int nBuf
21e0: 2c 20 63 68 61 72 20 2a 7a 42 75 66 29 7b 0a 20  , char *zBuf){. 
21f0: 20 73 74 61 74 69 63 20 63 68 61 72 20 7a 43 68   static char zCh
2200: 61 72 73 5b 5d 20 3d 0a 20 20 20 20 22 61 62 63  ars[] =.    "abc
2210: 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73  defghijklmnopqrs
2220: 74 75 76 77 78 79 7a 22 0a 20 20 20 20 22 41 42  tuvwxyz".    "AB
2230: 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52  CDEFGHIJKLMNOPQR
2240: 53 54 55 56 57 58 59 5a 22 0a 20 20 20 20 22 30  STUVWXYZ".    "0
2250: 31 32 33 34 35 36 37 38 39 22 3b 0a 20 20 69 6e  123456789";.  in
2260: 74 20 69 2c 6a 3b 0a 20 20 69 6e 74 20 61 74 74  t i,j;.  int att
2270: 65 6d 70 74 73 20 3d 20 30 3b 0a 20 20 69 6e 74  empts = 0;.  int
2280: 20 65 78 69 73 74 73 20 3d 20 30 3b 0a 20 20 69   exists = 0;.  i
2290: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 45  nt rc = SQLITE_E
22a0: 52 52 4f 52 3b 0a 0a 20 20 2f 2a 20 43 68 65 63  RROR;..  /* Chec
22b0: 6b 20 74 68 61 74 20 74 68 65 20 6f 75 74 70 75  k that the outpu
22c0: 74 20 62 75 66 66 65 72 20 69 73 20 6c 61 72 67  t buffer is larg
22d0: 65 20 65 6e 6f 75 67 68 20 66 6f 72 20 0a 20 20  e enough for .  
22e0: 2a 2a 20 70 56 66 73 2d 3e 6d 78 50 61 74 68 6e  ** pVfs->mxPathn
22f0: 61 6d 65 20 63 68 61 72 61 63 74 65 72 73 2e 0a  ame characters..
2300: 20 20 2a 2f 0a 20 20 69 66 28 20 70 4f 72 69 67    */.  if( pOrig
2310: 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 20  Vfs->mxPathname 
2320: 3c 3d 20 6e 42 75 66 20 29 7b 0a 20 20 20 20 63  <= nBuf ){.    c
2330: 68 61 72 20 2a 7a 54 6d 70 20 3d 20 73 71 6c 69  har *zTmp = sqli
2340: 74 65 33 5f 6d 61 6c 6c 6f 63 28 70 4f 72 69 67  te3_malloc(pOrig
2350: 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 29  Vfs->mxPathname)
2360: 3b 0a 20 20 20 20 69 66 28 20 7a 54 6d 70 3d 3d  ;.    if( zTmp==
2370: 30 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54  0 ) return SQLIT
2380: 45 5f 4e 4f 4d 45 4d 3b 0a 0a 20 20 20 20 2f 2a  E_NOMEM;..    /*
2390: 20 73 71 6c 69 74 65 33 5f 74 65 6d 70 5f 64 69   sqlite3_temp_di
23a0: 72 65 63 74 6f 72 79 20 73 68 6f 75 6c 64 20 61  rectory should a
23b0: 6c 77 61 79 73 20 62 65 20 6c 65 73 73 20 74 68  lways be less th
23c0: 61 6e 0a 20 20 20 20 2a 2a 20 70 56 66 73 2d 3e  an.    ** pVfs->
23d0: 6d 78 50 61 74 68 6e 61 6d 65 20 63 68 61 72 61  mxPathname chara
23e0: 63 74 65 72 73 2e 0a 20 20 20 20 2a 2f 0a 20 20  cters..    */.  
23f0: 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e    sqlite3_snprin
2400: 74 66 28 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  tf(pOrigVfs->mxP
2410: 61 74 68 6e 61 6d 65 2c 0a 20 20 20 20 20 20 20  athname,.       
2420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7a 54                zT
2430: 6d 70 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  mp,.            
2440: 20 20 20 20 20 20 20 20 20 22 25 73 2f 22 2c 0a           "%s/",.
2450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2460: 20 20 20 20 20 73 71 6c 69 74 65 33 5f 74 65 6d       sqlite3_tem
2470: 70 5f 64 69 72 65 63 74 6f 72 79 20 3f 20 73 71  p_directory ? sq
2480: 6c 69 74 65 33 5f 74 65 6d 70 5f 64 69 72 65 63  lite3_temp_direc
2490: 74 6f 72 79 20 3a 20 22 2e 22 29 3b 0a 20 20 20  tory : ".");.   
24a0: 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e   rc = pOrigVfs->
24b0: 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 70 4f  xFullPathname(pO
24c0: 72 69 67 56 66 73 2c 20 7a 54 6d 70 2c 20 6e 42  rigVfs, zTmp, nB
24d0: 75 66 2c 20 7a 42 75 66 29 3b 0a 20 20 20 20 73  uf, zBuf);.    s
24e0: 71 6c 69 74 65 33 5f 66 72 65 65 28 7a 54 6d 70  qlite3_free(zTmp
24f0: 29 3b 0a 20 20 20 20 69 66 28 20 72 63 20 29 20  );.    if( rc ) 
2500: 72 65 74 75 72 6e 20 72 63 3b 0a 0a 20 20 20 20  return rc;..    
2510: 2f 2a 20 43 68 65 63 6b 20 74 68 61 74 20 74 68  /* Check that th
2520: 65 20 6f 75 74 70 75 74 20 62 75 66 66 65 72 20  e output buffer 
2530: 69 73 20 6c 61 72 67 65 20 65 6e 6f 75 67 68 20  is large enough 
2540: 66 6f 72 20 74 68 65 20 74 65 6d 70 6f 72 61 72  for the temporar
2550: 79 20 66 69 6c 65 20 0a 20 20 20 20 2a 2a 20 6e  y file .    ** n
2560: 61 6d 65 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20  ame..    */.    
2570: 6a 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 74 72  j = multiplexStr
2580: 6c 65 6e 33 30 28 7a 42 75 66 29 3b 0a 20 20 20  len30(zBuf);.   
2590: 20 69 66 28 20 28 6a 20 2b 20 38 20 2b 20 31 20   if( (j + 8 + 1 
25a0: 2b 20 33 20 2b 20 31 29 20 3c 3d 20 6e 42 75 66  + 3 + 1) <= nBuf
25b0: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 4d 61 6b   ){.      /* Mak
25c0: 65 20 33 20 61 74 74 65 6d 70 74 73 20 74 6f 20  e 3 attempts to 
25d0: 67 65 6e 65 72 61 74 65 20 61 20 75 6e 69 71 75  generate a uniqu
25e0: 65 20 6e 61 6d 65 2e 20 2a 2f 0a 20 20 20 20 20  e name. */.     
25f0: 20 64 6f 20 7b 0a 20 20 20 20 20 20 20 20 61 74   do {.        at
2600: 74 65 6d 70 74 73 2b 2b 3b 0a 20 20 20 20 20 20  tempts++;.      
2610: 20 20 73 71 6c 69 74 65 33 5f 72 61 6e 64 6f 6d    sqlite3_random
2620: 6e 65 73 73 28 38 2c 20 26 7a 42 75 66 5b 6a 5d  ness(8, &zBuf[j]
2630: 29 3b 0a 20 20 20 20 20 20 20 20 66 6f 72 28 69  );.        for(i
2640: 3d 30 3b 20 69 3c 38 3b 20 69 2b 2b 29 7b 0a 20  =0; i<8; i++){. 
2650: 20 20 20 20 20 20 20 20 20 75 6e 73 69 67 6e 65           unsigne
2660: 64 20 63 68 61 72 20 75 63 20 3d 20 28 75 6e 73  d char uc = (uns
2670: 69 67 6e 65 64 20 63 68 61 72 29 7a 42 75 66 5b  igned char)zBuf[
2680: 6a 2b 69 5d 3b 0a 20 20 20 20 20 20 20 20 20 20  j+i];.          
2690: 7a 42 75 66 5b 6a 2b 69 5d 20 3d 20 28 63 68 61  zBuf[j+i] = (cha
26a0: 72 29 7a 43 68 61 72 73 5b 75 63 25 28 73 69 7a  r)zChars[uc%(siz
26b0: 65 6f 66 28 7a 43 68 61 72 73 29 2d 31 29 5d 3b  eof(zChars)-1)];
26c0: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
26d0: 20 20 20 6d 65 6d 63 70 79 28 26 7a 42 75 66 5b     memcpy(&zBuf[
26e0: 6a 2b 69 5d 2c 20 22 2e 74 6d 70 22 2c 20 35 29  j+i], ".tmp", 5)
26f0: 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70  ;.        rc = p
2700: 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73  OrigVfs->xAccess
2710: 28 70 4f 72 69 67 56 66 73 2c 20 7a 42 75 66 2c  (pOrigVfs, zBuf,
2720: 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45   SQLITE_ACCESS_E
2730: 58 49 53 54 53 2c 20 26 65 78 69 73 74 73 29 3b  XISTS, &exists);
2740: 0a 20 20 20 20 20 20 7d 20 77 68 69 6c 65 20 28  .      } while (
2750: 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 29   (rc==SQLITE_OK)
2760: 20 26 26 20 65 78 69 73 74 73 20 26 26 20 28 61   && exists && (a
2770: 74 74 65 6d 70 74 73 3c 33 29 20 29 3b 0a 20 20  ttempts<3) );.  
2780: 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49      if( rc==SQLI
2790: 54 45 5f 4f 4b 20 26 26 20 65 78 69 73 74 73 20  TE_OK && exists 
27a0: 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  ){.        rc = 
27b0: 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20  SQLITE_ERROR;.  
27c0: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
27d0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
27e0: 0a 2f 2a 20 43 6f 6d 70 75 74 65 20 74 68 65 20  ./* Compute the 
27f0: 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 74 68 65  filename for the
2800: 20 69 43 68 75 6e 6b 2d 74 68 20 63 68 75 6e 6b   iChunk-th chunk
2810: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
2820: 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e  ultiplexSubFilen
2830: 61 6d 65 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f  ame(multiplexGro
2840: 75 70 20 2a 70 47 72 6f 75 70 2c 20 69 6e 74 20  up *pGroup, int 
2850: 69 43 68 75 6e 6b 29 7b 0a 20 20 69 66 28 20 69  iChunk){.  if( i
2860: 43 68 75 6e 6b 3e 3d 70 47 72 6f 75 70 2d 3e 6e  Chunk>=pGroup->n
2870: 52 65 61 6c 20 29 7b 0a 20 20 20 20 73 74 72 75  Real ){.    stru
2880: 63 74 20 6d 75 6c 74 69 70 6c 65 78 52 65 61 6c  ct multiplexReal
2890: 20 2a 70 3b 0a 20 20 20 20 70 20 3d 20 73 71 6c   *p;.    p = sql
28a0: 69 74 65 33 5f 72 65 61 6c 6c 6f 63 28 70 47 72  ite3_realloc(pGr
28b0: 6f 75 70 2d 3e 61 52 65 61 6c 2c 20 28 69 43 68  oup->aReal, (iCh
28c0: 75 6e 6b 2b 31 29 2a 73 69 7a 65 6f 66 28 2a 70  unk+1)*sizeof(*p
28d0: 29 29 3b 0a 20 20 20 20 69 66 28 20 70 3d 3d 30  ));.    if( p==0
28e0: 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72 6e   ){.      return
28f0: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
2900: 20 20 20 7d 0a 20 20 20 20 6d 65 6d 73 65 74 28     }.    memset(
2910: 26 70 5b 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c  &p[pGroup->nReal
2920: 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 5b 30  ], 0, sizeof(p[0
2930: 5d 29 2a 28 69 43 68 75 6e 6b 2b 31 2d 70 47 72  ])*(iChunk+1-pGr
2940: 6f 75 70 2d 3e 6e 52 65 61 6c 29 29 3b 0a 20 20  oup->nReal));.  
2950: 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 20    pGroup->aReal 
2960: 3d 20 70 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  = p;.    pGroup-
2970: 3e 6e 52 65 61 6c 20 3d 20 69 43 68 75 6e 6b 2b  >nReal = iChunk+
2980: 31 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70 47 72  1;.  }.  if( pGr
2990: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
29a0: 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20 20 63  k].z==0 ){.    c
29b0: 68 61 72 20 2a 7a 3b 0a 20 20 20 20 69 6e 74 20  har *z;.    int 
29c0: 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  n = pGroup->nNam
29d0: 65 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 61  e;.    pGroup->a
29e0: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 20 3d  Real[iChunk].z =
29f0: 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c   z = sqlite3_mal
2a00: 6c 6f 63 28 20 6e 2b 33 20 29 3b 0a 20 20 20 20  loc( n+3 );.    
2a10: 69 66 28 20 7a 3d 3d 30 20 29 7b 0a 20 20 20 20  if( z==0 ){.    
2a20: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
2a30: 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20 20 20  NOMEM;.    }.   
2a40: 20 6d 65 6d 63 70 79 28 7a 2c 20 70 47 72 6f 75   memcpy(z, pGrou
2a50: 70 2d 3e 7a 4e 61 6d 65 2c 20 6e 2b 31 29 3b 0a  p->zName, n+1);.
2a60: 20 20 20 20 69 66 28 20 69 43 68 75 6e 6b 3e 30      if( iChunk>0
2a70: 20 29 7b 0a 23 69 66 64 65 66 20 53 51 4c 49 54   ){.#ifdef SQLIT
2a80: 45 5f 45 4e 41 42 4c 45 5f 38 5f 33 5f 4e 41 4d  E_ENABLE_8_3_NAM
2a90: 45 53 0a 20 20 20 20 20 20 69 66 28 20 6e 3e 33  ES.      if( n>3
2aa0: 20 26 26 20 7a 5b 6e 2d 33 5d 3d 3d 27 2e 27 20   && z[n-3]=='.' 
2ab0: 29 7b 0a 20 20 20 20 20 20 20 20 6e 2d 2d 3b 0a  ){.        n--;.
2ac0: 20 20 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20        }else if( 
2ad0: 6e 3e 34 20 26 26 20 7a 5b 6e 2d 34 5d 3d 3d 27  n>4 && z[n-4]=='
2ae0: 2e 27 20 29 7b 0a 20 20 20 20 20 20 20 20 6e 20  .' ){.        n 
2af0: 2d 3d 20 32 3b 0a 20 20 20 20 20 20 7d 0a 23 65  -= 2;.      }.#e
2b00: 6e 64 69 66 0a 20 20 20 20 20 20 73 71 6c 69 74  ndif.      sqlit
2b10: 65 33 5f 73 6e 70 72 69 6e 74 66 28 33 2c 26 7a  e3_snprintf(3,&z
2b20: 5b 6e 5d 2c 22 25 30 32 64 22 2c 69 43 68 75 6e  [n],"%02d",iChun
2b30: 6b 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  k);.    }.  }.  
2b40: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
2b50: 3b 0a 7d 0a 0a 2f 2a 20 54 72 61 6e 73 6c 61 74  ;.}../* Translat
2b60: 65 20 61 6e 20 73 71 6c 69 74 65 33 5f 66 69 6c  e an sqlite3_fil
2b70: 65 2a 20 74 68 61 74 20 69 73 20 72 65 61 6c 6c  e* that is reall
2b80: 79 20 61 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  y a multiplexGro
2b90: 75 70 2a 20 69 6e 74 6f 0a 2a 2a 20 74 68 65 20  up* into.** the 
2ba0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 2a 20 66 6f  sqlite3_file* fo
2bb0: 72 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67  r the underlying
2bc0: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a   original VFS..*
2bd0: 2f 0a 73 74 61 74 69 63 20 73 71 6c 69 74 65 33  /.static sqlite3
2be0: 5f 66 69 6c 65 20 2a 6d 75 6c 74 69 70 6c 65 78  _file *multiplex
2bf0: 53 75 62 4f 70 65 6e 28 0a 20 20 6d 75 6c 74 69  SubOpen(.  multi
2c00: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
2c10: 70 2c 0a 20 20 69 6e 74 20 69 43 68 75 6e 6b 2c  p,.  int iChunk,
2c20: 0a 20 20 69 6e 74 20 2a 72 63 2c 0a 20 20 69 6e  .  int *rc,.  in
2c30: 74 20 2a 70 4f 75 74 46 6c 61 67 73 0a 29 7b 0a  t *pOutFlags.){.
2c40: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
2c50: 70 53 75 62 4f 70 65 6e 20 3d 20 30 3b 0a 20 20  pSubOpen = 0;.  
2c60: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72  sqlite3_vfs *pOr
2c70: 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c  igVfs = gMultipl
2c80: 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 20  ex.pOrigVfs;    
2c90: 20 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20      /* Real VFS 
2ca0: 2a 2f 0a 20 20 2a 72 63 20 3d 20 6d 75 6c 74 69  */.  *rc = multi
2cb0: 70 6c 65 78 53 75 62 46 69 6c 65 6e 61 6d 65 28  plexSubFilename(
2cc0: 70 47 72 6f 75 70 2c 20 69 43 68 75 6e 6b 29 3b  pGroup, iChunk);
2cd0: 0a 20 20 69 66 28 20 28 2a 72 63 29 3d 3d 53 51  .  if( (*rc)==SQ
2ce0: 4c 49 54 45 5f 4f 4b 20 26 26 20 28 70 53 75 62  LITE_OK && (pSub
2cf0: 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61  Open = pGroup->a
2d00: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 29 3d  Real[iChunk].p)=
2d10: 3d 30 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70  =0 ){.    pSubOp
2d20: 65 6e 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c  en = sqlite3_mal
2d30: 6c 6f 63 28 20 70 4f 72 69 67 56 66 73 2d 3e 73  loc( pOrigVfs->s
2d40: 7a 4f 73 46 69 6c 65 20 29 3b 0a 20 20 20 20 69  zOsFile );.    i
2d50: 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29  f( pSubOpen==0 )
2d60: 7b 0a 20 20 20 20 20 20 2a 72 63 20 3d 20 53 51  {.      *rc = SQ
2d70: 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20  LITE_NOMEM;.    
2d80: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20    return 0;.    
2d90: 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52  }.    pGroup->aR
2da0: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d 20  eal[iChunk].p = 
2db0: 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 2a 72  pSubOpen;.    *r
2dc0: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 4f  c = pOrigVfs->xO
2dd0: 70 65 6e 28 70 4f 72 69 67 56 66 73 2c 20 70 47  pen(pOrigVfs, pG
2de0: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
2df0: 6e 6b 5d 2e 7a 2c 20 70 53 75 62 4f 70 65 6e 2c  nk].z, pSubOpen,
2e00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2e10: 20 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75             pGrou
2e20: 70 2d 3e 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c  p->flags, pOutFl
2e30: 61 67 73 29 3b 0a 20 20 20 20 69 66 28 20 2a 72  ags);.    if( *r
2e40: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c!=SQLITE_OK ){.
2e50: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72        sqlite3_fr
2e60: 65 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  ee(pSubOpen);.  
2e70: 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61      pGroup->aRea
2e80: 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d 20 30 3b  l[iChunk].p = 0;
2e90: 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20 30 3b  .      return 0;
2ea0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 72 65 74  .    }.  }.  ret
2eb0: 75 72 6e 20 70 53 75 62 4f 70 65 6e 3b 0a 7d 0a  urn pSubOpen;.}.
2ec0: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74  ./*.** This is t
2ed0: 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f  he implementatio
2ee0: 6e 20 6f 66 20 74 68 65 20 6d 75 6c 74 69 70 6c  n of the multipl
2ef0: 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 53 51 4c  ex_control() SQL
2f00: 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74   function..*/.st
2f10: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
2f20: 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e 63 28 0a  lexControlFunc(.
2f30: 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78    sqlite3_contex
2f40: 74 20 2a 63 6f 6e 74 65 78 74 2c 0a 20 20 69 6e  t *context,.  in
2f50: 74 20 61 72 67 63 2c 0a 20 20 73 71 6c 69 74 65  t argc,.  sqlite
2f60: 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67 76 0a 29  3_value **argv.)
2f70: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
2f80: 49 54 45 5f 4f 4b 3b 0a 20 20 73 71 6c 69 74 65  ITE_OK;.  sqlite
2f90: 33 20 2a 64 62 20 3d 20 73 71 6c 69 74 65 33 5f  3 *db = sqlite3_
2fa0: 63 6f 6e 74 65 78 74 5f 64 62 5f 68 61 6e 64 6c  context_db_handl
2fb0: 65 28 63 6f 6e 74 65 78 74 29 3b 0a 20 20 69 6e  e(context);.  in
2fc0: 74 20 6f 70 3b 0a 20 20 69 6e 74 20 69 56 61 6c  t op;.  int iVal
2fd0: 3b 0a 0a 20 20 69 66 28 20 21 64 62 20 7c 7c 20  ;..  if( !db || 
2fe0: 61 72 67 63 21 3d 32 20 29 7b 20 0a 20 20 20 20  argc!=2 ){ .    
2ff0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f  rc = SQLITE_ERRO
3000: 52 3b 20 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  R; .  }else{.   
3010: 20 2f 2a 20 65 78 74 72 61 63 74 20 70 61 72 61   /* extract para
3020: 6d 73 20 2a 2f 0a 20 20 20 20 6f 70 20 3d 20 73  ms */.    op = s
3030: 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74  qlite3_value_int
3040: 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20 20 69  (argv[0]);.    i
3050: 56 61 6c 20 3d 20 73 71 6c 69 74 65 33 5f 76 61  Val = sqlite3_va
3060: 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 31 5d 29  lue_int(argv[1])
3070: 3b 0a 20 20 20 20 2f 2a 20 6d 61 70 20 66 75 6e  ;.    /* map fun
3080: 63 74 69 6f 6e 20 6f 70 20 74 6f 20 66 69 6c 65  ction op to file
3090: 5f 63 6f 6e 74 72 6f 6c 20 6f 70 20 2a 2f 0a 20  _control op */. 
30a0: 20 20 20 73 77 69 74 63 68 28 20 6f 70 20 29 7b     switch( op ){
30b0: 0a 20 20 20 20 20 20 63 61 73 65 20 31 3a 20 0a  .      case 1: .
30c0: 20 20 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c          op = MUL
30d0: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
30e0: 4c 45 3b 20 0a 20 20 20 20 20 20 20 20 62 72 65  LE; .        bre
30f0: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 32  ak;.      case 2
3100: 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20 3d 20  : .        op = 
3110: 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53  MULTIPLEX_CTRL_S
3120: 45 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b 20 0a  ET_CHUNK_SIZE; .
3130: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
3140: 20 20 20 20 20 63 61 73 65 20 33 3a 20 0a 20 20       case 3: .  
3150: 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c 54 49        op = MULTI
3160: 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41  PLEX_CTRL_SET_MA
3170: 58 5f 43 48 55 4e 4b 53 3b 20 0a 20 20 20 20 20  X_CHUNKS; .     
3180: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
3190: 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  default:.       
31a0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 54   rc = SQLITE_NOT
31b0: 46 4f 55 4e 44 3b 0a 20 20 20 20 20 20 20 20 62  FOUND;.        b
31c0: 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  reak;.    }.  }.
31d0: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
31e0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  _OK ){.    rc = 
31f0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e  sqlite3_file_con
3200: 74 72 6f 6c 28 64 62 2c 20 30 2c 20 6f 70 2c 20  trol(db, 0, op, 
3210: 26 69 56 61 6c 29 3b 0a 20 20 7d 0a 20 20 73 71  &iVal);.  }.  sq
3220: 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72  lite3_result_err
3230: 6f 72 5f 63 6f 64 65 28 63 6f 6e 74 65 78 74 2c  or_code(context,
3240: 20 72 63 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54   rc);.}../*.** T
3250: 68 69 73 20 69 73 20 74 68 65 20 65 6e 74 72 79  his is the entry
3260: 20 70 6f 69 6e 74 20 74 6f 20 72 65 67 69 73 74   point to regist
3270: 65 72 20 74 68 65 20 61 75 74 6f 2d 65 78 74 65  er the auto-exte
3280: 6e 73 69 6f 6e 20 66 6f 72 20 74 68 65 20 0a 2a  nsion for the .*
3290: 2a 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74  * multiplex_cont
32a0: 72 6f 6c 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a  rol() function..
32b0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
32c0: 6c 74 69 70 6c 65 78 46 75 6e 63 49 6e 69 74 28  ltiplexFuncInit(
32d0: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 2c 20  .  sqlite3 *db, 
32e0: 0a 20 20 63 68 61 72 20 2a 2a 70 7a 45 72 72 4d  .  char **pzErrM
32f0: 73 67 2c 20 0a 20 20 63 6f 6e 73 74 20 73 71 6c  sg, .  const sql
3300: 69 74 65 33 5f 61 70 69 5f 72 6f 75 74 69 6e 65  ite3_api_routine
3310: 73 20 2a 70 41 70 69 0a 29 7b 0a 20 20 69 6e 74  s *pApi.){.  int
3320: 20 72 63 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69   rc;.  rc = sqli
3330: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
3340: 69 6f 6e 28 64 62 2c 20 22 6d 75 6c 74 69 70 6c  ion(db, "multipl
3350: 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 32 2c 20  ex_control", 2, 
3360: 53 51 4c 49 54 45 5f 41 4e 59 2c 20 0a 20 20 20  SQLITE_ANY, .   
3370: 20 20 20 30 2c 20 6d 75 6c 74 69 70 6c 65 78 43     0, multiplexC
3380: 6f 6e 74 72 6f 6c 46 75 6e 63 2c 20 30 2c 20 30  ontrolFunc, 0, 0
3390: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
33a0: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20 61  }../*.** Close a
33b0: 20 73 69 6e 67 6c 65 20 73 75 62 2d 66 69 6c 65   single sub-file
33c0: 20 69 6e 20 74 68 65 20 63 6f 6e 6e 65 63 74 69   in the connecti
33d0: 6f 6e 20 67 72 6f 75 70 2e 0a 2a 2f 0a 73 74 61  on group..*/.sta
33e0: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
33f0: 65 78 53 75 62 43 6c 6f 73 65 28 0a 20 20 6d 75  exSubClose(.  mu
3400: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
3410: 72 6f 75 70 2c 0a 20 20 69 6e 74 20 69 43 68 75  roup,.  int iChu
3420: 6e 6b 2c 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  nk,.  sqlite3_vf
3430: 73 20 2a 70 4f 72 69 67 56 66 73 0a 29 7b 0a 20  s *pOrigVfs.){. 
3440: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
3450: 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70  SubOpen = pGroup
3460: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
3470: 70 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  p;.  if( pSubOpe
3480: 6e 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70 65  n ){.    pSubOpe
3490: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 43 6c  n->pMethods->xCl
34a0: 6f 73 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20  ose(pSubOpen);. 
34b0: 20 20 20 69 66 28 20 70 4f 72 69 67 56 66 73 20     if( pOrigVfs 
34c0: 29 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c  ) pOrigVfs->xDel
34d0: 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 70 47  ete(pOrigVfs, pG
34e0: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
34f0: 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20 20 73  nk].z, 0);.    s
3500: 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72 6f  qlite3_free(pGro
3510: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
3520: 5d 2e 70 29 3b 0a 20 20 7d 0a 20 20 73 71 6c 69  ].p);.  }.  sqli
3530: 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d  te3_free(pGroup-
3540: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
3550: 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70 47 72  );.  memset(&pGr
3560: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
3570: 6b 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 47  k], 0, sizeof(pG
3580: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3590: 6e 6b 5d 29 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  nk]));.}../*.** 
35a0: 44 65 61 6c 6c 6f 63 61 74 65 20 6d 65 6d 6f 72  Deallocate memor
35b0: 79 20 68 65 6c 64 20 62 79 20 61 20 6d 75 6c 74  y held by a mult
35c0: 69 70 6c 65 78 47 72 6f 75 70 0a 2a 2f 0a 73 74  iplexGroup.*/.st
35d0: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
35e0: 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74  lexFreeComponent
35f0: 73 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  s(multiplexGroup
3600: 20 2a 70 47 72 6f 75 70 29 7b 0a 20 20 69 6e 74   *pGroup){.  int
3610: 20 69 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69   i;.  for(i=0; i
3620: 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b 20  <pGroup->nReal; 
3630: 69 2b 2b 29 7b 20 6d 75 6c 74 69 70 6c 65 78 53  i++){ multiplexS
3640: 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c 20  ubClose(pGroup, 
3650: 69 2c 20 30 29 3b 20 7d 0a 20 20 73 71 6c 69 74  i, 0); }.  sqlit
3660: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d 3e  e3_free(pGroup->
3670: 61 52 65 61 6c 29 3b 0a 20 20 70 47 72 6f 75 70  aReal);.  pGroup
3680: 2d 3e 61 52 65 61 6c 20 3d 20 30 3b 0a 20 20 70  ->aReal = 0;.  p
3690: 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20 30  Group->nReal = 0
36a0: 3b 0a 7d 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;.}.../*********
36b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
36c0: 20 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61 70   VFS Method Wrap
36d0: 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  pers ***********
36e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
36f0: 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  **/../*.** This 
3700: 69 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65 74  is the xOpen met
3710: 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68 65  hod used for the
3720: 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46 53   "multiplex" VFS
3730: 2e 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66 20  ..**.** Most of 
3740: 74 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e 65  the work is done
3750: 20 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79 69   by the underlyi
3760: 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e  ng original VFS.
3770: 20 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a 2a    This method.**
3780: 20 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74 68   simply links th
3790: 65 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f 20  e new file into 
37a0: 74 68 65 20 61 70 70 72 6f 70 72 69 61 74 65 20  the appropriate 
37b0: 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 20  multiplex group 
37c0: 69 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66 69  if it is a.** fi
37d0: 6c 65 20 74 68 61 74 20 6e 65 65 64 73 20 74 6f  le that needs to
37e0: 20 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f 0a   be tracked..*/.
37f0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
3800: 70 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c 69  plexOpen(.  sqli
3810: 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20 20  te3_vfs *pVfs,  
3820: 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d 75         /* The mu
3830: 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20  ltiplex VFS */. 
3840: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61   const char *zNa
3850: 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 4e  me,         /* N
3860: 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20 62  ame of file to b
3870: 65 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73 71  e opened */.  sq
3880: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
3890: 6e 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c 6c  n,       /* Fill
38a0: 20 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64 65   in this file de
38b0: 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69 6e  scriptor */.  in
38c0: 74 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20 20  t flags,        
38d0: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67           /* Flag
38e0: 73 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68 65  s to control the
38f0: 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e   opening */.  in
3900: 74 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20 20  t *pOutFlags    
3910: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67           /* Flag
3920: 73 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c 74  s showing result
3930: 73 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a  s of opening */.
3940: 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  ){.  int rc = SQ
3950: 4c 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20 20  LITE_OK;        
3960: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73            /* Res
3970: 75 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d 75  ult code */.  mu
3980: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d 75  ltiplexConn *pMu
3990: 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20 20  ltiplexOpen;    
39a0: 20 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d 75     /* The new mu
39b0: 6c 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65 73  ltiplex file des
39c0: 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75 6c  criptor */.  mul
39d0: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
39e0: 6f 75 70 3b 20 20 20 20 20 20 20 20 20 20 20 20  oup;            
39f0: 20 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64 69    /* Correspondi
3a00: 6e 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  ng multiplexGrou
3a10: 70 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73 71  p object */.  sq
3a20: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
3a30: 4f 70 65 6e 20 3d 20 30 3b 20 20 20 20 20 20 20  Open = 0;       
3a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
3a50: 52 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72 69  Real file descri
3a60: 70 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74 65  ptor */.  sqlite
3a70: 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20  3_vfs *pOrigVfs 
3a80: 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  = gMultiplex.pOr
3a90: 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c  igVfs;   /* Real
3aa0: 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e   VFS */.  int nN
3ab0: 61 6d 65 3b 0a 20 20 69 6e 74 20 73 7a 3b 0a 20  ame;.  int sz;. 
3ac0: 20 63 68 61 72 20 2a 7a 54 6f 46 72 65 65 20 3d   char *zToFree =
3ad0: 20 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41   0;..  UNUSED_PA
3ae0: 52 41 4d 45 54 45 52 28 70 56 66 73 29 3b 0a 20  RAMETER(pVfs);. 
3af0: 20 6d 65 6d 73 65 74 28 70 43 6f 6e 6e 2c 20 30   memset(pConn, 0
3b00: 2c 20 70 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65  , pVfs->szOsFile
3b10: 29 3b 0a 0a 20 20 2f 2a 20 57 65 20 6e 65 65 64  );..  /* We need
3b20: 20 74 6f 20 63 72 65 61 74 65 20 61 20 67 72 6f   to create a gro
3b30: 75 70 20 73 74 72 75 63 74 75 72 65 20 61 6e 64  up structure and
3b40: 20 6d 61 6e 61 67 65 0a 20 20 2a 2a 20 61 63 63   manage.  ** acc
3b50: 65 73 73 20 74 6f 20 74 68 69 73 20 67 72 6f 75  ess to this grou
3b60: 70 20 6f 66 20 66 69 6c 65 73 2e 0a 20 20 2a 2f  p of files..  */
3b70: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
3b80: 72 28 29 3b 0a 20 20 70 4d 75 6c 74 69 70 6c 65  r();.  pMultiple
3b90: 78 4f 70 65 6e 20 3d 20 28 6d 75 6c 74 69 70 6c  xOpen = (multipl
3ba0: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 0a  exConn*)pConn;..
3bb0: 20 20 2f 2a 20 49 66 20 74 68 65 20 73 65 63 6f    /* If the seco
3bc0: 6e 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 74  nd argument to t
3bd0: 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20  his function is 
3be0: 4e 55 4c 4c 2c 20 67 65 6e 65 72 61 74 65 20 61  NULL, generate a
3bf0: 20 0a 20 20 2a 2a 20 74 65 6d 70 6f 72 61 72 79   .  ** temporary
3c00: 20 66 69 6c 65 20 6e 61 6d 65 20 74 6f 20 75 73   file name to us
3c10: 65 2e 20 20 54 68 69 73 20 77 69 6c 6c 20 62 65  e.  This will be
3c20: 20 68 61 6e 64 6c 65 64 20 62 79 20 74 68 65 0a   handled by the.
3c30: 20 20 2a 2a 20 6f 72 69 67 69 6e 61 6c 20 78 4f    ** original xO
3c40: 70 65 6e 20 6d 65 74 68 6f 64 2e 20 20 57 65 20  pen method.  We 
3c50: 6a 75 73 74 20 6e 65 65 64 20 74 6f 20 61 6c 6c  just need to all
3c60: 6f 63 61 74 65 20 73 70 61 63 65 20 66 6f 72 0a  ocate space for.
3c70: 20 20 2a 2a 20 69 74 2e 0a 20 20 2a 2f 0a 20 20    ** it..  */.  
3c80: 69 66 28 20 21 7a 4e 61 6d 65 20 29 7b 0a 20 20  if( !zName ){.  
3c90: 20 20 7a 4e 61 6d 65 20 3d 20 7a 54 6f 46 72 65    zName = zToFre
3ca0: 65 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  e = sqlite3_mall
3cb0: 6f 63 28 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78  oc( pOrigVfs->mx
3cc0: 50 61 74 68 6e 61 6d 65 20 2b 20 31 30 20 29 3b  Pathname + 10 );
3cd0: 0a 20 20 20 20 69 66 28 20 7a 4e 61 6d 65 3d 3d  .    if( zName==
3ce0: 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  0 ){.      rc = 
3cf0: 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20  SQLITE_NOMEM;.  
3d00: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72    }else{.      r
3d10: 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 47 65 74  c = multiplexGet
3d20: 54 65 6d 70 6e 61 6d 65 28 70 4f 72 69 67 56 66  Tempname(pOrigVf
3d30: 73 2c 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  s, pOrigVfs->mxP
3d40: 61 74 68 6e 61 6d 65 2c 20 7a 54 6f 46 72 65 65  athname, zToFree
3d50: 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20  );.    }.  }..  
3d60: 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  if( rc==SQLITE_O
3d70: 4b 20 29 7b 0a 20 20 20 20 2f 2a 20 61 6c 6c 6f  K ){.    /* allo
3d80: 63 61 74 65 20 73 70 61 63 65 20 66 6f 72 20 67  cate space for g
3d90: 72 6f 75 70 20 2a 2f 0a 20 20 20 20 6e 4e 61 6d  roup */.    nNam
3da0: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 74 72  e = multiplexStr
3db0: 6c 65 6e 33 30 28 7a 4e 61 6d 65 29 3b 0a 20 20  len30(zName);.  
3dc0: 20 20 73 7a 20 3d 20 73 69 7a 65 6f 66 28 6d 75    sz = sizeof(mu
3dd0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 29 20 20 20  ltiplexGroup)   
3de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3df0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6d 75 6c            /* mul
3e00: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 2f 0a 20  tiplexGroup */. 
3e10: 20 20 20 20 20 20 2b 20 6e 4e 61 6d 65 20 2b 20        + nName + 
3e20: 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1;              
3e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e40: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 7a 4e             /* zN
3e50: 61 6d 65 20 2a 2f 0a 20 20 20 20 70 47 72 6f 75  ame */.    pGrou
3e60: 70 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  p = sqlite3_mall
3e70: 6f 63 28 20 73 7a 20 29 3b 0a 20 20 20 20 69 66  oc( sz );.    if
3e80: 28 20 70 47 72 6f 75 70 3d 3d 30 20 29 7b 0a 20  ( pGroup==0 ){. 
3e90: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
3ea0: 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20 20  _NOMEM;.    }.  
3eb0: 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  }..  if( rc==SQL
3ec0: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a  ITE_OK ){.    /*
3ed0: 20 61 73 73 69 67 6e 20 70 6f 69 6e 74 65 72 73   assign pointers
3ee0: 20 74 6f 20 65 78 74 72 61 20 73 70 61 63 65 20   to extra space 
3ef0: 61 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 20  allocated */.   
3f00: 20 63 68 61 72 20 2a 70 20 3d 20 28 63 68 61 72   char *p = (char
3f10: 20 2a 29 26 70 47 72 6f 75 70 5b 31 5d 3b 0a 20   *)&pGroup[1];. 
3f20: 20 20 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65     pMultiplexOpe
3f30: 6e 2d 3e 70 47 72 6f 75 70 20 3d 20 70 47 72 6f  n->pGroup = pGro
3f40: 75 70 3b 0a 20 20 20 20 6d 65 6d 73 65 74 28 70  up;.    memset(p
3f50: 47 72 6f 75 70 2c 20 30 2c 20 73 7a 29 3b 0a 20  Group, 0, sz);. 
3f60: 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62     pGroup->bEnab
3f70: 6c 65 64 20 3d 20 2d 31 3b 0a 20 20 20 20 70 47  led = -1;.    pG
3f80: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 3d 20  roup->szChunk = 
3f90: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
3fa0: 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b 0a 20 20 20  _CHUNK_SIZE;.   
3fb0: 20 69 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c   if( flags & SQL
3fc0: 49 54 45 5f 4f 50 45 4e 5f 55 52 49 20 29 7b 0a  ITE_OPEN_URI ){.
3fd0: 20 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72        const char
3fe0: 20 2a 7a 43 68 75 6e 6b 53 69 7a 65 3b 0a 20 20   *zChunkSize;.  
3ff0: 20 20 20 20 7a 43 68 75 6e 6b 53 69 7a 65 20 3d      zChunkSize =
4000: 20 73 71 6c 69 74 65 33 5f 75 72 69 5f 70 61 72   sqlite3_uri_par
4010: 61 6d 65 74 65 72 28 7a 4e 61 6d 65 2c 20 22 63  ameter(zName, "c
4020: 68 75 6e 6b 73 69 7a 65 22 29 3b 0a 20 20 20 20  hunksize");.    
4030: 20 20 69 66 28 20 7a 43 68 75 6e 6b 53 69 7a 65    if( zChunkSize
4040: 20 29 7b 0a 20 20 20 20 20 20 20 20 75 6e 73 69   ){.        unsi
4050: 67 6e 65 64 20 69 6e 74 20 6e 20 3d 20 30 3b 0a  gned int n = 0;.
4060: 20 20 20 20 20 20 20 20 69 6e 74 20 69 3b 0a 20          int i;. 
4070: 20 20 20 20 20 20 20 66 6f 72 28 69 3d 30 3b 20         for(i=0; 
4080: 7a 43 68 75 6e 6b 53 69 7a 65 5b 69 5d 3e 3d 27  zChunkSize[i]>='
4090: 30 27 20 26 26 20 7a 43 68 75 6e 6b 53 69 7a 65  0' && zChunkSize
40a0: 5b 69 5d 3c 3d 27 39 27 3b 20 69 2b 2b 29 7b 0a  [i]<='9'; i++){.
40b0: 20 20 20 20 20 20 20 20 20 20 6e 20 3d 20 6e 2a            n = n*
40c0: 31 30 20 2b 20 7a 43 68 75 6e 6b 53 69 7a 65 5b  10 + zChunkSize[
40d0: 69 5d 20 2d 20 27 30 27 3b 0a 20 20 20 20 20 20  i] - '0';.      
40e0: 20 20 7d 0a 20 20 20 20 20 20 20 20 69 66 28 20    }.        if( 
40f0: 6e 3e 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20  n>0 ){.         
4100: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
4110: 20 3d 20 28 6e 2b 30 78 66 66 66 66 29 26 7e 30   = (n+0xffff)&~0
4120: 78 66 66 66 66 3b 0a 20 20 20 20 20 20 20 20 7d  xffff;.        }
4130: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20  else{.          
4140: 2f 2a 20 41 20 7a 65 72 6f 20 6f 72 20 6e 65 67  /* A zero or neg
4150: 61 74 69 76 65 20 63 68 75 6e 6b 73 69 7a 65 20  ative chunksize 
4160: 64 69 73 61 62 6c 65 64 20 74 68 65 20 6d 75 6c  disabled the mul
4170: 74 69 70 6c 65 78 6f 72 20 2a 2f 0a 20 20 20 20  tiplexor */.    
4180: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45        pGroup->bE
4190: 6e 61 62 6c 65 64 20 3d 20 30 3b 0a 20 20 20 20  nabled = 0;.    
41a0: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20      }.      }.  
41b0: 20 20 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e    }.    pGroup->
41c0: 7a 4e 61 6d 65 20 3d 20 70 3b 0a 20 20 20 20 2f  zName = p;.    /
41d0: 2a 20 73 61 76 65 20 6f 66 66 20 62 61 73 65 20  * save off base 
41e0: 66 69 6c 65 6e 61 6d 65 2c 20 6e 61 6d 65 20 6c  filename, name l
41f0: 65 6e 67 74 68 2c 20 61 6e 64 20 6f 72 69 67 69  ength, and origi
4200: 6e 61 6c 20 6f 70 65 6e 20 66 6c 61 67 73 20 20  nal open flags  
4210: 2a 2f 0a 20 20 20 20 6d 65 6d 63 70 79 28 70 47  */.    memcpy(pG
4220: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 7a 4e 61  roup->zName, zNa
4230: 6d 65 2c 20 6e 4e 61 6d 65 2b 31 29 3b 0a 20 20  me, nName+1);.  
4240: 20 20 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 20    pGroup->nName 
4250: 3d 20 6e 4e 61 6d 65 3b 0a 20 20 20 20 70 47 72  = nName;.    pGr
4260: 6f 75 70 2d 3e 66 6c 61 67 73 20 3d 20 66 6c 61  oup->flags = fla
4270: 67 73 3b 0a 20 20 20 20 72 63 20 3d 20 6d 75 6c  gs;.    rc = mul
4280: 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e 61 6d  tiplexSubFilenam
4290: 65 28 70 47 72 6f 75 70 2c 20 31 29 3b 0a 20 20  e(pGroup, 1);.  
42a0: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
42b0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70 53 75  _OK ){.      pSu
42c0: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
42d0: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
42e0: 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46 6c 61   0, &rc, pOutFla
42f0: 67 73 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69  gs);.    }.    i
4300: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
4310: 20 20 20 20 20 69 6e 74 20 65 78 69 73 74 73 2c       int exists,
4320: 20 72 63 32 2c 20 72 63 33 3b 0a 20 20 20 20 20   rc2, rc3;.     
4330: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 73   sqlite3_int64 s
4340: 7a 3b 0a 0a 20 20 20 20 20 20 72 63 32 20 3d 20  z;..      rc2 = 
4350: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
4360: 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70 53  ds->xFileSize(pS
4370: 75 62 4f 70 65 6e 2c 20 26 73 7a 29 3b 0a 20 20  ubOpen, &sz);.  
4380: 20 20 20 20 69 66 28 20 72 63 32 3d 3d 53 51 4c      if( rc2==SQL
4390: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
43a0: 20 20 2f 2a 20 49 66 20 74 68 65 20 66 69 72 73    /* If the firs
43b0: 74 20 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20  t overflow file 
43c0: 65 78 69 73 74 73 20 61 6e 64 20 69 66 20 74 68  exists and if th
43d0: 65 20 73 69 7a 65 20 6f 66 20 74 68 65 20 6d 61  e size of the ma
43e0: 69 6e 20 66 69 6c 65 0a 20 20 20 20 20 20 20 20  in file.        
43f0: 2a 2a 20 69 73 20 64 69 66 66 65 72 65 6e 74 20  ** is different 
4400: 66 72 6f 6d 20 74 68 65 20 63 68 75 6e 6b 20 73  from the chunk s
4410: 69 7a 65 2c 20 74 68 61 74 20 6d 65 61 6e 73 20  ize, that means 
4420: 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 20 69  the chunk size i
4430: 73 20 73 65 74 0a 20 20 20 20 20 20 20 20 2a 2a  s set.        **
4440: 20 73 65 74 20 69 6e 63 6f 72 72 65 63 74 6c 79   set incorrectly
4450: 2e 20 20 53 6f 20 66 69 78 20 69 74 2e 0a 20 20  .  So fix it..  
4460: 20 20 20 20 20 20 2a 2a 0a 20 20 20 20 20 20 20        **.       
4470: 20 2a 2a 20 4f 72 2c 20 69 66 20 74 68 65 20 66   ** Or, if the f
4480: 69 72 73 74 20 6f 76 65 72 66 6c 6f 77 20 66 69  irst overflow fi
4490: 6c 65 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73  le does not exis
44a0: 74 20 61 6e 64 20 74 68 65 20 6d 61 69 6e 20 66  t and the main f
44b0: 69 6c 65 20 69 73 0a 20 20 20 20 20 20 20 20 2a  ile is.        *
44c0: 2a 20 6c 61 72 67 65 72 20 74 68 61 6e 20 74 68  * larger than th
44d0: 65 20 63 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68  e chunk size, th
44e0: 61 74 20 6d 65 61 6e 73 20 74 68 65 20 63 68 75  at means the chu
44f0: 6e 6b 20 73 69 7a 65 20 69 73 20 74 6f 6f 20 73  nk size is too s
4500: 6d 61 6c 6c 2e 0a 20 20 20 20 20 20 20 20 2a 2a  mall..        **
4510: 20 42 75 74 20 77 65 20 68 61 76 65 20 6e 6f 20   But we have no 
4520: 77 61 79 20 6f 66 20 64 65 74 65 72 6d 69 6e 69  way of determini
4530: 6e 67 20 74 68 65 20 69 6e 74 65 6e 64 65 64 20  ng the intended 
4540: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 73 6f 20 0a  chunk size, so .
4550: 20 20 20 20 20 20 20 20 2a 2a 20 6a 75 73 74 20          ** just 
4560: 64 69 73 61 62 6c 65 20 74 68 65 20 6d 75 6c 74  disable the mult
4570: 69 70 6c 65 78 6f 72 20 61 6c 6c 20 74 6f 67 65  iplexor all toge
4580: 74 68 72 65 2e 0a 20 20 20 20 20 20 20 20 2a 2f  thre..        */
4590: 0a 20 20 20 20 20 20 20 20 72 63 33 20 3d 20 70  .        rc3 = p
45a0: 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73  OrigVfs->xAccess
45b0: 28 70 4f 72 69 67 56 66 73 2c 20 70 47 72 6f 75  (pOrigVfs, pGrou
45c0: 70 2d 3e 61 52 65 61 6c 5b 31 5d 2e 7a 2c 0a 20  p->aReal[1].z,. 
45d0: 20 20 20 20 20 20 20 20 20 20 20 53 51 4c 49 54             SQLIT
45e0: 45 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c  E_ACCESS_EXISTS,
45f0: 20 26 65 78 69 73 74 73 29 3b 0a 20 20 20 20 20   &exists);.     
4600: 20 20 20 69 66 28 20 72 63 33 3d 3d 53 51 4c 49     if( rc3==SQLI
4610: 54 45 5f 4f 4b 20 26 26 20 65 78 69 73 74 73 20  TE_OK && exists 
4620: 26 26 20 73 7a 3d 3d 28 73 7a 26 30 78 66 66 66  && sz==(sz&0xfff
4630: 66 30 30 30 30 29 20 26 26 20 73 7a 3e 30 0a 20  f0000) && sz>0. 
4640: 20 20 20 20 20 20 20 20 20 20 20 26 26 20 73 7a             && sz
4650: 21 3d 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  !=pGroup->szChun
4660: 6b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70  k ){.          p
4670: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 3d  Group->szChunk =
4680: 20 73 7a 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c   sz;.        }el
4690: 73 65 20 69 66 28 20 72 63 33 3d 3d 53 51 4c 49  se if( rc3==SQLI
46a0: 54 45 5f 4f 4b 20 26 26 20 21 65 78 69 73 74 73  TE_OK && !exists
46b0: 20 26 26 20 73 7a 3e 70 47 72 6f 75 70 2d 3e 73   && sz>pGroup->s
46c0: 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20 20  zChunk ){.      
46d0: 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61      pGroup->bEna
46e0: 62 6c 65 64 20 3d 20 30 3b 0a 20 20 20 20 20 20  bled = 0;.      
46f0: 20 20 7d 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20    }.      }..   
4700: 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 2d     if( pSubOpen-
4710: 3e 70 4d 65 74 68 6f 64 73 2d 3e 69 56 65 72 73  >pMethods->iVers
4720: 69 6f 6e 3d 3d 31 20 29 7b 0a 20 20 20 20 20 20  ion==1 ){.      
4730: 20 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e    pMultiplexOpen
4740: 2d 3e 62 61 73 65 2e 70 4d 65 74 68 6f 64 73 20  ->base.pMethods 
4750: 3d 20 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  = &gMultiplex.sI
4760: 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 20 20  oMethodsV1;.    
4770: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
4780: 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 2d   pMultiplexOpen-
4790: 3e 62 61 73 65 2e 70 4d 65 74 68 6f 64 73 20 3d  >base.pMethods =
47a0: 20 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f   &gMultiplex.sIo
47b0: 4d 65 74 68 6f 64 73 56 32 3b 0a 20 20 20 20 20  MethodsV2;.     
47c0: 20 7d 0a 20 20 20 20 20 20 2f 2a 20 70 6c 61 63   }.      /* plac
47d0: 65 20 74 68 69 73 20 67 72 6f 75 70 20 61 74 20  e this group at 
47e0: 74 68 65 20 68 65 61 64 20 6f 66 20 6f 75 72 20  the head of our 
47f0: 6c 69 73 74 20 2a 2f 0a 20 20 20 20 20 20 70 47  list */.      pG
4800: 72 6f 75 70 2d 3e 70 4e 65 78 74 20 3d 20 67 4d  roup->pNext = gM
4810: 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73  ultiplex.pGroups
4820: 3b 0a 20 20 20 20 20 20 69 66 28 20 67 4d 75 6c  ;.      if( gMul
4830: 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 29  tiplex.pGroups )
4840: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f   gMultiplex.pGro
4850: 75 70 73 2d 3e 70 50 72 65 76 20 3d 20 70 47 72  ups->pPrev = pGr
4860: 6f 75 70 3b 0a 20 20 20 20 20 20 67 4d 75 6c 74  oup;.      gMult
4870: 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 3d 20  iplex.pGroups = 
4880: 70 47 72 6f 75 70 3b 0a 20 20 20 20 7d 65 6c 73  pGroup;.    }els
4890: 65 7b 0a 20 20 20 20 20 20 6d 75 6c 74 69 70 6c  e{.      multipl
48a0: 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74 73  exFreeComponents
48b0: 28 70 47 72 6f 75 70 29 3b 0a 20 20 20 20 20 20  (pGroup);.      
48c0: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72  sqlite3_free(pGr
48d0: 6f 75 70 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  oup);.    }.  }.
48e0: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
48f0: 28 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 72  ();.  sqlite3_fr
4900: 65 65 28 7a 54 6f 46 72 65 65 29 3b 0a 20 20 72  ee(zToFree);.  r
4910: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a  eturn rc;.}../*.
4920: 2a 2a 20 54 68 69 73 20 69 73 20 74 68 65 20 78  ** This is the x
4930: 44 65 6c 65 74 65 20 6d 65 74 68 6f 64 20 75 73  Delete method us
4940: 65 64 20 66 6f 72 20 74 68 65 20 22 6d 75 6c 74  ed for the "mult
4950: 69 70 6c 65 78 22 20 56 46 53 2e 0a 2a 2a 20 49  iplex" VFS..** I
4960: 74 20 61 74 74 65 6d 70 74 73 20 74 6f 20 64 65  t attempts to de
4970: 6c 65 74 65 20 74 68 65 20 66 69 6c 65 6e 61 6d  lete the filenam
4980: 65 20 73 70 65 63 69 66 69 65 64 2e 0a 2a 2f 0a  e specified..*/.
4990: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
49a0: 70 6c 65 78 44 65 6c 65 74 65 28 0a 20 20 73 71  plexDelete(.  sq
49b0: 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c  lite3_vfs *pVfs,
49c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20           /* The 
49d0: 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f  multiplex VFS */
49e0: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
49f0: 4e 61 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a  Name,         /*
4a00: 20 4e 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f   Name of file to
4a10: 20 64 65 6c 65 74 65 20 2a 2f 0a 20 20 69 6e 74   delete */.  int
4a20: 20 73 79 6e 63 44 69 72 0a 29 7b 0a 20 20 73 71   syncDir.){.  sq
4a30: 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67  lite3_vfs *pOrig
4a40: 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78  Vfs = gMultiplex
4a50: 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a 20  .pOrigVfs;   /* 
4a60: 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 72 65  Real VFS */.  re
4a70: 74 75 72 6e 20 70 4f 72 69 67 56 66 73 2d 3e 78  turn pOrigVfs->x
4a80: 44 65 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c  Delete(pOrigVfs,
4a90: 20 7a 4e 61 6d 65 2c 20 73 79 6e 63 44 69 72 29   zName, syncDir)
4aa0: 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74 20  ;.}..static int 
4ab0: 6d 75 6c 74 69 70 6c 65 78 41 63 63 65 73 73 28  multiplexAccess(
4ac0: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
4ad0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 62 2c 20 69  const char *b, i
4ae0: 6e 74 20 63 2c 20 69 6e 74 20 2a 64 29 7b 0a 20  nt c, int *d){. 
4af0: 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c   return gMultipl
4b00: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 41 63  ex.pOrigVfs->xAc
4b10: 63 65 73 73 28 67 4d 75 6c 74 69 70 6c 65 78 2e  cess(gMultiplex.
4b20: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 2c 20  pOrigVfs, b, c, 
4b30: 64 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  d);.}.static int
4b40: 20 6d 75 6c 74 69 70 6c 65 78 46 75 6c 6c 50 61   multiplexFullPa
4b50: 74 68 6e 61 6d 65 28 73 71 6c 69 74 65 33 5f 76  thname(sqlite3_v
4b60: 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61  fs *a, const cha
4b70: 72 20 2a 62 2c 20 69 6e 74 20 63 2c 20 63 68 61  r *b, int c, cha
4b80: 72 20 2a 64 29 7b 0a 20 20 72 65 74 75 72 6e 20  r *d){.  return 
4b90: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4ba0: 56 66 73 2d 3e 78 46 75 6c 6c 50 61 74 68 6e 61  Vfs->xFullPathna
4bb0: 6d 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  me(gMultiplex.pO
4bc0: 72 69 67 56 66 73 2c 20 62 2c 20 63 2c 20 64 29  rigVfs, b, c, d)
4bd0: 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20  ;.}.static void 
4be0: 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70 65 6e  *multiplexDlOpen
4bf0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
4c00: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 62 29 7b   const char *b){
4c10: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
4c20: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
4c30: 44 6c 4f 70 65 6e 28 67 4d 75 6c 74 69 70 6c 65  DlOpen(gMultiple
4c40: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a  x.pOrigVfs, b);.
4c50: 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75  }.static void mu
4c60: 6c 74 69 70 6c 65 78 44 6c 45 72 72 6f 72 28 73  ltiplexDlError(s
4c70: 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69  qlite3_vfs *a, i
4c80: 6e 74 20 62 2c 20 63 68 61 72 20 2a 63 29 7b 0a  nt b, char *c){.
4c90: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72    gMultiplex.pOr
4ca0: 69 67 56 66 73 2d 3e 78 44 6c 45 72 72 6f 72 28  igVfs->xDlError(
4cb0: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4cc0: 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74  Vfs, b, c);.}.st
4cd0: 61 74 69 63 20 76 6f 69 64 20 28 2a 6d 75 6c 74  atic void (*mult
4ce0: 69 70 6c 65 78 44 6c 53 79 6d 28 73 71 6c 69 74  iplexDlSym(sqlit
4cf0: 65 33 5f 76 66 73 20 2a 61 2c 20 76 6f 69 64 20  e3_vfs *a, void 
4d00: 2a 62 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  *b, const char *
4d10: 63 29 29 28 76 6f 69 64 29 7b 0a 20 20 72 65 74  c))(void){.  ret
4d20: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
4d30: 4f 72 69 67 56 66 73 2d 3e 78 44 6c 53 79 6d 28  OrigVfs->xDlSym(
4d40: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4d50: 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74  Vfs, b, c);.}.st
4d60: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
4d70: 6c 65 78 44 6c 43 6c 6f 73 65 28 73 71 6c 69 74  lexDlClose(sqlit
4d80: 65 33 5f 76 66 73 20 2a 61 2c 20 76 6f 69 64 20  e3_vfs *a, void 
4d90: 2a 62 29 7b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  *b){.  gMultiple
4da0: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 43  x.pOrigVfs->xDlC
4db0: 6c 6f 73 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e  lose(gMultiplex.
4dc0: 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a  pOrigVfs, b);.}.
4dd0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
4de0: 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73 28 73  plexRandomness(s
4df0: 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69  qlite3_vfs *a, i
4e00: 6e 74 20 62 2c 20 63 68 61 72 20 2a 63 29 7b 0a  nt b, char *c){.
4e10: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
4e20: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 52  lex.pOrigVfs->xR
4e30: 61 6e 64 6f 6d 6e 65 73 73 28 67 4d 75 6c 74 69  andomness(gMulti
4e40: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
4e50: 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69  , c);.}.static i
4e60: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65 65  nt multiplexSlee
4e70: 70 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  p(sqlite3_vfs *a
4e80: 2c 20 69 6e 74 20 62 29 7b 0a 20 20 72 65 74 75  , int b){.  retu
4e90: 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  rn gMultiplex.pO
4ea0: 72 69 67 56 66 73 2d 3e 78 53 6c 65 65 70 28 67  rigVfs->xSleep(g
4eb0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4ec0: 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63  fs, b);.}.static
4ed0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43 75   int multiplexCu
4ee0: 72 72 65 6e 74 54 69 6d 65 28 73 71 6c 69 74 65  rrentTime(sqlite
4ef0: 33 5f 76 66 73 20 2a 61 2c 20 64 6f 75 62 6c 65  3_vfs *a, double
4f00: 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *b){.  return g
4f10: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4f20: 66 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d 65  fs->xCurrentTime
4f30: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
4f40: 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74  gVfs, b);.}.stat
4f50: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
4f60: 47 65 74 4c 61 73 74 45 72 72 6f 72 28 73 71 6c  GetLastError(sql
4f70: 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74  ite3_vfs *a, int
4f80: 20 62 2c 20 63 68 61 72 20 2a 63 29 7b 0a 20 20   b, char *c){.  
4f90: 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65  return gMultiple
4fa0: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 47 65 74  x.pOrigVfs->xGet
4fb0: 4c 61 73 74 45 72 72 6f 72 28 67 4d 75 6c 74 69  LastError(gMulti
4fc0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
4fd0: 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69  , c);.}.static i
4fe0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72  nt multiplexCurr
4ff0: 65 6e 74 54 69 6d 65 49 6e 74 36 34 28 73 71 6c  entTimeInt64(sql
5000: 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 73 71 6c  ite3_vfs *a, sql
5010: 69 74 65 33 5f 69 6e 74 36 34 20 2a 62 29 7b 0a  ite3_int64 *b){.
5020: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
5030: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 43  lex.pOrigVfs->xC
5040: 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 28  urrentTimeInt64(
5050: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
5060: 56 66 73 2c 20 62 29 3b 0a 7d 0a 0a 2f 2a 2a 2a  Vfs, b);.}../***
5070: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
5080: 2a 2a 2a 2a 2a 20 49 2f 4f 20 4d 65 74 68 6f 64  ***** I/O Method
5090: 20 57 72 61 70 70 65 72 73 20 2a 2a 2a 2a 2a 2a   Wrappers ******
50a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
50b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 78  *********/../* x
50c0: 43 6c 6f 73 65 20 72 65 71 75 65 73 74 73 20 67  Close requests g
50d0: 65 74 20 70 61 73 73 65 64 20 74 68 72 6f 75 67  et passed throug
50e0: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
50f0: 6c 20 56 46 53 2e 0a 2a 2a 20 57 65 20 6c 6f 6f  l VFS..** We loo
5100: 70 20 6f 76 65 72 20 61 6c 6c 20 6f 70 65 6e 20  p over all open 
5110: 63 68 75 6e 6b 20 68 61 6e 64 6c 65 73 20 61 6e  chunk handles an
5120: 64 20 63 6c 6f 73 65 20 74 68 65 6d 2e 0a 2a 2a  d close them..**
5130: 20 54 68 65 20 67 72 6f 75 70 20 73 74 72 75 63   The group struc
5140: 74 75 72 65 20 66 6f 72 20 74 68 69 73 20 66 69  ture for this fi
5150: 6c 65 20 69 73 20 75 6e 6c 69 6e 6b 65 64 20 66  le is unlinked f
5160: 72 6f 6d 20 0a 2a 2a 20 6f 75 72 20 6c 69 73 74  rom .** our list
5170: 20 6f 66 20 67 72 6f 75 70 73 20 61 6e 64 20 66   of groups and f
5180: 72 65 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  reed..*/.static 
5190: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43 6c 6f  int multiplexClo
51a0: 73 65 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  se(sqlite3_file 
51b0: 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69  *pConn){.  multi
51c0: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
51d0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
51e0: 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  onn;.  multiplex
51f0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20  Group *pGroup = 
5200: 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74  p->pGroup;.  int
5210: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
5220: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
5230: 72 28 29 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  r();.  multiplex
5240: 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74 73 28 70  FreeComponents(p
5250: 47 72 6f 75 70 29 3b 0a 20 20 2f 2a 20 72 65 6d  Group);.  /* rem
5260: 6f 76 65 20 66 72 6f 6d 20 6c 69 6e 6b 65 64 20  ove from linked 
5270: 6c 69 73 74 20 2a 2f 0a 20 20 69 66 28 20 70 47  list */.  if( pG
5280: 72 6f 75 70 2d 3e 70 4e 65 78 74 20 29 20 70 47  roup->pNext ) pG
5290: 72 6f 75 70 2d 3e 70 4e 65 78 74 2d 3e 70 50 72  roup->pNext->pPr
52a0: 65 76 20 3d 20 70 47 72 6f 75 70 2d 3e 70 50 72  ev = pGroup->pPr
52b0: 65 76 3b 0a 20 20 69 66 28 20 70 47 72 6f 75 70  ev;.  if( pGroup
52c0: 2d 3e 70 50 72 65 76 20 29 7b 0a 20 20 20 20 70  ->pPrev ){.    p
52d0: 47 72 6f 75 70 2d 3e 70 50 72 65 76 2d 3e 70 4e  Group->pPrev->pN
52e0: 65 78 74 20 3d 20 70 47 72 6f 75 70 2d 3e 70 4e  ext = pGroup->pN
52f0: 65 78 74 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20  ext;.  }else{.  
5300: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72    gMultiplex.pGr
5310: 6f 75 70 73 20 3d 20 70 47 72 6f 75 70 2d 3e 70  oups = pGroup->p
5320: 4e 65 78 74 3b 0a 20 20 7d 0a 20 20 73 71 6c 69  Next;.  }.  sqli
5330: 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 29  te3_free(pGroup)
5340: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  ;.  multiplexLea
5350: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
5360: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 52  c;.}../* Pass xR
5370: 65 61 64 20 72 65 71 75 65 73 74 73 20 74 68 72  ead requests thr
5380: 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  u to the origina
5390: 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64  l VFS after.** d
53a0: 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63  etermining the c
53b0: 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20  orrect chunk to 
53c0: 6f 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20 42  operate on..** B
53d0: 72 65 61 6b 20 75 70 20 72 65 61 64 73 20 61 63  reak up reads ac
53e0: 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f 75 6e 64  ross chunk bound
53f0: 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  aries..*/.static
5400: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 52 65   int multiplexRe
5410: 61 64 28 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  ad(.  sqlite3_fi
5420: 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20 20 76 6f 69  le *pConn,.  voi
5430: 64 20 2a 70 42 75 66 2c 0a 20 20 69 6e 74 20 69  d *pBuf,.  int i
5440: 41 6d 74 2c 0a 20 20 73 71 6c 69 74 65 33 5f 69  Amt,.  sqlite3_i
5450: 6e 74 36 34 20 69 4f 66 73 74 0a 29 7b 0a 20 20  nt64 iOfst.){.  
5460: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
5470: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
5480: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74  n*)pConn;.  mult
5490: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
54a0: 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a  up = p->pGroup;.
54b0: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
54c0: 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  E_OK;.  multiple
54d0: 78 45 6e 74 65 72 28 29 3b 0a 20 20 69 66 28 20  xEnter();.  if( 
54e0: 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65  !pGroup->bEnable
54f0: 64 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33  d ){.    sqlite3
5500: 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20  _file *pSubOpen 
5510: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
5520: 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  en(pGroup, 0, &r
5530: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 69 66  c, NULL);.    if
5540: 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b  ( pSubOpen==0 ){
5550: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
5560: 54 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b 0a 20  TE_IOERR_READ;. 
5570: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
5580: 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  rc = pSubOpen->p
5590: 4d 65 74 68 6f 64 73 2d 3e 78 52 65 61 64 28 70  Methods->xRead(p
55a0: 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69  SubOpen, pBuf, i
55b0: 41 6d 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20  Amt, iOfst);.   
55c0: 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20   }.  }else{.    
55d0: 77 68 69 6c 65 28 20 69 41 6d 74 20 3e 20 30 20  while( iAmt > 0 
55e0: 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 69 20 3d  ){.      int i =
55f0: 20 28 69 6e 74 29 28 69 4f 66 73 74 20 2f 20 70   (int)(iOfst / p
5600: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b  Group->szChunk);
5610: 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66  .      sqlite3_f
5620: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
5630: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
5640: 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c  (pGroup, i, &rc,
5650: 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20 69 66   NULL);.      if
5660: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
5670: 20 20 20 20 20 20 69 6e 74 20 65 78 74 72 61 20        int extra 
5680: 3d 20 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25  = ((int)(iOfst %
5690: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
56a0: 29 20 2b 20 69 41 6d 74 29 20 2d 20 70 47 72 6f  ) + iAmt) - pGro
56b0: 75 70 2d 3e 73 7a 43 68 75 6e 6b 3b 0a 20 20 20  up->szChunk;.   
56c0: 20 20 20 20 20 69 66 28 20 65 78 74 72 61 3c 30       if( extra<0
56d0: 20 29 20 65 78 74 72 61 20 3d 20 30 3b 0a 20 20   ) extra = 0;.  
56e0: 20 20 20 20 20 20 69 41 6d 74 20 2d 3d 20 65 78        iAmt -= ex
56f0: 74 72 61 3b 0a 20 20 20 20 20 20 20 20 72 63 20  tra;.        rc 
5700: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
5710: 68 6f 64 73 2d 3e 78 52 65 61 64 28 70 53 75 62  hods->xRead(pSub
5720: 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74  Open, pBuf, iAmt
5730: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
5740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5750: 20 20 20 20 20 20 20 20 20 69 4f 66 73 74 20 25           iOfst %
5760: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
5770: 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 72  );.        if( r
5780: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62  c!=SQLITE_OK ) b
5790: 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 70 42  reak;.        pB
57a0: 75 66 20 3d 20 28 63 68 61 72 20 2a 29 70 42 75  uf = (char *)pBu
57b0: 66 20 2b 20 69 41 6d 74 3b 0a 20 20 20 20 20 20  f + iAmt;.      
57c0: 20 20 69 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b    iOfst += iAmt;
57d0: 0a 20 20 20 20 20 20 20 20 69 41 6d 74 20 3d 20  .        iAmt = 
57e0: 65 78 74 72 61 3b 0a 20 20 20 20 20 20 7d 65 6c  extra;.      }el
57f0: 73 65 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d  se{.        rc =
5800: 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45   SQLITE_IOERR_RE
5810: 41 44 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61  AD;.        brea
5820: 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  k;.      }.    }
5830: 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78  .  }.  multiplex
5840: 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72  Leave();.  retur
5850: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73  n rc;.}../* Pass
5860: 20 78 57 72 69 74 65 20 72 65 71 75 65 73 74 73   xWrite requests
5870: 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f 72 69   thru to the ori
5880: 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65 72 0a  ginal VFS after.
5890: 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74  ** determining t
58a0: 68 65 20 63 6f 72 72 65 63 74 20 63 68 75 6e 6b  he correct chunk
58b0: 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e 0a   to operate on..
58c0: 2a 2a 20 42 72 65 61 6b 20 75 70 20 77 72 69 74  ** Break up writ
58d0: 65 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b 20  es across chunk 
58e0: 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73  boundaries..*/.s
58f0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
5900: 6c 65 78 57 72 69 74 65 28 0a 20 20 73 71 6c 69  lexWrite(.  sqli
5910: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
5920: 0a 20 20 63 6f 6e 73 74 20 76 6f 69 64 20 2a 70  .  const void *p
5930: 42 75 66 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c  Buf,.  int iAmt,
5940: 0a 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34  .  sqlite3_int64
5950: 20 69 4f 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74   iOfst.){.  mult
5960: 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28  iplexConn *p = (
5970: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70  multiplexConn*)p
5980: 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  Conn;.  multiple
5990: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d  xGroup *pGroup =
59a0: 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e   p->pGroup;.  in
59b0: 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b  t rc = SQLITE_OK
59c0: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74  ;.  multiplexEnt
59d0: 65 72 28 29 3b 0a 20 20 69 66 28 20 21 70 47 72  er();.  if( !pGr
59e0: 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b  oup->bEnabled ){
59f0: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  .    sqlite3_fil
5a00: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
5a10: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
5a20: 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e  Group, 0, &rc, N
5a30: 55 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20 70 53  ULL);.    if( pS
5a40: 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20  ubOpen==0 ){.   
5a50: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49     rc = SQLITE_I
5a60: 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20 20 20 20  OERR_WRITE;.    
5a70: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20  }else{.      rc 
5a80: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
5a90: 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70 53 75  hods->xWrite(pSu
5aa0: 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d  bOpen, pBuf, iAm
5ab0: 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20 20 7d  t, iOfst);.    }
5ac0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 77 68  .  }else{.    wh
5ad0: 69 6c 65 28 20 69 41 6d 74 20 3e 20 30 20 29 7b  ile( iAmt > 0 ){
5ae0: 0a 20 20 20 20 20 20 69 6e 74 20 69 20 3d 20 28  .      int i = (
5af0: 69 6e 74 29 28 69 4f 66 73 74 20 2f 20 70 47 72  int)(iOfst / pGr
5b00: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20  oup->szChunk);. 
5b10: 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c       sqlite3_fil
5b20: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
5b30: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
5b40: 47 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c 20 4e  Group, i, &rc, N
5b50: 55 4c 4c 29 3b 0a 20 20 20 20 20 20 69 66 28 20  ULL);.      if( 
5b60: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
5b70: 20 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20      int extra = 
5b80: 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70  ((int)(iOfst % p
5b90: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20  Group->szChunk) 
5ba0: 2b 20 69 41 6d 74 29 20 2d 0a 20 20 20 20 20 20  + iAmt) -.      
5bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 47                pG
5bc0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 3b 0a 20  roup->szChunk;. 
5bd0: 20 20 20 20 20 20 20 69 66 28 20 65 78 74 72 61         if( extra
5be0: 3c 30 20 29 20 65 78 74 72 61 20 3d 20 30 3b 0a  <0 ) extra = 0;.
5bf0: 20 20 20 20 20 20 20 20 69 41 6d 74 20 2d 3d 20          iAmt -= 
5c00: 65 78 74 72 61 3b 0a 20 20 20 20 20 20 20 20 72  extra;.        r
5c10: 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  c = pSubOpen->pM
5c20: 65 74 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70  ethods->xWrite(p
5c30: 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69  SubOpen, pBuf, i
5c40: 41 6d 74 2c 0a 20 20 20 20 20 20 20 20 20 20 20  Amt,.           
5c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 4f 66               iOf
5c70: 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43  st % pGroup->szC
5c80: 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20 20 69  hunk);.        i
5c90: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
5ca0: 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20   ) break;.      
5cb0: 20 20 70 42 75 66 20 3d 20 28 63 68 61 72 20 2a    pBuf = (char *
5cc0: 29 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20  )pBuf + iAmt;.  
5cd0: 20 20 20 20 20 20 69 4f 66 73 74 20 2b 3d 20 69        iOfst += i
5ce0: 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 41 6d  Amt;.        iAm
5cf0: 74 20 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20  t = extra;.     
5d00: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
5d10: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
5d20: 52 5f 57 52 49 54 45 3b 0a 20 20 20 20 20 20 20  R_WRITE;.       
5d30: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a   break;.      }.
5d40: 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74      }.  }.  mult
5d50: 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20  iplexLeave();.  
5d60: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
5d70: 20 50 61 73 73 20 78 54 72 75 6e 63 61 74 65 20   Pass xTruncate 
5d80: 72 65 71 75 65 73 74 73 20 74 68 72 75 20 74 6f  requests thru to
5d90: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
5da0: 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72  S after.** deter
5db0: 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65  mining the corre
5dc0: 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72  ct chunk to oper
5dd0: 61 74 65 20 6f 6e 2e 20 20 44 65 6c 65 74 65 20  ate on.  Delete 
5de0: 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b 73 20 61 62  any.** chunks ab
5df0: 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61 74 65  ove the truncate
5e00: 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74 61 74 69 63   mark..*/.static
5e10: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 54 72   int multiplexTr
5e20: 75 6e 63 61 74 65 28 73 71 6c 69 74 65 33 5f 66  uncate(sqlite3_f
5e30: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71 6c 69  ile *pConn, sqli
5e40: 74 65 33 5f 69 6e 74 36 34 20 73 69 7a 65 29 7b  te3_int64 size){
5e50: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
5e60: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
5e70: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d  Conn*)pConn;.  m
5e80: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
5e90: 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75  Group = p->pGrou
5ea0: 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  p;.  int rc = SQ
5eb0: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69  LITE_OK;.  multi
5ec0: 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 69  plexEnter();.  i
5ed0: 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61  f( !pGroup->bEna
5ee0: 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71 6c 69  bled ){.    sqli
5ef0: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
5f00: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
5f10: 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c  bOpen(pGroup, 0,
5f20: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20   &rc, NULL);.   
5f30: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30   if( pSubOpen==0
5f40: 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 53   ){.      rc = S
5f50: 51 4c 49 54 45 5f 49 4f 45 52 52 5f 54 52 55 4e  QLITE_IOERR_TRUN
5f60: 43 41 54 45 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  CATE;.    }else{
5f70: 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62  .      rc = pSub
5f80: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
5f90: 78 54 72 75 6e 63 61 74 65 28 70 53 75 62 4f 70  xTruncate(pSubOp
5fa0: 65 6e 2c 20 73 69 7a 65 29 3b 0a 20 20 20 20 7d  en, size);.    }
5fb0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 69 6e  .  }else{.    in
5fc0: 74 20 72 63 32 3b 0a 20 20 20 20 69 6e 74 20 69  t rc2;.    int i
5fd0: 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69  ;.    sqlite3_fi
5fe0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 3b 0a 20 20  le *pSubOpen;.  
5ff0: 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70    sqlite3_vfs *p
6000: 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69  OrigVfs = gMulti
6010: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20  plex.pOrigVfs;  
6020: 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a   /* Real VFS */.
6030: 20 20 20 20 2f 2a 20 64 65 6c 65 74 65 20 74 68      /* delete th
6040: 65 20 63 68 75 6e 6b 73 20 61 62 6f 76 65 20 74  e chunks above t
6050: 68 65 20 74 72 75 6e 63 61 74 65 20 6c 69 6d 69  he truncate limi
6060: 74 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d 28  t */.    for(i=(
6070: 69 6e 74 29 28 73 69 7a 65 20 2f 20 70 47 72 6f  int)(size / pGro
6080: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 2b 31 3b 20  up->szChunk)+1; 
6090: 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b  i<pGroup->nReal;
60a0: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 6d 75 6c   i++){.      mul
60b0: 74 69 70 6c 65 78 53 75 62 43 6c 6f 73 65 28 70  tiplexSubClose(p
60c0: 47 72 6f 75 70 2c 20 69 2c 20 70 4f 72 69 67 56  Group, i, pOrigV
60d0: 66 73 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70  fs);.    }.    p
60e0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
60f0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
6100: 70 2c 20 28 69 6e 74 29 28 73 69 7a 65 2f 70 47  p, (int)(size/pG
6110: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 2c 20  roup->szChunk), 
6120: 26 72 63 32 2c 30 29 3b 0a 20 20 20 20 69 66 28  &rc2,0);.    if(
6130: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
6140: 20 20 20 72 63 32 20 3d 20 70 53 75 62 4f 70 65     rc2 = pSubOpe
6150: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 54 72  n->pMethods->xTr
6160: 75 6e 63 61 74 65 28 70 53 75 62 4f 70 65 6e 2c  uncate(pSubOpen,
6170: 20 73 69 7a 65 20 25 20 70 47 72 6f 75 70 2d 3e   size % pGroup->
6180: 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20  szChunk);.      
6190: 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f  if( rc2!=SQLITE_
61a0: 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a 20  OK ) rc = rc2;. 
61b0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
61c0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
61d0: 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20 20  R_TRUNCATE;.    
61e0: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
61f0: 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75  xLeave();.  retu
6200: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
6210: 73 20 78 53 79 6e 63 20 72 65 71 75 65 73 74 73  s xSync requests
6220: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
6230: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 77 69 74  original VFS wit
6240: 68 6f 75 74 20 63 68 61 6e 67 65 0a 2a 2f 0a 73  hout change.*/.s
6250: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6260: 6c 65 78 53 79 6e 63 28 73 71 6c 69 74 65 33 5f  lexSync(sqlite3_
6270: 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74  file *pConn, int
6280: 20 66 6c 61 67 73 29 7b 0a 20 20 6d 75 6c 74 69   flags){.  multi
6290: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
62a0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
62b0: 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  onn;.  multiplex
62c0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20  Group *pGroup = 
62d0: 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74  p->pGroup;.  int
62e0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
62f0: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75 6c 74  .  int i;.  mult
6300: 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20  iplexEnter();.  
6310: 66 6f 72 28 69 3d 30 3b 20 69 3c 70 47 72 6f 75  for(i=0; i<pGrou
6320: 70 2d 3e 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a  p->nReal; i++){.
6330: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
6340: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 70 47 72   *pSubOpen = pGr
6350: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 5d 2e 70 3b  oup->aReal[i].p;
6360: 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65  .    if( pSubOpe
6370: 6e 20 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 72  n ){.      int r
6380: 63 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  c2 = pSubOpen->p
6390: 4d 65 74 68 6f 64 73 2d 3e 78 53 79 6e 63 28 70  Methods->xSync(p
63a0: 53 75 62 4f 70 65 6e 2c 20 66 6c 61 67 73 29 3b  SubOpen, flags);
63b0: 0a 20 20 20 20 20 20 69 66 28 20 72 63 32 21 3d  .      if( rc2!=
63c0: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d  SQLITE_OK ) rc =
63d0: 20 72 63 32 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a   rc2;.    }.  }.
63e0: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
63f0: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
6400: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c  .}../* Pass xFil
6410: 65 53 69 7a 65 20 72 65 71 75 65 73 74 73 20 74  eSize requests t
6420: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
6430: 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 20 41  iginal VFS..** A
6440: 67 67 72 65 67 61 74 65 20 74 68 65 20 73 69 7a  ggregate the siz
6450: 65 20 6f 66 20 61 6c 6c 20 74 68 65 20 63 68 75  e of all the chu
6460: 6e 6b 73 20 62 65 66 6f 72 65 20 72 65 74 75 72  nks before retur
6470: 6e 69 6e 67 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ning..*/.static 
6480: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c  int multiplexFil
6490: 65 53 69 7a 65 28 73 71 6c 69 74 65 33 5f 66 69  eSize(sqlite3_fi
64a0: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71 6c 69 74  le *pConn, sqlit
64b0: 65 33 5f 69 6e 74 36 34 20 2a 70 53 69 7a 65 29  e3_int64 *pSize)
64c0: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
64d0: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
64e0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
64f0: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
6500: 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f  pGroup = p->pGro
6510: 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  up;.  int rc = S
6520: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
6530: 72 63 32 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  rc2;.  int i;.  
6540: 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29  multiplexEnter()
6550: 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d  ;.  if( !pGroup-
6560: 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20  >bEnabled ){.   
6570: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
6580: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
6590: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
65a0: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29  p, 0, &rc, NULL)
65b0: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
65c0: 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72  en==0 ){.      r
65d0: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
65e0: 5f 46 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c 73  _FSTAT;.    }els
65f0: 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53  e{.      rc = pS
6600: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
6610: 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62  ->xFileSize(pSub
6620: 4f 70 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20 20  Open, pSize);.  
6630: 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20    }.  }else{.   
6640: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f   sqlite3_vfs *pO
6650: 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70  rigVfs = gMultip
6660: 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 0a 20 20  lex.pOrigVfs;.  
6670: 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20    *pSize = 0;.  
6680: 20 20 66 6f 72 28 69 3d 30 3b 20 31 3b 20 69 2b    for(i=0; 1; i+
6690: 2b 29 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  +){.      sqlite
66a0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
66b0: 20 3d 20 30 3b 0a 20 20 20 20 20 20 69 6e 74 20   = 0;.      int 
66c0: 65 78 69 73 74 73 20 3d 20 30 3b 0a 20 20 20 20  exists = 0;.    
66d0: 20 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78    rc = multiplex
66e0: 53 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f  SubFilename(pGro
66f0: 75 70 2c 20 69 29 3b 0a 20 20 20 20 20 20 69 66  up, i);.      if
6700: 28 20 72 63 20 29 20 62 72 65 61 6b 3b 0a 20 20  ( rc ) break;.  
6710: 20 20 20 20 72 63 32 20 3d 20 70 4f 72 69 67 56      rc2 = pOrigV
6720: 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f 72 69  fs->xAccess(pOri
6730: 67 56 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61 52  gVfs, pGroup->aR
6740: 65 61 6c 5b 69 5d 2e 7a 2c 0a 20 20 20 20 20 20  eal[i].z,.      
6750: 20 20 20 20 53 51 4c 49 54 45 5f 41 43 43 45 53      SQLITE_ACCES
6760: 53 5f 45 58 49 53 54 53 2c 20 26 65 78 69 73 74  S_EXISTS, &exist
6770: 73 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63  s);.      if( rc
6780: 32 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20  2==SQLITE_OK && 
6790: 65 78 69 73 74 73 29 7b 0a 20 20 20 20 20 20 20  exists){.       
67a0: 20 2f 2a 20 69 66 20 69 74 20 65 78 69 73 74 73   /* if it exists
67b0: 2c 20 6f 70 65 6e 20 69 74 20 2a 2f 0a 20 20 20  , open it */.   
67c0: 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20       pSubOpen = 
67d0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
67e0: 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c  (pGroup, i, &rc,
67f0: 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20 7d 65   NULL);.      }e
6800: 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20  lse{.        /* 
6810: 73 74 6f 70 20 61 74 20 66 69 72 73 74 20 22 67  stop at first "g
6820: 61 70 22 20 2a 2f 0a 20 20 20 20 20 20 20 20 62  ap" */.        b
6830: 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20  reak;.      }.  
6840: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
6850: 20 29 7b 0a 20 20 20 20 20 20 20 20 73 71 6c 69   ){.        sqli
6860: 74 65 33 5f 69 6e 74 36 34 20 73 7a 3b 0a 20 20  te3_int64 sz;.  
6870: 20 20 20 20 20 20 72 63 32 20 3d 20 70 53 75 62        rc2 = pSub
6880: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
6890: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70  xFileSize(pSubOp
68a0: 65 6e 2c 20 26 73 7a 29 3b 0a 20 20 20 20 20 20  en, &sz);.      
68b0: 20 20 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54    if( rc2!=SQLIT
68c0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  E_OK ){.        
68d0: 20 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20 20    rc = rc2;.    
68e0: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
68f0: 20 20 20 20 20 69 66 28 20 73 7a 3e 70 47 72 6f       if( sz>pGro
6900: 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 29 7b 0a 20  up->szChunk ){. 
6910: 20 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20             rc = 
6920: 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 46 53 54  SQLITE_IOERR_FST
6930: 41 54 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a  AT;.          }.
6940: 20 20 20 20 20 20 20 20 20 20 2a 70 53 69 7a 65            *pSize
6950: 20 2b 3d 20 73 7a 3b 0a 20 20 20 20 20 20 20 20   += sz;.        
6960: 7d 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  }.      }else{. 
6970: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
6980: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
6990: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
69a0: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
69b0: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 4c 6f 63  .}../* Pass xLoc
69c0: 6b 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  k requests throu
69d0: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
69e0: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
69f0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
6a00: 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b 28 73 71  multiplexLock(sq
6a10: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
6a20: 6e 2c 20 69 6e 74 20 6c 6f 63 6b 29 7b 0a 20 20  n, int lock){.  
6a30: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
6a40: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
6a50: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
6a60: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
6a70: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
6a80: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
6a90: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
6aa0: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20  c, NULL);.  if( 
6ab0: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
6ac0: 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d  return pSubOpen-
6ad0: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 4c 6f 63 6b  >pMethods->xLock
6ae0: 28 70 53 75 62 4f 70 65 6e 2c 20 6c 6f 63 6b 29  (pSubOpen, lock)
6af0: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53  ;.  }.  return S
6b00: 51 4c 49 54 45 5f 42 55 53 59 3b 0a 7d 0a 0a 2f  QLITE_BUSY;.}../
6b10: 2a 20 50 61 73 73 20 78 55 6e 6c 6f 63 6b 20 72  * Pass xUnlock r
6b20: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
6b30: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
6b40: 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a  VFS unchanged..*
6b50: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
6b60: 74 69 70 6c 65 78 55 6e 6c 6f 63 6b 28 73 71 6c  tiplexUnlock(sql
6b70: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
6b80: 2c 20 69 6e 74 20 6c 6f 63 6b 29 7b 0a 20 20 6d  , int lock){.  m
6b90: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
6ba0: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
6bb0: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
6bc0: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
6bd0: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
6be0: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
6bf0: 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63  ->pGroup, 0, &rc
6c00: 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70  , NULL);.  if( p
6c10: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72  SubOpen ){.    r
6c20: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e  eturn pSubOpen->
6c30: 70 4d 65 74 68 6f 64 73 2d 3e 78 55 6e 6c 6f 63  pMethods->xUnloc
6c40: 6b 28 70 53 75 62 4f 70 65 6e 2c 20 6c 6f 63 6b  k(pSubOpen, lock
6c50: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
6c60: 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 55 4e 4c  SQLITE_IOERR_UNL
6c70: 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  OCK;.}../* Pass 
6c80: 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f  xCheckReservedLo
6c90: 63 6b 20 72 65 71 75 65 73 74 73 20 74 68 72 6f  ck requests thro
6ca0: 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69  ugh to the origi
6cb0: 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65  nal VFS unchange
6cc0: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
6cd0: 20 6d 75 6c 74 69 70 6c 65 78 43 68 65 63 6b 52   multiplexCheckR
6ce0: 65 73 65 72 76 65 64 4c 6f 63 6b 28 73 71 6c 69  eservedLock(sqli
6cf0: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
6d00: 20 69 6e 74 20 2a 70 52 65 73 4f 75 74 29 7b 0a   int *pResOut){.
6d10: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
6d20: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
6d30: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
6d40: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
6d50: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
6d60: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
6d70: 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20  n(p->pGroup, 0, 
6d80: 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66  &rc, NULL);.  if
6d90: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
6da0: 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65    return pSubOpe
6db0: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 43 68  n->pMethods->xCh
6dc0: 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 28  eckReservedLock(
6dd0: 70 53 75 62 4f 70 65 6e 2c 20 70 52 65 73 4f 75  pSubOpen, pResOu
6de0: 74 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  t);.  }.  return
6df0: 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 43 48   SQLITE_IOERR_CH
6e00: 45 43 4b 52 45 53 45 52 56 45 44 4c 4f 43 4b 3b  ECKRESERVEDLOCK;
6e10: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c  .}../* Pass xFil
6e20: 65 43 6f 6e 74 72 6f 6c 20 72 65 71 75 65 73 74  eControl request
6e30: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
6e40: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
6e50: 63 68 61 6e 67 65 64 2c 0a 2a 2a 20 65 78 63 65  changed,.** exce
6e60: 70 74 20 66 6f 72 20 61 6e 79 20 4d 55 4c 54 49  pt for any MULTI
6e70: 50 4c 45 58 5f 43 54 52 4c 5f 2a 20 72 65 71 75  PLEX_CTRL_* requ
6e80: 65 73 74 73 20 68 65 72 65 2e 0a 2a 2f 0a 73 74  ests here..*/.st
6e90: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
6ea0: 65 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 73 71  exFileControl(sq
6eb0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
6ec0: 6e 2c 20 69 6e 74 20 6f 70 2c 20 76 6f 69 64 20  n, int op, void 
6ed0: 2a 70 41 72 67 29 7b 0a 20 20 6d 75 6c 74 69 70  *pArg){.  multip
6ee0: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
6ef0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
6f00: 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47  nn;.  multiplexG
6f10: 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70  roup *pGroup = p
6f20: 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20  ->pGroup;.  int 
6f30: 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f  rc = SQLITE_ERRO
6f40: 52 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  R;.  sqlite3_fil
6f50: 65 20 2a 70 53 75 62 4f 70 65 6e 3b 0a 0a 20 20  e *pSubOpen;..  
6f60: 69 66 28 20 21 67 4d 75 6c 74 69 70 6c 65 78 2e  if( !gMultiplex.
6f70: 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 29 20  isInitialized ) 
6f80: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49  return SQLITE_MI
6f90: 53 55 53 45 3b 0a 20 20 73 77 69 74 63 68 28 20  SUSE;.  switch( 
6fa0: 6f 70 20 29 7b 0a 20 20 20 20 63 61 73 65 20 4d  op ){.    case M
6fb0: 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e  ULTIPLEX_CTRL_EN
6fc0: 41 42 4c 45 3a 0a 20 20 20 20 20 20 69 66 28 20  ABLE:.      if( 
6fd0: 70 41 72 67 20 29 20 7b 0a 20 20 20 20 20 20 20  pArg ) {.       
6fe0: 20 69 6e 74 20 62 45 6e 61 62 6c 65 64 20 3d 20   int bEnabled = 
6ff0: 2a 28 69 6e 74 20 2a 29 70 41 72 67 3b 0a 20 20  *(int *)pArg;.  
7000: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45        pGroup->bE
7010: 6e 61 62 6c 65 64 20 3d 20 62 45 6e 61 62 6c 65  nabled = bEnable
7020: 64 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  d;.        rc = 
7030: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20  SQLITE_OK;.     
7040: 20 7d 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a   }.      break;.
7050: 20 20 20 20 63 61 73 65 20 4d 55 4c 54 49 50 4c      case MULTIPL
7060: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
7070: 4b 5f 53 49 5a 45 3a 0a 20 20 20 20 20 20 69 66  K_SIZE:.      if
7080: 28 20 70 41 72 67 20 29 20 7b 0a 20 20 20 20 20  ( pArg ) {.     
7090: 20 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20     unsigned int 
70a0: 73 7a 43 68 75 6e 6b 20 3d 20 2a 28 75 6e 73 69  szChunk = *(unsi
70b0: 67 6e 65 64 2a 29 70 41 72 67 3b 0a 20 20 20 20  gned*)pArg;.    
70c0: 20 20 20 20 69 66 28 20 73 7a 43 68 75 6e 6b 3c      if( szChunk<
70d0: 31 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72  1 ){.          r
70e0: 63 20 3d 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  c = SQLITE_MISUS
70f0: 45 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65  E;.        }else
7100: 7b 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52  {.          /* R
7110: 6f 75 6e 64 20 75 70 20 74 6f 20 6e 65 61 72 65  ound up to neare
7120: 73 74 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d  st multiple of M
7130: 41 58 5f 50 41 47 45 5f 53 49 5a 45 2e 20 2a 2f  AX_PAGE_SIZE. */
7140: 0a 20 20 20 20 20 20 20 20 20 20 73 7a 43 68 75  .          szChu
7150: 6e 6b 20 3d 20 28 73 7a 43 68 75 6e 6b 20 2b 20  nk = (szChunk + 
7160: 28 4d 41 58 5f 50 41 47 45 5f 53 49 5a 45 2d 31  (MAX_PAGE_SIZE-1
7170: 29 29 3b 0a 20 20 20 20 20 20 20 20 20 20 73 7a  ));.          sz
7180: 43 68 75 6e 6b 20 26 3d 20 7e 28 4d 41 58 5f 50  Chunk &= ~(MAX_P
7190: 41 47 45 5f 53 49 5a 45 2d 31 29 3b 0a 20 20 20  AGE_SIZE-1);.   
71a0: 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73         pGroup->s
71b0: 7a 43 68 75 6e 6b 20 3d 20 73 7a 43 68 75 6e 6b  zChunk = szChunk
71c0: 3b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  ;.          rc =
71d0: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20   SQLITE_OK;.    
71e0: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20      }.      }.  
71f0: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 63      break;.    c
7200: 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  ase MULTIPLEX_CT
7210: 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b  RL_SET_MAX_CHUNK
7220: 53 3a 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51  S:.      rc = SQ
7230: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62  LITE_OK;.      b
7240: 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 53  reak;.    case S
7250: 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 53 49 5a 45  QLITE_FCNTL_SIZE
7260: 5f 48 49 4e 54 3a 0a 20 20 20 20 63 61 73 65 20  _HINT:.    case 
7270: 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 43 48 55  SQLITE_FCNTL_CHU
7280: 4e 4b 5f 53 49 5a 45 3a 0a 20 20 20 20 20 20 2f  NK_SIZE:.      /
7290: 2a 20 6e 6f 2d 6f 70 20 74 68 65 73 65 20 2a 2f  * no-op these */
72a0: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
72b0: 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65  TE_OK;.      bre
72c0: 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74 3a  ak;.    default:
72d0: 0a 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20  .      pSubOpen 
72e0: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
72f0: 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  en(pGroup, 0, &r
7300: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20  c, NULL);.      
7310: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
7320: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
7330: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
7340: 3e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 70 53  >xFileControl(pS
7350: 75 62 4f 70 65 6e 2c 20 6f 70 2c 20 70 41 72 67  ubOpen, op, pArg
7360: 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20  );.      }.     
7370: 20 62 72 65 61 6b 3b 0a 20 20 7d 0a 20 20 72 65   break;.  }.  re
7380: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50  turn rc;.}../* P
7390: 61 73 73 20 78 53 65 63 74 6f 72 53 69 7a 65 20  ass xSectorSize 
73a0: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
73b0: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
73c0: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
73d0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
73e0: 6c 74 69 70 6c 65 78 53 65 63 74 6f 72 53 69 7a  ltiplexSectorSiz
73f0: 65 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  e(sqlite3_file *
7400: 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70  pConn){.  multip
7410: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
7420: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
7430: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
7440: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7450: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
7460: 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72  exSubOpen(p->pGr
7470: 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  oup, 0, &rc, NUL
7480: 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  L);.  if( pSubOp
7490: 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  en ){.    return
74a0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
74b0: 6f 64 73 2d 3e 78 53 65 63 74 6f 72 53 69 7a 65  ods->xSectorSize
74c0: 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a  (pSubOpen);.  }.
74d0: 20 20 72 65 74 75 72 6e 20 44 45 46 41 55 4c 54    return DEFAULT
74e0: 5f 53 45 43 54 4f 52 5f 53 49 5a 45 3b 0a 7d 0a  _SECTOR_SIZE;.}.
74f0: 0a 2f 2a 20 50 61 73 73 20 78 44 65 76 69 63 65  ./* Pass xDevice
7500: 43 68 61 72 61 63 74 65 72 69 73 74 69 63 73 20  Characteristics 
7510: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
7520: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
7530: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
7540: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
7550: 6c 74 69 70 6c 65 78 44 65 76 69 63 65 43 68 61  ltiplexDeviceCha
7560: 72 61 63 74 65 72 69 73 74 69 63 73 28 73 71 6c  racteristics(sql
7570: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
7580: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
7590: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
75a0: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
75b0: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
75c0: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
75d0: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
75e0: 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20  Open(p->pGroup, 
75f0: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20  0, &rc, NULL);. 
7600: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
7610: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
7620: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
7630: 78 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72  xDeviceCharacter
7640: 69 73 74 69 63 73 28 70 53 75 62 4f 70 65 6e 29  istics(pSubOpen)
7650: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 30  ;.  }.  return 0
7660: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68  ;.}../* Pass xSh
7670: 6d 4d 61 70 20 72 65 71 75 65 73 74 73 20 74 68  mMap requests th
7680: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
7690: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
76a0: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
76b0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4d  nt multiplexShmM
76c0: 61 70 28 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  ap(.  sqlite3_fi
76d0: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20  le *pConn,      
76e0: 20 20 20 20 20 20 2f 2a 20 48 61 6e 64 6c 65 20        /* Handle 
76f0: 6f 70 65 6e 20 6f 6e 20 64 61 74 61 62 61 73 65  open on database
7700: 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 69   file */.  int i
7710: 52 65 67 69 6f 6e 2c 20 20 20 20 20 20 20 20 20  Region,         
7720: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
7730: 67 69 6f 6e 20 74 6f 20 72 65 74 72 69 65 76 65  gion to retrieve
7740: 20 2a 2f 0a 20 20 69 6e 74 20 73 7a 52 65 67 69   */.  int szRegi
7750: 6f 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  on,             
7760: 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66        /* Size of
7770: 20 72 65 67 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e   regions */.  in
7780: 74 20 62 45 78 74 65 6e 64 2c 20 20 20 20 20 20  t bExtend,      
7790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
77a0: 20 54 72 75 65 20 74 6f 20 65 78 74 65 6e 64 20   True to extend 
77b0: 66 69 6c 65 20 69 66 20 6e 65 63 65 73 73 61 72  file if necessar
77c0: 79 20 2a 2f 0a 20 20 76 6f 69 64 20 76 6f 6c 61  y */.  void vola
77d0: 74 69 6c 65 20 2a 2a 70 70 20 20 20 20 20 20 20  tile **pp       
77e0: 20 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 4d         /* OUT: M
77f0: 61 70 70 65 64 20 6d 65 6d 6f 72 79 20 2a 2f 0a  apped memory */.
7800: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
7810: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
7820: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
7830: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
7840: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
7850: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
7860: 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20  Open(p->pGroup, 
7870: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20  0, &rc, NULL);. 
7880: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
7890: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
78a0: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
78b0: 78 53 68 6d 4d 61 70 28 70 53 75 62 4f 70 65 6e  xShmMap(pSubOpen
78c0: 2c 20 69 52 65 67 69 6f 6e 2c 20 73 7a 52 65 67  , iRegion, szReg
78d0: 69 6f 6e 2c 20 62 45 78 74 65 6e 64 2c 70 70 29  ion, bExtend,pp)
78e0: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53  ;.  }.  return S
78f0: 51 4c 49 54 45 5f 49 4f 45 52 52 3b 0a 7d 0a 0a  QLITE_IOERR;.}..
7900: 2f 2a 20 50 61 73 73 20 78 53 68 6d 4c 6f 63 6b  /* Pass xShmLock
7910: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
7920: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
7930: 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e  l VFS unchanged.
7940: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
7950: 75 6c 74 69 70 6c 65 78 53 68 6d 4c 6f 63 6b 28  ultiplexShmLock(
7960: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
7970: 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20 20 2f 2a  *pConn,       /*
7980: 20 44 61 74 61 62 61 73 65 20 66 69 6c 65 20 68   Database file h
7990: 6f 6c 64 69 6e 67 20 74 68 65 20 73 68 61 72 65  olding the share
79a0: 64 20 6d 65 6d 6f 72 79 20 2a 2f 0a 20 20 69 6e  d memory */.  in
79b0: 74 20 6f 66 73 74 2c 20 20 20 20 20 20 20 20 20  t ofst,         
79c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 69 72 73           /* Firs
79d0: 74 20 6c 6f 63 6b 20 74 6f 20 61 63 71 75 69 72  t lock to acquir
79e0: 65 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f 0a  e or release */.
79f0: 20 20 69 6e 74 20 6e 2c 20 20 20 20 20 20 20 20    int n,        
7a00: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
7a10: 4e 75 6d 62 65 72 20 6f 66 20 6c 6f 63 6b 73 20  Number of locks 
7a20: 74 6f 20 61 63 71 75 69 72 65 20 6f 72 20 72 65  to acquire or re
7a30: 6c 65 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 66  lease */.  int f
7a40: 6c 61 67 73 20 20 20 20 20 20 20 20 20 20 20 20  lags            
7a50: 20 20 20 20 20 20 2f 2a 20 57 68 61 74 20 74 6f        /* What to
7a60: 20 64 6f 20 77 69 74 68 20 74 68 65 20 6c 6f 63   do with the loc
7a70: 6b 20 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74 69 70  k */.){.  multip
7a80: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
7a90: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
7aa0: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
7ab0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7ac0: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
7ad0: 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72  exSubOpen(p->pGr
7ae0: 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  oup, 0, &rc, NUL
7af0: 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  L);.  if( pSubOp
7b00: 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  en ){.    return
7b10: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7b20: 6f 64 73 2d 3e 78 53 68 6d 4c 6f 63 6b 28 70 53  ods->xShmLock(pS
7b30: 75 62 4f 70 65 6e 2c 20 6f 66 73 74 2c 20 6e 2c  ubOpen, ofst, n,
7b40: 20 66 6c 61 67 73 29 3b 0a 20 20 7d 0a 20 20 72   flags);.  }.  r
7b50: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53  eturn SQLITE_BUS
7b60: 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53  Y;.}../* Pass xS
7b70: 68 6d 42 61 72 72 69 65 72 20 72 65 71 75 65 73  hmBarrier reques
7b80: 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68  ts through to th
7b90: 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75  e original VFS u
7ba0: 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61  nchanged..*/.sta
7bb0: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
7bc0: 65 78 53 68 6d 42 61 72 72 69 65 72 28 73 71 6c  exShmBarrier(sql
7bd0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
7be0: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
7bf0: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
7c00: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
7c10: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
7c20: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
7c30: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
7c40: 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20  Open(p->pGroup, 
7c50: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20  0, &rc, NULL);. 
7c60: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
7c70: 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70  .    pSubOpen->p
7c80: 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 42 61 72  Methods->xShmBar
7c90: 72 69 65 72 28 70 53 75 62 4f 70 65 6e 29 3b 0a  rier(pSubOpen);.
7ca0: 20 20 7d 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78    }.}../* Pass x
7cb0: 53 68 6d 55 6e 6d 61 70 20 72 65 71 75 65 73 74  ShmUnmap request
7cc0: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
7cd0: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
7ce0: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
7cf0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
7d00: 53 68 6d 55 6e 6d 61 70 28 73 71 6c 69 74 65 33  ShmUnmap(sqlite3
7d10: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e  _file *pConn, in
7d20: 74 20 64 65 6c 65 74 65 46 6c 61 67 29 7b 0a 20  t deleteFlag){. 
7d30: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
7d40: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
7d50: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
7d60: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
7d70: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
7d80: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
7d90: 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26  (p->pGroup, 0, &
7da0: 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28  rc, NULL);.  if(
7db0: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
7dc0: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
7dd0: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d  ->pMethods->xShm
7de0: 55 6e 6d 61 70 28 70 53 75 62 4f 70 65 6e 2c 20  Unmap(pSubOpen, 
7df0: 64 65 6c 65 74 65 46 6c 61 67 29 3b 0a 20 20 7d  deleteFlag);.  }
7e00: 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45  .  return SQLITE
7e10: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a  _OK;.}../*******
7e20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
7e30: 2a 2a 2a 20 50 75 62 6c 69 63 20 49 6e 74 65 72  *** Public Inter
7e40: 66 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  faces **********
7e50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
7e60: 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a  ***/./*.** CAPI:
7e70: 20 49 6e 69 74 69 61 6c 69 7a 65 20 74 68 65 20   Initialize the 
7e80: 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 73 68  multiplex VFS sh
7e90: 69 6d 20 2d 20 73 71 6c 69 74 65 33 5f 6d 75 6c  im - sqlite3_mul
7ea0: 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a  tiplex_initializ
7eb0: 65 28 29 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74 68  e().**.** Use th
7ec0: 65 20 56 46 53 20 6e 61 6d 65 64 20 7a 4f 72 69  e VFS named zOri
7ed0: 67 56 66 73 4e 61 6d 65 20 61 73 20 74 68 65 20  gVfsName as the 
7ee0: 56 46 53 20 74 68 61 74 20 64 6f 65 73 20 74 68  VFS that does th
7ef0: 65 20 61 63 74 75 61 6c 20 77 6f 72 6b 2e 20 20  e actual work.  
7f00: 0a 2a 2a 20 55 73 65 20 74 68 65 20 64 65 66 61  .** Use the defa
7f10: 75 6c 74 20 69 66 20 7a 4f 72 69 67 56 66 73 4e  ult if zOrigVfsN
7f20: 61 6d 65 3d 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a 0a  ame==NULL.  .**.
7f30: 2a 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78  ** The multiplex
7f40: 20 56 46 53 20 73 68 69 6d 20 69 73 20 6e 61 6d   VFS shim is nam
7f50: 65 64 20 22 6d 75 6c 74 69 70 6c 65 78 22 2e 20  ed "multiplex". 
7f60: 20 49 74 20 77 69 6c 6c 20 62 65 63 6f 6d 65 20   It will become 
7f70: 74 68 65 20 64 65 66 61 75 6c 74 0a 2a 2a 20 56  the default.** V
7f80: 46 53 20 69 66 20 6d 61 6b 65 44 65 66 61 75 6c  FS if makeDefaul
7f90: 74 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a 2a  t is non-zero..*
7fa0: 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49 4e  *.** THIS ROUTIN
7fb0: 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44 53  E IS NOT THREADS
7fc0: 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73 20  AFE.  Call this 
7fd0: 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79 20  routine exactly 
7fe0: 6f 6e 63 65 0a 2a 2a 20 64 75 72 69 6e 67 20 73  once.** during s
7ff0: 74 61 72 74 2d 75 70 2e 0a 2a 2f 0a 69 6e 74 20  tart-up..*/.int 
8000: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
8010: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 63 6f 6e  x_initialize(con
8020: 73 74 20 63 68 61 72 20 2a 7a 4f 72 69 67 56 66  st char *zOrigVf
8030: 73 4e 61 6d 65 2c 20 69 6e 74 20 6d 61 6b 65 44  sName, int makeD
8040: 65 66 61 75 6c 74 29 7b 0a 20 20 73 71 6c 69 74  efault){.  sqlit
8050: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
8060: 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c  ;.  if( gMultipl
8070: 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64  ex.isInitialized
8080: 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45   ) return SQLITE
8090: 5f 4d 49 53 55 53 45 3b 0a 20 20 70 4f 72 69 67  _MISUSE;.  pOrig
80a0: 56 66 73 20 3d 20 73 71 6c 69 74 65 33 5f 76 66  Vfs = sqlite3_vf
80b0: 73 5f 66 69 6e 64 28 7a 4f 72 69 67 56 66 73 4e  s_find(zOrigVfsN
80c0: 61 6d 65 29 3b 0a 20 20 69 66 28 20 70 4f 72 69  ame);.  if( pOri
80d0: 67 56 66 73 3d 3d 30 20 29 20 72 65 74 75 72 6e  gVfs==0 ) return
80e0: 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20   SQLITE_ERROR;. 
80f0: 20 61 73 73 65 72 74 28 20 70 4f 72 69 67 56 66   assert( pOrigVf
8100: 73 21 3d 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73  s!=&gMultiplex.s
8110: 54 68 69 73 56 66 73 20 29 3b 0a 20 20 67 4d 75  ThisVfs );.  gMu
8120: 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20 3d  ltiplex.pMutex =
8130: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 61   sqlite3_mutex_a
8140: 6c 6c 6f 63 28 53 51 4c 49 54 45 5f 4d 55 54 45  lloc(SQLITE_MUTE
8150: 58 5f 46 41 53 54 29 3b 0a 20 20 69 66 28 20 21  X_FAST);.  if( !
8160: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65  gMultiplex.pMute
8170: 78 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  x ){.    return 
8180: 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20  SQLITE_NOMEM;.  
8190: 7d 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  }.  gMultiplex.p
81a0: 47 72 6f 75 70 73 20 3d 20 4e 55 4c 4c 3b 0a 20  Groups = NULL;. 
81b0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e   gMultiplex.isIn
81c0: 69 74 69 61 6c 69 7a 65 64 20 3d 20 31 3b 0a 20  itialized = 1;. 
81d0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
81e0: 67 56 66 73 20 3d 20 70 4f 72 69 67 56 66 73 3b  gVfs = pOrigVfs;
81f0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
8200: 68 69 73 56 66 73 20 3d 20 2a 70 4f 72 69 67 56  hisVfs = *pOrigV
8210: 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  fs;.  gMultiplex
8220: 2e 73 54 68 69 73 56 66 73 2e 73 7a 4f 73 46 69  .sThisVfs.szOsFi
8230: 6c 65 20 2b 3d 20 73 69 7a 65 6f 66 28 6d 75 6c  le += sizeof(mul
8240: 74 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a 20 20 67  tiplexConn);.  g
8250: 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56  Multiplex.sThisV
8260: 66 73 2e 7a 4e 61 6d 65 20 3d 20 53 51 4c 49 54  fs.zName = SQLIT
8270: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f  E_MULTIPLEX_VFS_
8280: 4e 41 4d 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  NAME;.  gMultipl
8290: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 4f 70 65  ex.sThisVfs.xOpe
82a0: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4f 70 65  n = multiplexOpe
82b0: 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  n;.  gMultiplex.
82c0: 73 54 68 69 73 56 66 73 2e 78 44 65 6c 65 74 65  sThisVfs.xDelete
82d0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c 65   = multiplexDele
82e0: 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  te;.  gMultiplex
82f0: 2e 73 54 68 69 73 56 66 73 2e 78 41 63 63 65 73  .sThisVfs.xAcces
8300: 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78 41 63 63  s = multiplexAcc
8310: 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ess;.  gMultiple
8320: 78 2e 73 54 68 69 73 56 66 73 2e 78 46 75 6c 6c  x.sThisVfs.xFull
8330: 50 61 74 68 6e 61 6d 65 20 3d 20 6d 75 6c 74 69  Pathname = multi
8340: 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65  plexFullPathname
8350: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
8360: 54 68 69 73 56 66 73 2e 78 44 6c 4f 70 65 6e 20  ThisVfs.xDlOpen 
8370: 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70 65  = multiplexDlOpe
8380: 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  n;.  gMultiplex.
8390: 73 54 68 69 73 56 66 73 2e 78 44 6c 45 72 72 6f  sThisVfs.xDlErro
83a0: 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 45  r = multiplexDlE
83b0: 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  rror;.  gMultipl
83c0: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 53  ex.sThisVfs.xDlS
83d0: 79 6d 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c  ym = multiplexDl
83e0: 53 79 6d 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  Sym;.  gMultiple
83f0: 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 43 6c  x.sThisVfs.xDlCl
8400: 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44  ose = multiplexD
8410: 6c 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74 69  lClose;.  gMulti
8420: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 52  plex.sThisVfs.xR
8430: 61 6e 64 6f 6d 6e 65 73 73 20 3d 20 6d 75 6c 74  andomness = mult
8440: 69 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73 3b  iplexRandomness;
8450: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
8460: 68 69 73 56 66 73 2e 78 53 6c 65 65 70 20 3d 20  hisVfs.xSleep = 
8470: 6d 75 6c 74 69 70 6c 65 78 53 6c 65 65 70 3b 0a  multiplexSleep;.
8480: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
8490: 69 73 56 66 73 2e 78 43 75 72 72 65 6e 74 54 69  isVfs.xCurrentTi
84a0: 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75  me = multiplexCu
84b0: 72 72 65 6e 74 54 69 6d 65 3b 0a 20 20 67 4d 75  rrentTime;.  gMu
84c0: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
84d0: 2e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 20 3d  .xGetLastError =
84e0: 20 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c 61 73   multiplexGetLas
84f0: 74 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69  tError;.  gMulti
8500: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 43  plex.sThisVfs.xC
8510: 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 20  urrentTimeInt64 
8520: 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65  = multiplexCurre
8530: 6e 74 54 69 6d 65 49 6e 74 36 34 3b 0a 0a 20 20  ntTimeInt64;..  
8540: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
8550: 74 68 6f 64 73 56 31 2e 69 56 65 72 73 69 6f 6e  thodsV1.iVersion
8560: 20 3d 20 31 3b 0a 20 20 67 4d 75 6c 74 69 70 6c   = 1;.  gMultipl
8570: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
8580: 78 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c  xClose = multipl
8590: 65 78 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74  exClose;.  gMult
85a0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
85b0: 56 31 2e 78 52 65 61 64 20 3d 20 6d 75 6c 74 69  V1.xRead = multi
85c0: 70 6c 65 78 52 65 61 64 3b 0a 20 20 67 4d 75 6c  plexRead;.  gMul
85d0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
85e0: 73 56 31 2e 78 57 72 69 74 65 20 3d 20 6d 75 6c  sV1.xWrite = mul
85f0: 74 69 70 6c 65 78 57 72 69 74 65 3b 0a 20 20 67  tiplexWrite;.  g
8600: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
8610: 68 6f 64 73 56 31 2e 78 54 72 75 6e 63 61 74 65  hodsV1.xTruncate
8620: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 54 72 75 6e   = multiplexTrun
8630: 63 61 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  cate;.  gMultipl
8640: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
8650: 78 53 79 6e 63 20 3d 20 6d 75 6c 74 69 70 6c 65  xSync = multiple
8660: 78 53 79 6e 63 3b 0a 20 20 67 4d 75 6c 74 69 70  xSync;.  gMultip
8670: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
8680: 2e 78 46 69 6c 65 53 69 7a 65 20 3d 20 6d 75 6c  .xFileSize = mul
8690: 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 3b 0a  tiplexFileSize;.
86a0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
86b0: 4d 65 74 68 6f 64 73 56 31 2e 78 4c 6f 63 6b 20  MethodsV1.xLock 
86c0: 3d 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b 3b  = multiplexLock;
86d0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
86e0: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 55 6e 6c 6f  oMethodsV1.xUnlo
86f0: 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 55 6e  ck = multiplexUn
8700: 6c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  lock;.  gMultipl
8710: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
8720: 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f  xCheckReservedLo
8730: 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 68  ck = multiplexCh
8740: 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 3b  eckReservedLock;
8750: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
8760: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46 69 6c 65  oMethodsV1.xFile
8770: 43 6f 6e 74 72 6f 6c 20 3d 20 6d 75 6c 74 69 70  Control = multip
8780: 6c 65 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 3b 0a  lexFileControl;.
8790: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
87a0: 4d 65 74 68 6f 64 73 56 31 2e 78 53 65 63 74 6f  MethodsV1.xSecto
87b0: 72 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c 65  rSize = multiple
87c0: 78 53 65 63 74 6f 72 53 69 7a 65 3b 0a 20 20 67  xSectorSize;.  g
87d0: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
87e0: 68 6f 64 73 56 31 2e 78 44 65 76 69 63 65 43 68  hodsV1.xDeviceCh
87f0: 61 72 61 63 74 65 72 69 73 74 69 63 73 20 3d 0a  aracteristics =.
8800: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8820: 20 20 20 20 20 20 20 20 20 20 20 20 6d 75 6c 74              mult
8830: 69 70 6c 65 78 44 65 76 69 63 65 43 68 61 72 61  iplexDeviceChara
8840: 63 74 65 72 69 73 74 69 63 73 3b 0a 20 20 67 4d  cteristics;.  gM
8850: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8860: 6f 64 73 56 32 20 3d 20 67 4d 75 6c 74 69 70 6c  odsV2 = gMultipl
8870: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 3b  ex.sIoMethodsV1;
8880: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
8890: 6f 4d 65 74 68 6f 64 73 56 32 2e 69 56 65 72 73  oMethodsV2.iVers
88a0: 69 6f 6e 20 3d 20 32 3b 0a 20 20 67 4d 75 6c 74  ion = 2;.  gMult
88b0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
88c0: 56 32 2e 78 53 68 6d 4d 61 70 20 3d 20 6d 75 6c  V2.xShmMap = mul
88d0: 74 69 70 6c 65 78 53 68 6d 4d 61 70 3b 0a 20 20  tiplexShmMap;.  
88e0: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
88f0: 74 68 6f 64 73 56 32 2e 78 53 68 6d 4c 6f 63 6b  thodsV2.xShmLock
8900: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4c   = multiplexShmL
8910: 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ock;.  gMultiple
8920: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78  x.sIoMethodsV2.x
8930: 53 68 6d 42 61 72 72 69 65 72 20 3d 20 6d 75 6c  ShmBarrier = mul
8940: 74 69 70 6c 65 78 53 68 6d 42 61 72 72 69 65 72  tiplexShmBarrier
8950: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
8960: 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d  IoMethodsV2.xShm
8970: 55 6e 6d 61 70 20 3d 20 6d 75 6c 74 69 70 6c 65  Unmap = multiple
8980: 78 53 68 6d 55 6e 6d 61 70 3b 0a 20 20 73 71 6c  xShmUnmap;.  sql
8990: 69 74 65 33 5f 76 66 73 5f 72 65 67 69 73 74 65  ite3_vfs_registe
89a0: 72 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  r(&gMultiplex.sT
89b0: 68 69 73 56 66 73 2c 20 6d 61 6b 65 44 65 66 61  hisVfs, makeDefa
89c0: 75 6c 74 29 3b 0a 0a 20 20 73 71 6c 69 74 65 33  ult);..  sqlite3
89d0: 5f 61 75 74 6f 5f 65 78 74 65 6e 73 69 6f 6e 28  _auto_extension(
89e0: 28 76 6f 69 64 2a 29 6d 75 6c 74 69 70 6c 65 78  (void*)multiplex
89f0: 46 75 6e 63 49 6e 69 74 29 3b 0a 0a 20 20 72 65  FuncInit);..  re
8a00: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  turn SQLITE_OK;.
8a10: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20 53  }../*.** CAPI: S
8a20: 68 75 74 64 6f 77 6e 20 74 68 65 20 6d 75 6c 74  hutdown the mult
8a30: 69 70 6c 65 78 20 73 79 73 74 65 6d 20 2d 20 73  iplex system - s
8a40: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
8a50: 5f 73 68 75 74 64 6f 77 6e 28 29 0a 2a 2a 0a 2a  _shutdown().**.*
8a60: 2a 20 41 6c 6c 20 53 51 4c 69 74 65 20 64 61 74  * All SQLite dat
8a70: 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e  abase connection
8a80: 73 20 6d 75 73 74 20 62 65 20 63 6c 6f 73 65 64  s must be closed
8a90: 20 62 65 66 6f 72 65 20 63 61 6c 6c 69 6e 67 20   before calling 
8aa0: 74 68 69 73 0a 2a 2a 20 72 6f 75 74 69 6e 65 2e  this.** routine.
8ab0: 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54  .**.** THIS ROUT
8ac0: 49 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41  INE IS NOT THREA
8ad0: 44 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69  DSAFE.  Call thi
8ae0: 73 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c  s routine exactl
8af0: 79 20 6f 6e 63 65 20 77 68 69 6c 65 0a 2a 2a 20  y once while.** 
8b00: 73 68 75 74 74 69 6e 67 20 64 6f 77 6e 20 69 6e  shutting down in
8b10: 20 6f 72 64 65 72 20 74 6f 20 66 72 65 65 20 61   order to free a
8b20: 6c 6c 20 72 65 6d 61 69 6e 69 6e 67 20 6d 75 6c  ll remaining mul
8b30: 74 69 70 6c 65 78 20 67 72 6f 75 70 73 2e 0a 2a  tiplex groups..*
8b40: 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75  /.int sqlite3_mu
8b50: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
8b60: 28 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 67 4d  (void){.  if( gM
8b70: 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69  ultiplex.isIniti
8b80: 61 6c 69 7a 65 64 3d 3d 30 20 29 20 72 65 74 75  alized==0 ) retu
8b90: 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45  rn SQLITE_MISUSE
8ba0: 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c  ;.  if( gMultipl
8bb0: 65 78 2e 70 47 72 6f 75 70 73 20 29 20 72 65 74  ex.pGroups ) ret
8bc0: 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  urn SQLITE_MISUS
8bd0: 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  E;.  gMultiplex.
8be0: 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20  isInitialized = 
8bf0: 30 3b 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74  0;.  sqlite3_mut
8c00: 65 78 5f 66 72 65 65 28 67 4d 75 6c 74 69 70 6c  ex_free(gMultipl
8c10: 65 78 2e 70 4d 75 74 65 78 29 3b 0a 20 20 73 71  ex.pMutex);.  sq
8c20: 6c 69 74 65 33 5f 76 66 73 5f 75 6e 72 65 67 69  lite3_vfs_unregi
8c30: 73 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78  ster(&gMultiplex
8c40: 2e 73 54 68 69 73 56 66 73 29 3b 0a 20 20 6d 65  .sThisVfs);.  me
8c50: 6d 73 65 74 28 26 67 4d 75 6c 74 69 70 6c 65 78  mset(&gMultiplex
8c60: 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 4d 75 6c  , 0, sizeof(gMul
8c70: 74 69 70 6c 65 78 29 29 3b 0a 20 20 72 65 74 75  tiplex));.  retu
8c80: 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a  rn SQLITE_OK;.}.
8c90: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
8ca0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
8cb0: 54 65 73 74 20 43 6f 64 65 20 2a 2a 2a 2a 2a 2a  Test Code ******
8cc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8cd0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 23  *************/.#
8ce0: 69 66 64 65 66 20 53 51 4c 49 54 45 5f 54 45 53  ifdef SQLITE_TES
8cf0: 54 0a 23 69 6e 63 6c 75 64 65 20 3c 74 63 6c 2e  T.#include <tcl.
8d00: 68 3e 0a 65 78 74 65 72 6e 20 63 6f 6e 73 74 20  h>.extern const 
8d10: 63 68 61 72 20 2a 73 71 6c 69 74 65 33 54 65 73  char *sqlite3Tes
8d20: 74 45 72 72 6f 72 4e 61 6d 65 28 69 6e 74 29 3b  tErrorName(int);
8d30: 0a 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a  .../*.** tclcmd:
8d40: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
8d50: 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 20 4e 41  ex_initialize NA
8d60: 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 0a 2a  ME MAKEDEFAULT.*
8d70: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65 73  /.static int tes
8d80: 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  t_multiplex_init
8d90: 69 61 6c 69 7a 65 28 0a 20 20 76 6f 69 64 20 2a  ialize(.  void *
8da0: 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54   clientData,.  T
8db0: 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72  cl_Interp *inter
8dc0: 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20  p,.  int objc,. 
8dd0: 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20   Tcl_Obj *CONST 
8de0: 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73  objv[].){.  cons
8df0: 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20  t char *zName;  
8e00: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
8e10: 61 6d 65 20 6f 66 20 6e 65 77 20 6d 75 6c 74 69  ame of new multi
8e20: 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 69 6e  plex VFS */.  in
8e30: 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 3b 20 20  t makeDefault;  
8e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
8e50: 20 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 74 68   True to make th
8e60: 65 20 6e 65 77 20 56 46 53 20 74 68 65 20 64 65  e new VFS the de
8e70: 66 61 75 6c 74 20 2a 2f 0a 20 20 69 6e 74 20 72  fault */.  int r
8e80: 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c;              
8e90: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56 61             /* Va
8ea0: 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62 79 20  lue returned by 
8eb0: 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61  multiplex_initia
8ec0: 6c 69 7a 65 28 29 20 2a 2f 0a 0a 20 20 55 4e 55  lize() */..  UNU
8ed0: 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c  SED_PARAMETER(cl
8ee0: 69 65 6e 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a  ientData);..  /*
8ef0: 20 50 72 6f 63 65 73 73 20 61 72 67 75 6d 65 6e   Process argumen
8f00: 74 73 20 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63  ts */.  if( objc
8f10: 21 3d 33 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57  !=3 ){.    Tcl_W
8f20: 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65  rongNumArgs(inte
8f30: 72 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 4e 41  rp, 1, objv, "NA
8f40: 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 22 29  ME MAKEDEFAULT")
8f50: 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c  ;.    return TCL
8f60: 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e  _ERROR;.  }.  zN
8f70: 61 6d 65 20 3d 20 54 63 6c 5f 47 65 74 53 74 72  ame = Tcl_GetStr
8f80: 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20  ing(objv[1]);.  
8f90: 69 66 28 20 54 63 6c 5f 47 65 74 42 6f 6f 6c 65  if( Tcl_GetBoole
8fa0: 61 6e 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70  anFromObj(interp
8fb0: 2c 20 6f 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65  , objv[2], &make
8fc0: 44 65 66 61 75 6c 74 29 20 29 20 72 65 74 75 72  Default) ) retur
8fd0: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 69  n TCL_ERROR;.  i
8fe0: 66 28 20 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30  f( zName[0]=='\0
8ff0: 27 20 29 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a  ' ) zName = 0;..
9000: 20 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69 74 65    /* Call sqlite
9010: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  3_multiplex_init
9020: 69 61 6c 69 7a 65 28 29 20 2a 2f 0a 20 20 72 63  ialize() */.  rc
9030: 20 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69   = sqlite3_multi
9040: 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28  plex_initialize(
9050: 7a 4e 61 6d 65 2c 20 6d 61 6b 65 44 65 66 61 75  zName, makeDefau
9060: 6c 74 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65  lt);.  Tcl_SetRe
9070: 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68  sult(interp, (ch
9080: 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73 74  ar *)sqlite3Test
9090: 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54  ErrorName(rc), T
90a0: 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20 20 72  CL_STATIC);..  r
90b0: 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a  eturn TCL_OK;.}.
90c0: 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73  ./*.** tclcmd: s
90d0: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
90e0: 5f 73 68 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74 61  _shutdown.*/.sta
90f0: 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c  tic int test_mul
9100: 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28  tiplex_shutdown(
9110: 0a 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74  .  void * client
9120: 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65  Data,.  Tcl_Inte
9130: 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e  rp *interp,.  in
9140: 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62  t objc,.  Tcl_Ob
9150: 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a  j *CONST objv[].
9160: 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20  ){.  int rc;    
9170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9180: 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20 72 65       /* Value re
9190: 74 75 72 6e 65 64 20 62 79 20 6d 75 6c 74 69 70  turned by multip
91a0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a  lex_shutdown() *
91b0: 2f 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  /..  UNUSED_PARA
91c0: 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61  METER(clientData
91d0: 29 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d  );..  if( objc!=
91e0: 31 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f  1 ){.    Tcl_Wro
91f0: 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70  ngNumArgs(interp
9200: 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 22 29 3b 0a  , 1, objv, "");.
9210: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
9220: 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20  RROR;.  }..  /* 
9230: 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d 75 6c  Call sqlite3_mul
9240: 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28  tiplex_shutdown(
9250: 29 20 2a 2f 0a 20 20 72 63 20 3d 20 73 71 6c 69  ) */.  rc = sqli
9260: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
9270: 75 74 64 6f 77 6e 28 29 3b 0a 20 20 54 63 6c 5f  utdown();.  Tcl_
9280: 53 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72 70  SetResult(interp
9290: 2c 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74 65  , (char *)sqlite
92a0: 33 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28 72  3TestErrorName(r
92b0: 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29 3b  c), TCL_STATIC);
92c0: 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f  ..  return TCL_O
92d0: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63  K;.}../*.** tclc
92e0: 6d 64 3a 20 20 73 71 6c 69 74 65 33 5f 6d 75 6c  md:  sqlite3_mul
92f0: 74 69 70 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a 73  tiplex_dump.*/.s
9300: 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d  tatic int test_m
9310: 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 28 0a 20  ultiplex_dump(. 
9320: 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61   void * clientDa
9330: 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70  ta,.  Tcl_Interp
9340: 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20   *interp,.  int 
9350: 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20  objc,.  Tcl_Obj 
9360: 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b  *CONST objv[].){
9370: 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 52 65 73  .  Tcl_Obj *pRes
9380: 75 6c 74 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a  ult;.  Tcl_Obj *
9390: 70 47 72 6f 75 70 54 65 72 6d 3b 0a 20 20 6d 75  pGroupTerm;.  mu
93a0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
93b0: 72 6f 75 70 3b 0a 20 20 69 6e 74 20 69 3b 0a 20  roup;.  int i;. 
93c0: 20 69 6e 74 20 6e 43 68 75 6e 6b 73 20 3d 20 30   int nChunks = 0
93d0: 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  ;..  UNUSED_PARA
93e0: 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61  METER(clientData
93f0: 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  );.  UNUSED_PARA
9400: 4d 45 54 45 52 28 6f 62 6a 63 29 3b 0a 20 20 55  METER(objc);.  U
9410: 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28  NUSED_PARAMETER(
9420: 6f 62 6a 76 29 3b 0a 0a 20 20 70 52 65 73 75 6c  objv);..  pResul
9430: 74 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28 29  t = Tcl_NewObj()
9440: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74  ;.  multiplexEnt
9450: 65 72 28 29 3b 0a 20 20 66 6f 72 28 70 47 72 6f  er();.  for(pGro
9460: 75 70 3d 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47  up=gMultiplex.pG
9470: 72 6f 75 70 73 3b 20 70 47 72 6f 75 70 3b 20 70  roups; pGroup; p
9480: 47 72 6f 75 70 3d 70 47 72 6f 75 70 2d 3e 70 4e  Group=pGroup->pN
9490: 65 78 74 29 7b 0a 20 20 20 20 70 47 72 6f 75 70  ext){.    pGroup
94a0: 54 65 72 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f 62  Term = Tcl_NewOb
94b0: 6a 28 29 3b 0a 0a 20 20 20 20 70 47 72 6f 75 70  j();..    pGroup
94c0: 2d 3e 7a 4e 61 6d 65 5b 70 47 72 6f 75 70 2d 3e  ->zName[pGroup->
94d0: 6e 4e 61 6d 65 5d 20 3d 20 27 5c 30 27 3b 0a 20  nName] = '\0';. 
94e0: 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70     Tcl_ListObjAp
94f0: 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65  pendElement(inte
9500: 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a  rp, pGroupTerm,.
9510: 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65            Tcl_Ne
9520: 77 53 74 72 69 6e 67 4f 62 6a 28 70 47 72 6f 75  wStringObj(pGrou
9530: 70 2d 3e 7a 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a  p->zName, -1));.
9540: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
9550: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
9560: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
9570: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
9580: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
9590: 3e 6e 4e 61 6d 65 29 29 3b 0a 20 20 20 20 54 63  >nName));.    Tc
95a0: 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45  l_ListObjAppendE
95b0: 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70  lement(interp, p
95c0: 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20 20  GroupTerm,.     
95d0: 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74 4f       Tcl_NewIntO
95e0: 62 6a 28 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73  bj(pGroup->flags
95f0: 29 29 3b 0a 0a 20 20 20 20 2f 2a 20 63 6f 75 6e  ));..    /* coun
9600: 74 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75 6e  t number of chun
9610: 6b 73 20 77 69 74 68 20 6f 70 65 6e 20 68 61 6e  ks with open han
9620: 64 6c 65 73 20 2a 2f 0a 20 20 20 20 66 6f 72 28  dles */.    for(
9630: 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e  i=0; i<pGroup->n
9640: 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  Real; i++){.    
9650: 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 61 52    if( pGroup->aR
9660: 65 61 6c 5b 69 5d 2e 70 21 3d 30 20 29 20 6e 43  eal[i].p!=0 ) nC
9670: 68 75 6e 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a 20  hunks++;.    }. 
9680: 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70     Tcl_ListObjAp
9690: 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65  pendElement(inte
96a0: 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a  rp, pGroupTerm,.
96b0: 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65            Tcl_Ne
96c0: 77 49 6e 74 4f 62 6a 28 6e 43 68 75 6e 6b 73 29  wIntObj(nChunks)
96d0: 29 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74  );..    Tcl_List
96e0: 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74  ObjAppendElement
96f0: 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70 54  (interp, pGroupT
9700: 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20 54  erm,.          T
9710: 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72  cl_NewIntObj(pGr
9720: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 29 3b 0a  oup->szChunk));.
9730: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
9740: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
9750: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
9760: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
9770: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
9780: 3e 6e 52 65 61 6c 29 29 3b 0a 0a 20 20 20 20 54  >nReal));..    T
9790: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
97a0: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
97b0: 70 52 65 73 75 6c 74 2c 20 70 47 72 6f 75 70 54  pResult, pGroupT
97c0: 65 72 6d 29 3b 0a 20 20 7d 0a 20 20 6d 75 6c 74  erm);.  }.  mult
97d0: 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20  iplexLeave();.  
97e0: 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74  Tcl_SetObjResult
97f0: 28 69 6e 74 65 72 70 2c 20 70 52 65 73 75 6c 74  (interp, pResult
9800: 29 3b 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  );.  return TCL_
9810: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63 6c  OK;.}../*.** Tcl
9820: 63 6d 64 3a 20 74 65 73 74 5f 6d 75 6c 74 69 70  cmd: test_multip
9830: 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20 48 41 4e 44  lex_control HAND
9840: 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43 4f  LE DBNAME SUB-CO
9850: 4d 4d 41 4e 44 20 3f 49 4e 54 2d 56 41 4c 55 45  MMAND ?INT-VALUE
9860: 3f 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ?.*/.static int 
9870: 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 63  test_multiplex_c
9880: 6f 6e 74 72 6f 6c 28 0a 20 20 43 6c 69 65 6e 74  ontrol(.  Client
9890: 44 61 74 61 20 63 64 2c 0a 20 20 54 63 6c 5f 49  Data cd,.  Tcl_I
98a0: 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20  nterp *interp,. 
98b0: 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c   int objc,.  Tcl
98c0: 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76  _Obj *CONST objv
98d0: 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20  [].){.  int rc; 
98e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
98f0: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72          /* Retur
9900: 6e 20 63 6f 64 65 20 66 72 6f 6d 20 66 69 6c 65  n code from file
9910: 5f 63 6f 6e 74 72 6f 6c 28 29 20 2a 2f 0a 20 20  _control() */.  
9920: 69 6e 74 20 69 64 78 3b 20 20 20 20 20 20 20 20  int idx;        
9930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9940: 2f 2a 20 49 6e 64 65 78 20 69 6e 20 61 53 75 62  /* Index in aSub
9950: 5b 5d 20 2a 2f 0a 20 20 54 63 6c 5f 43 6d 64 49  [] */.  Tcl_CmdI
9960: 6e 66 6f 20 63 6d 64 49 6e 66 6f 3b 20 20 20 20  nfo cmdInfo;    
9970: 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6d 6d 61          /* Comma
9980: 6e 64 20 69 6e 66 6f 20 73 74 72 75 63 74 75 72  nd info structur
9990: 65 20 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f 0a  e for HANDLE */.
99a0: 20 20 73 71 6c 69 74 65 33 20 2a 64 62 3b 20 20    sqlite3 *db;  
99b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
99c0: 20 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67 20    /* Underlying 
99d0: 64 62 20 68 61 6e 64 6c 65 20 66 6f 72 20 48 41  db handle for HA
99e0: 4e 44 4c 45 20 2a 2f 0a 20 20 69 6e 74 20 69 56  NDLE */.  int iV
99f0: 61 6c 75 65 20 3d 20 30 3b 0a 20 20 76 6f 69 64  alue = 0;.  void
9a00: 20 2a 70 41 72 67 20 3d 20 30 3b 0a 0a 20 20 73   *pArg = 0;..  s
9a10: 74 72 75 63 74 20 53 75 62 43 6f 6d 6d 61 6e 64  truct SubCommand
9a20: 20 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61   {.    const cha
9a30: 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 69 6e  r *zName;.    in
9a40: 74 20 6f 70 3b 0a 20 20 20 20 69 6e 74 20 61 72  t op;.    int ar
9a50: 67 74 79 70 65 3b 0a 20 20 7d 20 61 53 75 62 5b  gtype;.  } aSub[
9a60: 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 65 6e 61  ] = {.    { "ena
9a70: 62 6c 65 22 2c 20 20 20 20 20 20 20 4d 55 4c 54  ble",       MULT
9a80: 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42 4c  IPLEX_CTRL_ENABL
9a90: 45 2c 20 20 20 20 20 20 20 20 20 20 20 31 20 7d  E,           1 }
9aa0: 2c 0a 20 20 20 20 7b 20 22 63 68 75 6e 6b 5f 73  ,.    { "chunk_s
9ab0: 69 7a 65 22 2c 20 20 20 4d 55 4c 54 49 50 4c 45  ize",   MULTIPLE
9ac0: 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b  X_CTRL_SET_CHUNK
9ad0: 5f 53 49 5a 45 2c 20 20 20 31 20 7d 2c 0a 20 20  _SIZE,   1 },.  
9ae0: 20 20 7b 20 22 6d 61 78 5f 63 68 75 6e 6b 73 22    { "max_chunks"
9af0: 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  ,   MULTIPLEX_CT
9b00: 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b  RL_SET_MAX_CHUNK
9b10: 53 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b 20  S,   1 },.    { 
9b20: 30 2c 20 30 2c 20 30 20 7d 0a 20 20 7d 3b 0a 0a  0, 0, 0 }.  };..
9b30: 20 20 69 66 28 20 6f 62 6a 63 21 3d 35 20 29 7b    if( objc!=5 ){
9b40: 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75  .    Tcl_WrongNu
9b50: 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c  mArgs(interp, 1,
9b60: 20 6f 62 6a 76 2c 20 22 48 41 4e 44 4c 45 20 44   objv, "HANDLE D
9b70: 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41 4e  BNAME SUB-COMMAN
9b80: 44 20 49 4e 54 2d 56 41 4c 55 45 22 29 3b 0a 20  D INT-VALUE");. 
9b90: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
9ba0: 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20  ROR;.  }..  if( 
9bb0: 30 3d 3d 54 63 6c 5f 47 65 74 43 6f 6d 6d 61 6e  0==Tcl_GetComman
9bc0: 64 49 6e 66 6f 28 69 6e 74 65 72 70 2c 20 54 63  dInfo(interp, Tc
9bd0: 6c 5f 47 65 74 53 74 72 69 6e 67 28 6f 62 6a 76  l_GetString(objv
9be0: 5b 31 5d 29 2c 20 26 63 6d 64 49 6e 66 6f 29 20  [1]), &cmdInfo) 
9bf0: 29 7b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65 6e  ){.    Tcl_Appen
9c00: 64 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20  dResult(interp, 
9c10: 22 65 78 70 65 63 74 65 64 20 64 61 74 61 62 61  "expected databa
9c20: 73 65 20 68 61 6e 64 6c 65 2c 20 67 6f 74 20 5c  se handle, got \
9c30: 22 22 2c 20 30 29 3b 0a 20 20 20 20 54 63 6c 5f  "", 0);.    Tcl_
9c40: 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e 74  AppendResult(int
9c50: 65 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72 69  erp, Tcl_GetStri
9c60: 6e 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 22 5c 22  ng(objv[1]), "\"
9c70: 22 2c 20 30 29 3b 0a 20 20 20 20 72 65 74 75 72  ", 0);.    retur
9c80: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d  n TCL_ERROR;.  }
9c90: 65 6c 73 65 7b 0a 20 20 20 20 64 62 20 3d 20 2a  else{.    db = *
9ca0: 28 73 71 6c 69 74 65 33 20 2a 2a 29 63 6d 64 49  (sqlite3 **)cmdI
9cb0: 6e 66 6f 2e 6f 62 6a 43 6c 69 65 6e 74 44 61 74  nfo.objClientDat
9cc0: 61 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 54  a;.  }..  rc = T
9cd0: 63 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d 4f  cl_GetIndexFromO
9ce0: 62 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20 20  bjStruct(.      
9cf0: 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 33 5d 2c  interp, objv[3],
9d00: 20 61 53 75 62 2c 20 73 69 7a 65 6f 66 28 61 53   aSub, sizeof(aS
9d10: 75 62 5b 30 5d 29 2c 20 22 73 75 62 2d 63 6f 6d  ub[0]), "sub-com
9d20: 6d 61 6e 64 22 2c 20 30 2c 20 26 69 64 78 0a 20  mand", 0, &idx. 
9d30: 20 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54 43   );.  if( rc!=TC
9d40: 4c 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72 63  L_OK ) return rc
9d50: 3b 0a 0a 20 20 73 77 69 74 63 68 28 20 61 53 75  ;..  switch( aSu
9d60: 62 5b 69 64 78 5d 2e 61 72 67 74 79 70 65 20 29  b[idx].argtype )
9d70: 7b 0a 20 20 20 20 63 61 73 65 20 31 3a 0a 20 20  {.    case 1:.  
9d80: 20 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74 49      if( Tcl_GetI
9d90: 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70  ntFromObj(interp
9da0: 2c 20 6f 62 6a 76 5b 34 5d 2c 20 26 69 56 61 6c  , objv[4], &iVal
9db0: 75 65 29 20 29 7b 0a 20 20 20 20 20 20 20 20 72  ue) ){.        r
9dc0: 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b  eturn TCL_ERROR;
9dd0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 70  .      }.      p
9de0: 41 72 67 20 3d 20 28 76 6f 69 64 20 2a 29 26 69  Arg = (void *)&i
9df0: 56 61 6c 75 65 3b 0a 20 20 20 20 20 20 62 72 65  Value;.      bre
9e00: 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74 3a  ak;.    default:
9e10: 0a 20 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67  .      Tcl_Wrong
9e20: 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20  NumArgs(interp, 
9e30: 34 2c 20 6f 62 6a 76 2c 20 22 53 55 42 2d 43 4f  4, objv, "SUB-CO
9e40: 4d 4d 41 4e 44 22 29 3b 0a 20 20 20 20 20 20 72  MMAND");.      r
9e50: 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b  eturn TCL_ERROR;
9e60: 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 73 71 6c  .  }..  rc = sql
9e70: 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e 74 72 6f  ite3_file_contro
9e80: 6c 28 64 62 2c 20 54 63 6c 5f 47 65 74 53 74 72  l(db, Tcl_GetStr
9e90: 69 6e 67 28 6f 62 6a 76 5b 32 5d 29 2c 20 61 53  ing(objv[2]), aS
9ea0: 75 62 5b 69 64 78 5d 2e 6f 70 2c 20 70 41 72 67  ub[idx].op, pArg
9eb0: 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75  );.  Tcl_SetResu
9ec0: 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72  lt(interp, (char
9ed0: 20 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45 72   *)sqlite3TestEr
9ee0: 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c  rorName(rc), TCL
9ef0: 5f 53 54 41 54 49 43 29 3b 0a 20 20 72 65 74 75  _STATIC);.  retu
9f00: 72 6e 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  rn (rc==SQLITE_O
9f10: 4b 29 20 3f 20 54 43 4c 5f 4f 4b 20 3a 20 54 43  K) ? TCL_OK : TC
9f20: 4c 5f 45 52 52 4f 52 3b 0a 7d 0a 0a 2f 2a 0a 2a  L_ERROR;.}../*.*
9f30: 2a 20 54 68 69 73 20 72 6f 75 74 69 6e 65 20 72  * This routine r
9f40: 65 67 69 73 74 65 72 73 20 74 68 65 20 63 75 73  egisters the cus
9f50: 74 6f 6d 20 54 43 4c 20 63 6f 6d 6d 61 6e 64 73  tom TCL commands
9f60: 20 64 65 66 69 6e 65 64 20 69 6e 20 74 68 69 73   defined in this
9f70: 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 20 20 54 68 69  .** module.  Thi
9f80: 73 20 73 68 6f 75 6c 64 20 62 65 20 74 68 65 20  s should be the 
9f90: 6f 6e 6c 79 20 70 72 6f 63 65 64 75 72 65 20 76  only procedure v
9fa0: 69 73 69 62 6c 65 20 66 72 6f 6d 20 6f 75 74 73  isible from outs
9fb0: 69 64 65 0a 2a 2a 20 6f 66 20 74 68 69 73 20 6d  ide.** of this m
9fc0: 6f 64 75 6c 65 2e 0a 2a 2f 0a 69 6e 74 20 53 71  odule..*/.int Sq
9fd0: 6c 69 74 65 6d 75 6c 74 69 70 6c 65 78 5f 49 6e  litemultiplex_In
9fe0: 69 74 28 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69  it(Tcl_Interp *i
9ff0: 6e 74 65 72 70 29 7b 0a 20 20 73 74 61 74 69 63  nterp){.  static
a000: 20 73 74 72 75 63 74 20 7b 0a 20 20 20 20 20 63   struct {.     c
a010: 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20  har *zName;.    
a020: 20 54 63 6c 5f 4f 62 6a 43 6d 64 50 72 6f 63 20   Tcl_ObjCmdProc 
a030: 2a 78 50 72 6f 63 3b 0a 20 20 7d 20 61 43 6d 64  *xProc;.  } aCmd
a040: 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 73 71  [] = {.    { "sq
a050: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
a060: 69 6e 69 74 69 61 6c 69 7a 65 22 2c 20 74 65 73  initialize", tes
a070: 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  t_multiplex_init
a080: 69 61 6c 69 7a 65 20 7d 2c 0a 20 20 20 20 7b 20  ialize },.    { 
a090: 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c  "sqlite3_multipl
a0a0: 65 78 5f 73 68 75 74 64 6f 77 6e 22 2c 20 74 65  ex_shutdown", te
a0b0: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  st_multiplex_shu
a0c0: 74 64 6f 77 6e 20 7d 2c 0a 20 20 20 20 7b 20 22  tdown },.    { "
a0d0: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
a0e0: 78 5f 64 75 6d 70 22 2c 20 74 65 73 74 5f 6d 75  x_dump", test_mu
a0f0: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 20 7d 2c 0a  ltiplex_dump },.
a100: 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d      { "sqlite3_m
a110: 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c  ultiplex_control
a120: 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65  ", test_multiple
a130: 78 5f 63 6f 6e 74 72 6f 6c 20 7d 2c 0a 20 20 7d  x_control },.  }
a140: 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 66 6f  ;.  int i;..  fo
a150: 72 28 69 3d 30 3b 20 69 3c 73 69 7a 65 6f 66 28  r(i=0; i<sizeof(
a160: 61 43 6d 64 29 2f 73 69 7a 65 6f 66 28 61 43 6d  aCmd)/sizeof(aCm
a170: 64 5b 30 5d 29 3b 20 69 2b 2b 29 7b 0a 20 20 20  d[0]); i++){.   
a180: 20 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f   Tcl_CreateObjCo
a190: 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c 20 61 43  mmand(interp, aC
a1a0: 6d 64 5b 69 5d 2e 7a 4e 61 6d 65 2c 20 61 43 6d  md[i].zName, aCm
a1b0: 64 5b 69 5d 2e 78 50 72 6f 63 2c 20 30 2c 20 30  d[i].xProc, 0, 0
a1c0: 29 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e  );.  }..  return
a1d0: 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64 69   TCL_OK;.}.#endi
a1e0: 66 0a                                            f.