/ Hex Artifact Content
Login

Artifact d1b43de1209bd1bc207b694a738fdb84a162f65b:


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 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 2a 70  sqlite3_file **p
11f0: 52 65 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20  Real;           
1200: 20 2f 2a 20 48 61 6e 64 6c 65 73 20 74 6f 20 65   /* Handles to e
1210: 61 63 68 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 63  ach chunk */.  c
1220: 68 61 72 20 2a 62 4f 70 65 6e 3b 20 20 20 20 20  har *bOpen;     
1230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1240: 2f 2a 20 61 72 72 61 79 20 6f 66 20 62 6f 6f 6c  /* array of bool
1250: 73 20 2d 20 30 20 69 66 20 63 68 75 6e 6b 20 6e  s - 0 if chunk n
1260: 6f 74 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 63  ot opened */.  c
1270: 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20  har *zName;     
1280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1290: 2f 2a 20 42 61 73 65 20 66 69 6c 65 6e 61 6d 65  /* Base filename
12a0: 20 6f 66 20 74 68 69 73 20 67 72 6f 75 70 20 2a   of this group *
12b0: 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 20 20  /.  int nName;  
12c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12d0: 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f       /* Length o
12e0: 66 20 62 61 73 65 20 66 69 6c 65 6e 61 6d 65 20  f base filename 
12f0: 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 3b 20  */.  int flags; 
1300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1310: 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20 75        /* Flags u
1320: 73 65 64 20 66 6f 72 20 6f 72 69 67 69 6e 61 6c  sed for original
1330: 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e   opening */.  in
1340: 74 20 6e 43 68 75 6e 6b 53 69 7a 65 3b 20 20 20  t nChunkSize;   
1350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
1360: 2a 20 43 68 75 6e 6b 20 73 69 7a 65 20 75 73 65  * Chunk size use
1370: 64 20 66 6f 72 20 74 68 69 73 20 67 72 6f 75 70  d for this group
1380: 20 2a 2f 0a 20 20 69 6e 74 20 6e 4d 61 78 43 68   */.  int nMaxCh
1390: 75 6e 6b 73 3b 20 20 20 20 20 20 20 20 20 20 20  unks;           
13a0: 20 20 20 20 20 20 20 2f 2a 20 4d 61 78 20 6e 75         /* Max nu
13b0: 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73 20 66  mber of chunks f
13c0: 6f 72 20 74 68 69 73 20 67 72 6f 75 70 20 2a 2f  or this group */
13d0: 0a 20 20 69 6e 74 20 62 45 6e 61 62 6c 65 64 3b  .  int bEnabled;
13e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13f0: 20 20 20 20 2f 2a 20 54 52 55 45 20 74 6f 20 75      /* TRUE to u
1400: 73 65 20 4d 75 6c 74 69 70 6c 65 78 20 56 46 53  se Multiplex VFS
1410: 20 66 6f 72 20 74 68 69 73 20 66 69 6c 65 20 2a   for this file *
1420: 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  /.  multiplexGro
1430: 75 70 20 2a 70 4e 65 78 74 2c 20 2a 70 50 72 65  up *pNext, *pPre
1440: 76 3b 20 20 20 2f 2a 20 44 6f 75 62 6c 79 20 6c  v;   /* Doubly l
1450: 69 6e 6b 65 64 20 6c 69 73 74 20 6f 66 20 61 6c  inked list of al
1460: 6c 20 67 72 6f 75 70 20 6f 62 6a 65 63 74 73 20  l group objects 
1470: 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6e 20  */.};../*.** An 
1480: 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65 20  instance of the 
1490: 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74  following object
14a0: 20 72 65 70 72 65 73 65 6e 74 73 20 65 61 63 68   represents each
14b0: 20 6f 70 65 6e 20 63 6f 6e 6e 65 63 74 69 6f 6e   open connection
14c0: 0a 2a 2a 20 74 6f 20 61 20 66 69 6c 65 20 74 68  .** to a file th
14d0: 61 74 20 69 73 20 6d 75 6c 74 69 70 6c 65 78 27  at is multiplex'
14e0: 65 64 2e 20 20 54 68 69 73 20 6f 62 6a 65 63 74  ed.  This object
14f0: 20 69 73 20 61 20 0a 2a 2a 20 73 75 62 63 6c 61   is a .** subcla
1500: 73 73 20 6f 66 20 73 71 6c 69 74 65 33 5f 66 69  ss of sqlite3_fi
1510: 6c 65 2e 20 20 54 68 65 20 73 71 6c 69 74 65 33  le.  The sqlite3
1520: 5f 66 69 6c 65 20 6f 62 6a 65 63 74 20 66 6f 72  _file object for
1530: 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 0a   the underlying.
1540: 2a 2a 20 56 46 53 20 69 73 20 61 70 70 65 6e 64  ** VFS is append
1550: 65 64 20 74 6f 20 74 68 69 73 20 73 74 72 75 63  ed to this struc
1560: 74 75 72 65 2e 0a 2a 2f 0a 73 74 72 75 63 74 20  ture..*/.struct 
1570: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 7b 0a  multiplexConn {.
1580: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 62    sqlite3_file b
1590: 61 73 65 3b 20 20 20 20 20 20 20 20 20 20 20 20  ase;            
15a0: 20 20 2f 2a 20 42 61 73 65 20 63 6c 61 73 73 20    /* Base class 
15b0: 2d 20 6d 75 73 74 20 62 65 20 66 69 72 73 74 20  - must be first 
15c0: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  */.  multiplexGr
15d0: 6f 75 70 20 2a 70 47 72 6f 75 70 3b 20 20 20 20  oup *pGroup;    
15e0: 20 20 20 20 20 2f 2a 20 54 68 65 20 75 6e 64 65       /* The unde
15f0: 72 6c 79 69 6e 67 20 67 72 6f 75 70 20 6f 66 20  rlying group of 
1600: 66 69 6c 65 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 2a  files */.};../**
1610: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1620: 2a 2a 2a 2a 2a 2a 2a 20 47 6c 6f 62 61 6c 20 56  ******* Global V
1630: 61 72 69 61 62 6c 65 73 20 2a 2a 2a 2a 2a 2a 2a  ariables *******
1640: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1650: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a 0a  ***********/./*.
1660: 2a 2a 20 41 6c 6c 20 67 6c 6f 62 61 6c 20 76 61  ** All global va
1670: 72 69 61 62 6c 65 73 20 75 73 65 64 20 62 79 20  riables used by 
1680: 74 68 69 73 20 66 69 6c 65 20 61 72 65 20 63 6f  this file are co
1690: 6e 74 61 69 6e 69 6e 67 20 77 69 74 68 69 6e 20  ntaining within 
16a0: 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 0a 2a 2a  the following.**
16b0: 20 67 4d 75 6c 74 69 70 6c 65 78 20 73 74 72 75   gMultiplex stru
16c0: 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 61 74 69 63  cture..*/.static
16d0: 20 73 74 72 75 63 74 20 7b 0a 20 20 2f 2a 20 54   struct {.  /* T
16e0: 68 65 20 70 4f 72 69 67 56 66 73 20 69 73 20 74  he pOrigVfs is t
16f0: 68 65 20 72 65 61 6c 2c 20 6f 72 69 67 69 6e 61  he real, origina
1700: 6c 20 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53  l underlying VFS
1710: 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 2e   implementation.
1720: 0a 20 20 2a 2a 20 4d 6f 73 74 20 6f 70 65 72 61  .  ** Most opera
1730: 74 69 6f 6e 73 20 70 61 73 73 2d 74 68 72 6f 75  tions pass-throu
1740: 67 68 20 74 6f 20 74 68 65 20 72 65 61 6c 20 56  gh to the real V
1750: 46 53 2e 20 20 54 68 69 73 20 76 61 6c 75 65 20  FS.  This value 
1760: 69 73 20 72 65 61 64 2d 6f 6e 6c 79 0a 20 20 2a  is read-only.  *
1770: 2a 20 64 75 72 69 6e 67 20 6f 70 65 72 61 74 69  * during operati
1780: 6f 6e 2e 20 20 49 74 20 69 73 20 6f 6e 6c 79 20  on.  It is only 
1790: 6d 6f 64 69 66 69 65 64 20 61 74 20 73 74 61 72  modified at star
17a0: 74 2d 74 69 6d 65 20 61 6e 64 20 74 68 75 73 20  t-time and thus 
17b0: 64 6f 65 73 20 6e 6f 74 0a 20 20 2a 2a 20 72 65  does not.  ** re
17c0: 71 75 69 72 65 20 61 20 6d 75 74 65 78 2e 0a 20  quire a mutex.. 
17d0: 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76 66   */.  sqlite3_vf
17e0: 73 20 2a 70 4f 72 69 67 56 66 73 3b 0a 0a 20 20  s *pOrigVfs;..  
17f0: 2f 2a 20 54 68 65 20 73 54 68 69 73 56 66 73 20  /* The sThisVfs 
1800: 69 73 20 74 68 65 20 56 46 53 20 73 74 72 75 63  is the VFS struc
1810: 74 75 72 65 20 75 73 65 64 20 62 79 20 74 68 69  ture used by thi
1820: 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73 20 69  s shim.  It is i
1830: 6e 69 74 69 61 6c 69 7a 65 64 0a 20 20 2a 2a 20  nitialized.  ** 
1840: 61 74 20 73 74 61 72 74 2d 74 69 6d 65 20 61 6e  at start-time an
1850: 64 20 74 68 75 73 20 64 6f 65 73 20 6e 6f 74 20  d thus does not 
1860: 72 65 71 75 69 72 65 20 61 20 6d 75 74 65 78 0a  require a mutex.
1870: 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76    */.  sqlite3_v
1880: 66 73 20 73 54 68 69 73 56 66 73 3b 0a 0a 20 20  fs sThisVfs;..  
1890: 2f 2a 20 54 68 65 20 73 49 6f 4d 65 74 68 6f 64  /* The sIoMethod
18a0: 73 20 64 65 66 69 6e 65 73 20 74 68 65 20 6d 65  s defines the me
18b0: 74 68 6f 64 73 20 75 73 65 64 20 62 79 20 73 71  thods used by sq
18c0: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63  lite3_file objec
18d0: 74 73 20 0a 20 20 2a 2a 20 61 73 73 6f 63 69 61  ts .  ** associa
18e0: 74 65 64 20 77 69 74 68 20 74 68 69 73 20 73 68  ted with this sh
18f0: 69 6d 2e 20 20 49 74 20 69 73 20 69 6e 69 74 69  im.  It is initi
1900: 61 6c 69 7a 65 64 20 61 74 20 73 74 61 72 74 2d  alized at start-
1910: 74 69 6d 65 20 61 6e 64 20 64 6f 65 73 0a 20 20  time and does.  
1920: 2a 2a 20 6e 6f 74 20 72 65 71 75 69 72 65 20 61  ** not require a
1930: 20 6d 75 74 65 78 2e 0a 20 20 2a 2a 0a 20 20 2a   mutex..  **.  *
1940: 2a 20 57 68 65 6e 20 74 68 65 20 75 6e 64 65 72  * When the under
1950: 6c 79 69 6e 67 20 56 46 53 20 69 73 20 63 61 6c  lying VFS is cal
1960: 6c 65 64 20 74 6f 20 6f 70 65 6e 20 61 20 66 69  led to open a fi
1970: 6c 65 2c 20 69 74 20 6d 69 67 68 74 20 72 65 74  le, it might ret
1980: 75 72 6e 20 0a 20 20 2a 2a 20 65 69 74 68 65 72  urn .  ** either
1990: 20 61 20 76 65 72 73 69 6f 6e 20 31 20 6f 72 20   a version 1 or 
19a0: 61 20 76 65 72 73 69 6f 6e 20 32 20 73 71 6c 69  a version 2 sqli
19b0: 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74 2e  te3_file object.
19c0: 20 20 54 68 69 73 20 73 68 69 6d 0a 20 20 2a 2a    This shim.  **
19d0: 20 68 61 73 20 74 6f 20 63 72 65 61 74 65 20 61   has to create a
19e0: 20 77 72 61 70 70 65 72 20 73 71 6c 69 74 65 33   wrapper sqlite3
19f0: 5f 66 69 6c 65 20 6f 66 20 74 68 65 20 73 61 6d  _file of the sam
1a00: 65 20 76 65 72 73 69 6f 6e 2e 20 20 48 65 6e 63  e version.  Henc
1a10: 65 0a 20 20 2a 2a 20 74 68 65 72 65 20 61 72 65  e.  ** there are
1a20: 20 74 77 6f 20 49 2f 4f 20 6d 65 74 68 6f 64 20   two I/O method 
1a30: 73 74 72 75 63 74 75 72 65 73 2c 20 6f 6e 65 20  structures, one 
1a40: 66 6f 72 20 76 65 72 73 69 6f 6e 20 31 20 61 6e  for version 1 an
1a50: 64 20 74 68 65 20 6f 74 68 65 72 0a 20 20 2a 2a  d the other.  **
1a60: 20 66 6f 72 20 76 65 72 73 69 6f 6e 20 32 2e 0a   for version 2..
1a70: 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 69    */.  sqlite3_i
1a80: 6f 5f 6d 65 74 68 6f 64 73 20 73 49 6f 4d 65 74  o_methods sIoMet
1a90: 68 6f 64 73 56 31 3b 0a 20 20 73 71 6c 69 74 65  hodsV1;.  sqlite
1aa0: 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49 6f  3_io_methods sIo
1ab0: 4d 65 74 68 6f 64 73 56 32 3b 0a 0a 20 20 2f 2a  MethodsV2;..  /*
1ac0: 20 54 72 75 65 20 77 68 65 6e 20 74 68 69 73 20   True when this 
1ad0: 73 68 69 6d 20 68 61 73 20 62 65 65 6e 20 69 6e  shim has been in
1ae0: 69 74 69 61 6c 69 7a 65 64 2e 0a 20 20 2a 2f 0a  itialized..  */.
1af0: 20 20 69 6e 74 20 69 73 49 6e 69 74 69 61 6c 69    int isInitiali
1b00: 7a 65 64 3b 0a 0a 20 20 2f 2a 20 46 6f 72 20 72  zed;..  /* For r
1b10: 75 6e 2d 74 69 6d 65 20 61 63 63 65 73 73 20 61  un-time access a
1b20: 6e 79 20 6f 66 20 74 68 65 20 6f 74 68 65 72 20  ny of the other 
1b30: 67 6c 6f 62 61 6c 20 64 61 74 61 20 73 74 72 75  global data stru
1b40: 63 74 75 72 65 73 20 69 6e 20 74 68 69 73 0a 20  ctures in this. 
1b50: 20 2a 2a 20 73 68 69 6d 2c 20 74 68 65 20 66 6f   ** shim, the fo
1b60: 6c 6c 6f 77 69 6e 67 20 6d 75 74 65 78 20 6d 75  llowing mutex mu
1b70: 73 74 20 62 65 20 68 65 6c 64 2e 0a 20 20 2a 2f  st be held..  */
1b80: 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  .  sqlite3_mutex
1b90: 20 2a 70 4d 75 74 65 78 3b 0a 0a 20 20 2f 2a 20   *pMutex;..  /* 
1ba0: 4c 69 73 74 20 6f 66 20 6d 75 6c 74 69 70 6c 65  List of multiple
1bb0: 78 47 72 6f 75 70 20 6f 62 6a 65 63 74 73 2e 0a  xGroup objects..
1bc0: 20 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78    */.  multiplex
1bd0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 73 3b 0a  Group *pGroups;.
1be0: 0a 20 20 2f 2a 20 53 74 6f 72 61 67 65 20 66 6f  .  /* Storage fo
1bf0: 72 20 74 65 6d 70 20 66 69 6c 65 20 6e 61 6d 65  r temp file name
1c00: 73 2e 20 20 41 6c 6c 6f 63 61 74 65 64 20 64 75  s.  Allocated du
1c10: 72 69 6e 67 20 0a 20 20 2a 2a 20 69 6e 69 74 69  ring .  ** initi
1c20: 61 6c 69 7a 61 74 69 6f 6e 20 74 6f 20 74 68 65  alization to the
1c30: 20 6d 61 78 20 70 61 74 68 6e 61 6d 65 20 6f 66   max pathname of
1c40: 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20   the underlying 
1c50: 56 46 53 2e 0a 20 20 2a 2f 0a 20 20 63 68 61 72  VFS..  */.  char
1c60: 20 2a 7a 4e 61 6d 65 3b 0a 0a 7d 20 67 4d 75 6c   *zName;..} gMul
1c70: 74 69 70 6c 65 78 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a  tiplex;../******
1c80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1c90: 2a 2a 2a 20 55 74 69 6c 69 74 79 20 52 6f 75 74  *** Utility Rout
1ca0: 69 6e 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ines ***********
1cb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1cc0: 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 41 63  ******/./*.** Ac
1cd0: 71 75 69 72 65 20 61 6e 64 20 72 65 6c 65 61 73  quire and releas
1ce0: 65 20 74 68 65 20 6d 75 74 65 78 20 75 73 65 64  e the mutex used
1cf0: 20 74 6f 20 73 65 72 69 61 6c 69 7a 65 20 61 63   to serialize ac
1d00: 63 65 73 73 20 74 6f 20 74 68 65 0a 2a 2a 20 6c  cess to the.** l
1d10: 69 73 74 20 6f 66 20 6d 75 6c 74 69 70 6c 65 78  ist of multiplex
1d20: 47 72 6f 75 70 73 2e 0a 2a 2f 0a 73 74 61 74 69  Groups..*/.stati
1d30: 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78  c void multiplex
1d40: 45 6e 74 65 72 28 76 6f 69 64 29 7b 20 73 71 6c  Enter(void){ sql
1d50: 69 74 65 33 5f 6d 75 74 65 78 5f 65 6e 74 65 72  ite3_mutex_enter
1d60: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74  (gMultiplex.pMut
1d70: 65 78 29 3b 20 7d 0a 73 74 61 74 69 63 20 76 6f  ex); }.static vo
1d80: 69 64 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76  id multiplexLeav
1d90: 65 28 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33  e(void){ sqlite3
1da0: 5f 6d 75 74 65 78 5f 6c 65 61 76 65 28 67 4d 75  _mutex_leave(gMu
1db0: 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b  ltiplex.pMutex);
1dc0: 20 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6f 6d 70 75 74   }../*.** Comput
1dd0: 65 20 61 20 73 74 72 69 6e 67 20 6c 65 6e 67 74  e a string lengt
1de0: 68 20 74 68 61 74 20 69 73 20 6c 69 6d 69 74 65  h that is limite
1df0: 64 20 74 6f 20 77 68 61 74 20 63 61 6e 20 62 65  d to what can be
1e00: 20 73 74 6f 72 65 64 20 69 6e 0a 2a 2a 20 6c 6f   stored in.** lo
1e10: 77 65 72 20 33 30 20 62 69 74 73 20 6f 66 20 61  wer 30 bits of a
1e20: 20 33 32 2d 62 69 74 20 73 69 67 6e 65 64 20 69   32-bit signed i
1e30: 6e 74 65 67 65 72 2e 0a 2a 2a 0a 2a 2a 20 54 68  nteger..**.** Th
1e40: 65 20 76 61 6c 75 65 20 72 65 74 75 72 6e 65 64  e value returned
1e50: 20 77 69 6c 6c 20 6e 65 76 65 72 20 62 65 20 6e   will never be n
1e60: 65 67 61 74 69 76 65 2e 20 20 4e 6f 72 20 77 69  egative.  Nor wi
1e70: 6c 6c 20 69 74 20 65 76 65 72 20 62 65 20 67 72  ll it ever be gr
1e80: 65 61 74 65 72 0a 2a 2a 20 74 68 61 6e 20 74 68  eater.** than th
1e90: 65 20 61 63 74 75 61 6c 20 6c 65 6e 67 74 68 20  e actual length 
1ea0: 6f 66 20 74 68 65 20 73 74 72 69 6e 67 2e 20 20  of the string.  
1eb0: 46 6f 72 20 76 65 72 79 20 6c 6f 6e 67 20 73 74  For very long st
1ec0: 72 69 6e 67 73 20 28 67 72 65 61 74 65 72 0a 2a  rings (greater.*
1ed0: 2a 20 74 68 61 6e 20 31 47 69 42 29 20 74 68 65  * than 1GiB) the
1ee0: 20 76 61 6c 75 65 20 72 65 74 75 72 6e 65 64 20   value returned 
1ef0: 6d 69 67 68 74 20 62 65 20 6c 65 73 73 20 74 68  might be less th
1f00: 61 6e 20 74 68 65 20 74 72 75 65 20 73 74 72 69  an the true stri
1f10: 6e 67 20 6c 65 6e 67 74 68 2e 0a 2a 2f 0a 73 74  ng length..*/.st
1f20: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
1f30: 65 78 53 74 72 6c 65 6e 33 30 28 63 6f 6e 73 74  exStrlen30(const
1f40: 20 63 68 61 72 20 2a 7a 29 7b 0a 20 20 63 6f 6e   char *z){.  con
1f50: 73 74 20 63 68 61 72 20 2a 7a 32 20 3d 20 7a 3b  st char *z2 = z;
1f60: 0a 20 20 69 66 28 20 7a 3d 3d 30 20 29 20 72 65  .  if( z==0 ) re
1f70: 74 75 72 6e 20 30 3b 0a 20 20 77 68 69 6c 65 28  turn 0;.  while(
1f80: 20 2a 7a 32 20 29 7b 20 7a 32 2b 2b 3b 20 7d 0a   *z2 ){ z2++; }.
1f90: 20 20 72 65 74 75 72 6e 20 30 78 33 66 66 66 66    return 0x3ffff
1fa0: 66 66 66 20 26 20 28 69 6e 74 29 28 7a 32 20 2d  fff & (int)(z2 -
1fb0: 20 7a 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 72   z);.}../*.** Cr
1fc0: 65 61 74 65 20 61 20 74 65 6d 70 6f 72 61 72 79  eate a temporary
1fd0: 20 66 69 6c 65 20 6e 61 6d 65 20 69 6e 20 7a 42   file name in zB
1fe0: 75 66 2e 20 20 7a 42 75 66 20 6d 75 73 74 20 62  uf.  zBuf must b
1ff0: 65 20 62 69 67 20 65 6e 6f 75 67 68 20 74 6f 0a  e big enough to.
2000: 2a 2a 20 68 6f 6c 64 20 61 74 20 70 4f 72 69 67  ** hold at pOrig
2010: 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 20  Vfs->mxPathname 
2020: 63 68 61 72 61 63 74 65 72 73 2e 20 20 54 68 69  characters.  Thi
2030: 73 20 66 75 6e 63 74 69 6f 6e 20 64 65 70 61 72  s function depar
2040: 74 73 0a 2a 2a 20 66 72 6f 6d 20 74 68 65 20 74  ts.** from the t
2050: 72 61 64 69 74 69 6f 6e 61 6c 20 74 65 6d 70 6f  raditional tempo
2060: 72 61 72 79 20 6e 61 6d 65 20 67 65 6e 65 72 61  rary name genera
2070: 74 69 6f 6e 20 69 6e 20 74 68 65 20 6f 73 5f 77  tion in the os_w
2080: 69 6e 0a 2a 2a 20 61 6e 64 20 6f 73 5f 75 6e 69  in.** and os_uni
2090: 78 20 56 46 53 20 69 6e 20 73 65 76 65 72 61 6c  x VFS in several
20a0: 20 77 61 79 73 2c 20 62 75 74 20 69 73 20 6e 65   ways, but is ne
20b0: 63 65 73 73 61 72 79 20 73 6f 20 74 68 61 74 20  cessary so that 
20c0: 0a 2a 2a 20 74 68 65 20 66 69 6c 65 20 6e 61 6d  .** the file nam
20d0: 65 20 69 73 20 6b 6e 6f 77 6e 20 66 6f 72 20 74  e is known for t
20e0: 65 6d 70 6f 72 61 72 79 20 66 69 6c 65 73 20 28  emporary files (
20f0: 6c 69 6b 65 20 74 68 6f 73 65 20 75 73 65 64 20  like those used 
2100: 0a 2a 2a 20 64 75 72 69 6e 67 20 76 61 63 75 75  .** during vacuu
2110: 6d 2e 29 0a 2a 2a 0a 2a 2a 20 4e 2e 42 2e 20 54  m.).**.** N.B. T
2120: 68 69 73 20 72 6f 75 74 69 6e 65 20 61 73 73 75  his routine assu
2130: 6d 65 73 20 79 6f 75 72 20 75 6e 64 65 72 6c 79  mes your underly
2140: 69 6e 67 20 56 46 53 20 69 73 20 6f 6b 20 77 69  ing VFS is ok wi
2150: 74 68 20 75 73 69 6e 67 0a 2a 2a 20 22 2f 22 20  th using.** "/" 
2160: 61 73 20 61 20 64 69 72 65 63 74 6f 72 79 20 73  as a directory s
2170: 65 70 65 72 61 74 6f 72 2e 20 20 54 68 69 73 20  eperator.  This 
2180: 69 73 20 74 68 65 20 64 65 66 61 75 6c 74 20 66  is the default f
2190: 6f 72 20 55 4e 49 58 73 0a 2a 2a 20 61 6e 64 20  or UNIXs.** and 
21a0: 69 73 20 61 6c 6c 6f 77 65 64 20 28 65 76 65 6e  is allowed (even
21b0: 20 6d 69 78 65 64 29 20 66 6f 72 20 6d 6f 73 74   mixed) for most
21c0: 20 76 65 72 73 69 6f 6e 73 20 6f 66 20 57 69 6e   versions of Win
21d0: 64 6f 77 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  dows..*/.static 
21e0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 47 65 74  int multiplexGet
21f0: 54 65 6d 70 6e 61 6d 65 28 73 71 6c 69 74 65 33  Tempname(sqlite3
2200: 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 2c 20  _vfs *pOrigVfs, 
2210: 69 6e 74 20 6e 42 75 66 2c 20 63 68 61 72 20 2a  int nBuf, char *
2220: 7a 42 75 66 29 7b 0a 20 20 73 74 61 74 69 63 20  zBuf){.  static 
2230: 63 68 61 72 20 7a 43 68 61 72 73 5b 5d 20 3d 0a  char zChars[] =.
2240: 20 20 20 20 22 61 62 63 64 65 66 67 68 69 6a 6b      "abcdefghijk
2250: 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 22  lmnopqrstuvwxyz"
2260: 0a 20 20 20 20 22 41 42 43 44 45 46 47 48 49 4a  .    "ABCDEFGHIJ
2270: 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a  KLMNOPQRSTUVWXYZ
2280: 22 0a 20 20 20 20 22 30 31 32 33 34 35 36 37 38  ".    "012345678
2290: 39 22 3b 0a 20 20 69 6e 74 20 69 2c 6a 3b 0a 20  9";.  int i,j;. 
22a0: 20 69 6e 74 20 61 74 74 65 6d 70 74 73 20 3d 20   int attempts = 
22b0: 30 3b 0a 20 20 69 6e 74 20 65 78 69 73 74 73 20  0;.  int exists 
22c0: 3d 20 30 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  = 0;.  int rc = 
22d0: 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 0a 20  SQLITE_ERROR;.. 
22e0: 20 2f 2a 20 43 68 65 63 6b 20 74 68 61 74 20 74   /* Check that t
22f0: 68 65 20 6f 75 74 70 75 74 20 62 75 66 66 65 72  he output buffer
2300: 20 69 73 20 6c 61 72 67 65 20 65 6e 6f 75 67 68   is large enough
2310: 20 66 6f 72 20 0a 20 20 2a 2a 20 70 56 66 73 2d   for .  ** pVfs-
2320: 3e 6d 78 50 61 74 68 6e 61 6d 65 20 63 68 61 72  >mxPathname char
2330: 61 63 74 65 72 73 2e 0a 20 20 2a 2f 0a 20 20 69  acters..  */.  i
2340: 66 28 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  f( pOrigVfs->mxP
2350: 61 74 68 6e 61 6d 65 20 3c 3d 20 6e 42 75 66 20  athname <= nBuf 
2360: 29 7b 0a 20 20 20 20 63 68 61 72 20 2a 7a 54 6d  ){.    char *zTm
2370: 70 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  p = sqlite3_mall
2380: 6f 63 28 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  oc(pOrigVfs->mxP
2390: 61 74 68 6e 61 6d 65 29 3b 0a 20 20 20 20 69 66  athname);.    if
23a0: 28 20 7a 54 6d 70 3d 3d 30 20 29 20 72 65 74 75  ( zTmp==0 ) retu
23b0: 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b  rn SQLITE_NOMEM;
23c0: 0a 0a 20 20 20 20 2f 2a 20 73 71 6c 69 74 65 33  ..    /* sqlite3
23d0: 5f 74 65 6d 70 5f 64 69 72 65 63 74 6f 72 79 20  _temp_directory 
23e0: 73 68 6f 75 6c 64 20 61 6c 77 61 79 73 20 62 65  should always be
23f0: 20 6c 65 73 73 20 74 68 61 6e 0a 20 20 20 20 2a   less than.    *
2400: 2a 20 70 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61  * pVfs->mxPathna
2410: 6d 65 20 63 68 61 72 61 63 74 65 72 73 2e 0a 20  me characters.. 
2420: 20 20 20 2a 2f 0a 20 20 20 20 73 71 6c 69 74 65     */.    sqlite
2430: 33 5f 73 6e 70 72 69 6e 74 66 28 70 4f 72 69 67  3_snprintf(pOrig
2440: 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 2c  Vfs->mxPathname,
2450: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2460: 20 20 20 20 20 20 7a 54 6d 70 2c 0a 20 20 20 20        zTmp,.    
2470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2480: 20 22 25 73 2f 22 2c 0a 20 20 20 20 20 20 20 20   "%s/",.        
2490: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 71 6c               sql
24a0: 69 74 65 33 5f 74 65 6d 70 5f 64 69 72 65 63 74  ite3_temp_direct
24b0: 6f 72 79 20 3f 20 73 71 6c 69 74 65 33 5f 74 65  ory ? sqlite3_te
24c0: 6d 70 5f 64 69 72 65 63 74 6f 72 79 20 3a 20 22  mp_directory : "
24d0: 2e 22 29 3b 0a 20 20 20 20 72 63 20 3d 20 70 4f  .");.    rc = pO
24e0: 72 69 67 56 66 73 2d 3e 78 46 75 6c 6c 50 61 74  rigVfs->xFullPat
24f0: 68 6e 61 6d 65 28 70 4f 72 69 67 56 66 73 2c 20  hname(pOrigVfs, 
2500: 7a 54 6d 70 2c 20 6e 42 75 66 2c 20 7a 42 75 66  zTmp, nBuf, zBuf
2510: 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66  );.    sqlite3_f
2520: 72 65 65 28 7a 54 6d 70 29 3b 0a 20 20 20 20 69  ree(zTmp);.    i
2530: 66 28 20 72 63 20 29 20 72 65 74 75 72 6e 20 72  f( rc ) return r
2540: 63 3b 0a 0a 20 20 20 20 2f 2a 20 43 68 65 63 6b  c;..    /* Check
2550: 20 74 68 61 74 20 74 68 65 20 6f 75 74 70 75 74   that the output
2560: 20 62 75 66 66 65 72 20 69 73 20 6c 61 72 67 65   buffer is large
2570: 20 65 6e 6f 75 67 68 20 66 6f 72 20 74 68 65 20   enough for the 
2580: 74 65 6d 70 6f 72 61 72 79 20 66 69 6c 65 20 0a  temporary file .
2590: 20 20 20 20 2a 2a 20 6e 61 6d 65 2e 0a 20 20 20      ** name..   
25a0: 20 2a 2f 0a 20 20 20 20 6a 20 3d 20 6d 75 6c 74   */.    j = mult
25b0: 69 70 6c 65 78 53 74 72 6c 65 6e 33 30 28 7a 42  iplexStrlen30(zB
25c0: 75 66 29 3b 0a 20 20 20 20 69 66 28 20 28 6a 20  uf);.    if( (j 
25d0: 2b 20 38 20 2b 20 31 20 2b 20 33 20 2b 20 31 29  + 8 + 1 + 3 + 1)
25e0: 20 3c 3d 20 6e 42 75 66 20 29 7b 0a 20 20 20 20   <= nBuf ){.    
25f0: 20 20 2f 2a 20 4d 61 6b 65 20 33 20 61 74 74 65    /* Make 3 atte
2600: 6d 70 74 73 20 74 6f 20 67 65 6e 65 72 61 74 65  mpts to generate
2610: 20 61 20 75 6e 69 71 75 65 20 6e 61 6d 65 2e 20   a unique name. 
2620: 2a 2f 0a 20 20 20 20 20 20 64 6f 20 7b 0a 20 20  */.      do {.  
2630: 20 20 20 20 20 20 61 74 74 65 6d 70 74 73 2b 2b        attempts++
2640: 3b 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65  ;.        sqlite
2650: 33 5f 72 61 6e 64 6f 6d 6e 65 73 73 28 38 2c 20  3_randomness(8, 
2660: 26 7a 42 75 66 5b 6a 5d 29 3b 0a 20 20 20 20 20  &zBuf[j]);.     
2670: 20 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 38 3b     for(i=0; i<8;
2680: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 20   i++){.         
2690: 20 75 6e 73 69 67 6e 65 64 20 63 68 61 72 20 75   unsigned char u
26a0: 63 20 3d 20 28 75 6e 73 69 67 6e 65 64 20 63 68  c = (unsigned ch
26b0: 61 72 29 7a 42 75 66 5b 6a 2b 69 5d 3b 0a 20 20  ar)zBuf[j+i];.  
26c0: 20 20 20 20 20 20 20 20 7a 42 75 66 5b 6a 2b 69          zBuf[j+i
26d0: 5d 20 3d 20 28 63 68 61 72 29 7a 43 68 61 72 73  ] = (char)zChars
26e0: 5b 75 63 25 28 73 69 7a 65 6f 66 28 7a 43 68 61  [uc%(sizeof(zCha
26f0: 72 73 29 2d 31 29 5d 3b 0a 20 20 20 20 20 20 20  rs)-1)];.       
2700: 20 7d 0a 20 20 20 20 20 20 20 20 6d 65 6d 63 70   }.        memcp
2710: 79 28 26 7a 42 75 66 5b 6a 2b 69 5d 2c 20 22 2e  y(&zBuf[j+i], ".
2720: 74 6d 70 22 2c 20 35 29 3b 0a 20 20 20 20 20 20  tmp", 5);.      
2730: 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d    rc = pOrigVfs-
2740: 3e 78 41 63 63 65 73 73 28 70 4f 72 69 67 56 66  >xAccess(pOrigVf
2750: 73 2c 20 7a 42 75 66 2c 20 53 51 4c 49 54 45 5f  s, zBuf, SQLITE_
2760: 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20 26  ACCESS_EXISTS, &
2770: 65 78 69 73 74 73 29 3b 0a 20 20 20 20 20 20 7d  exists);.      }
2780: 20 77 68 69 6c 65 20 28 20 28 72 63 3d 3d 53 51   while ( (rc==SQ
2790: 4c 49 54 45 5f 4f 4b 29 20 26 26 20 65 78 69 73  LITE_OK) && exis
27a0: 74 73 20 26 26 20 28 61 74 74 65 6d 70 74 73 3c  ts && (attempts<
27b0: 33 29 20 29 3b 0a 20 20 20 20 20 20 69 66 28 20  3) );.      if( 
27c0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
27d0: 20 65 78 69 73 74 73 20 29 7b 0a 20 20 20 20 20   exists ){.     
27e0: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 45     rc = SQLITE_E
27f0: 52 52 4f 52 3b 0a 20 20 20 20 20 20 7d 0a 20 20  RROR;.      }.  
2800: 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72    }.  }..  retur
2810: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 54 72 61 6e  n rc;.}../* Tran
2820: 73 6c 61 74 65 20 61 6e 20 73 71 6c 69 74 65 33  slate an sqlite3
2830: 5f 66 69 6c 65 2a 20 74 68 61 74 20 69 73 20 72  _file* that is r
2840: 65 61 6c 6c 79 20 61 20 6d 75 6c 74 69 70 6c 65  eally a multiple
2850: 78 47 72 6f 75 70 2a 20 69 6e 74 6f 0a 2a 2a 20  xGroup* into.** 
2860: 74 68 65 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  the sqlite3_file
2870: 2a 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c  * for the underl
2880: 79 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46  ying original VF
2890: 53 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73 71 6c  S..*/.static sql
28a0: 69 74 65 33 5f 66 69 6c 65 20 2a 6d 75 6c 74 69  ite3_file *multi
28b0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 0a 20 20 6d  plexSubOpen(.  m
28c0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 43  ultiplexConn *pC
28d0: 6f 6e 6e 2c 0a 20 20 69 6e 74 20 69 43 68 75 6e  onn,.  int iChun
28e0: 6b 2c 0a 20 20 69 6e 74 20 2a 72 63 2c 0a 20 20  k,.  int *rc,.  
28f0: 69 6e 74 20 2a 70 4f 75 74 46 6c 61 67 73 0a 29  int *pOutFlags.)
2900: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  {.  multiplexGro
2910: 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 43 6f  up *pGroup = pCo
2920: 6e 6e 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 73 71  nn->pGroup;.  sq
2930: 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67  lite3_vfs *pOrig
2940: 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78  Vfs = gMultiplex
2950: 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 20 20 20  .pOrigVfs;      
2960: 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f    /* Real VFS */
2970: 0a 20 20 69 66 28 20 69 43 68 75 6e 6b 3c 70 47  .  if( iChunk<pG
2980: 72 6f 75 70 2d 3e 6e 4d 61 78 43 68 75 6e 6b 73  roup->nMaxChunks
2990: 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f   ){.    sqlite3_
29a0: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
29b0: 20 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c 5b 69   pGroup->pReal[i
29c0: 43 68 75 6e 6b 5d 3b 20 20 20 2f 2a 20 52 65 61  Chunk];   /* Rea
29d0: 6c 20 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f  l file descripto
29e0: 72 20 2a 2f 0a 20 20 20 20 69 66 28 20 21 70 47  r */.    if( !pG
29f0: 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 43 68 75  roup->bOpen[iChu
2a00: 6e 6b 5d 20 29 7b 0a 20 20 20 20 20 20 6d 65 6d  nk] ){.      mem
2a10: 63 70 79 28 67 4d 75 6c 74 69 70 6c 65 78 2e 7a  cpy(gMultiplex.z
2a20: 4e 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 7a 4e  Name, pGroup->zN
2a30: 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 6e 4e 61  ame, pGroup->nNa
2a40: 6d 65 2b 31 29 3b 0a 20 20 20 20 20 20 69 66 28  me+1);.      if(
2a50: 20 69 43 68 75 6e 6b 20 29 7b 0a 23 69 66 64 65   iChunk ){.#ifde
2a60: 66 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  f SQLITE_MULTIPL
2a70: 45 58 5f 45 58 54 5f 4f 56 57 52 0a 20 20 20 20  EX_EXT_OVWR.    
2a80: 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72      sqlite3_snpr
2a90: 69 6e 74 66 28 53 51 4c 49 54 45 5f 4d 55 4c 54  intf(SQLITE_MULT
2aa0: 49 50 4c 45 58 5f 45 58 54 5f 53 5a 2b 31 2c 0a  IPLEX_EXT_SZ+1,.
2ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 67 4d 75               gMu
2ac0: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2b 70 47  ltiplex.zName+pG
2ad0: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2d 53 51 4c 49  roup->nName-SQLI
2ae0: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
2af0: 5f 53 5a 2c 0a 20 20 20 20 20 20 20 20 20 20 20  _SZ,.           
2b00: 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c    SQLITE_MULTIPL
2b10: 45 58 5f 45 58 54 5f 46 4d 54 2c 20 69 43 68 75  EX_EXT_FMT, iChu
2b20: 6e 6b 29 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20  nk);.#else.     
2b30: 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69     sqlite3_snpri
2b40: 6e 74 66 28 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ntf(SQLITE_MULTI
2b50: 50 4c 45 58 5f 45 58 54 5f 53 5a 2b 31 2c 0a 20  PLEX_EXT_SZ+1,. 
2b60: 20 20 20 20 20 20 20 20 20 20 20 20 67 4d 75 6c              gMul
2b70: 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2b 70 47 72  tiplex.zName+pGr
2b80: 6f 75 70 2d 3e 6e 4e 61 6d 65 2c 0a 20 20 20 20  oup->nName,.    
2b90: 20 20 20 20 20 20 20 20 20 53 51 4c 49 54 45 5f           SQLITE_
2ba0: 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d  MULTIPLEX_EXT_FM
2bb0: 54 2c 20 69 43 68 75 6e 6b 29 3b 0a 23 65 6e 64  T, iChunk);.#end
2bc0: 69 66 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20  if.      }.     
2bd0: 20 2a 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d   *rc = pOrigVfs-
2be0: 3e 78 4f 70 65 6e 28 70 4f 72 69 67 56 66 73 2c  >xOpen(pOrigVfs,
2bf0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d   gMultiplex.zNam
2c00: 65 2c 20 70 53 75 62 4f 70 65 6e 2c 0a 20 20 20  e, pSubOpen,.   
2c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c20: 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d           pGroup-
2c30: 3e 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c 61 67  >flags, pOutFlag
2c40: 73 29 3b 0a 20 20 20 20 20 20 69 66 28 20 2a 72  s);.      if( *r
2c50: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
2c60: 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e          pGroup->
2c70: 62 4f 70 65 6e 5b 69 43 68 75 6e 6b 5d 20 3d 20  bOpen[iChunk] = 
2c80: 2d 31 3b 0a 20 20 20 20 20 20 20 20 72 65 74 75  -1;.        retu
2c90: 72 6e 20 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20  rn pSubOpen;.   
2ca0: 20 20 20 7d 0a 20 20 20 20 20 20 72 65 74 75 72     }.      retur
2cb0: 6e 20 4e 55 4c 4c 3b 0a 20 20 20 20 7d 0a 20 20  n NULL;.    }.  
2cc0: 20 20 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f    *rc = SQLITE_O
2cd0: 4b 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  K;.    return pS
2ce0: 75 62 4f 70 65 6e 3b 0a 20 20 7d 0a 20 20 2a 72  ubOpen;.  }.  *r
2cf0: 63 20 3d 20 53 51 4c 49 54 45 5f 46 55 4c 4c 3b  c = SQLITE_FULL;
2d00: 0a 20 20 72 65 74 75 72 6e 20 4e 55 4c 4c 3b 0a  .  return NULL;.
2d10: 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73  }../*.** This is
2d20: 20 74 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74   the implementat
2d30: 69 6f 6e 20 6f 66 20 74 68 65 20 6d 75 6c 74 69  ion of the multi
2d40: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 53  plex_control() S
2d50: 51 4c 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a  QL function..*/.
2d60: 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74  static void mult
2d70: 69 70 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e 63  iplexControlFunc
2d80: 28 0a 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74  (.  sqlite3_cont
2d90: 65 78 74 20 2a 63 6f 6e 74 65 78 74 2c 0a 20 20  ext *context,.  
2da0: 69 6e 74 20 61 72 67 63 2c 0a 20 20 73 71 6c 69  int argc,.  sqli
2db0: 74 65 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67 76  te3_value **argv
2dc0: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  .){.  int rc = S
2dd0: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 73 71 6c 69  QLITE_OK;.  sqli
2de0: 74 65 33 20 2a 64 62 20 3d 20 73 71 6c 69 74 65  te3 *db = sqlite
2df0: 33 5f 63 6f 6e 74 65 78 74 5f 64 62 5f 68 61 6e  3_context_db_han
2e00: 64 6c 65 28 63 6f 6e 74 65 78 74 29 3b 0a 20 20  dle(context);.  
2e10: 69 6e 74 20 6f 70 3b 0a 20 20 69 6e 74 20 69 56  int op;.  int iV
2e20: 61 6c 3b 0a 0a 20 20 69 66 28 20 21 64 62 20 7c  al;..  if( !db |
2e30: 7c 20 61 72 67 63 21 3d 32 20 29 7b 20 0a 20 20  | argc!=2 ){ .  
2e40: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52    rc = SQLITE_ER
2e50: 52 4f 52 3b 20 0a 20 20 7d 65 6c 73 65 7b 0a 20  ROR; .  }else{. 
2e60: 20 20 20 2f 2a 20 65 78 74 72 61 63 74 20 70 61     /* extract pa
2e70: 72 61 6d 73 20 2a 2f 0a 20 20 20 20 6f 70 20 3d  rams */.    op =
2e80: 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69   sqlite3_value_i
2e90: 6e 74 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20  nt(argv[0]);.   
2ea0: 20 69 56 61 6c 20 3d 20 73 71 6c 69 74 65 33 5f   iVal = sqlite3_
2eb0: 76 61 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 31  value_int(argv[1
2ec0: 5d 29 3b 0a 20 20 20 20 2f 2a 20 6d 61 70 20 66  ]);.    /* map f
2ed0: 75 6e 63 74 69 6f 6e 20 6f 70 20 74 6f 20 66 69  unction op to fi
2ee0: 6c 65 5f 63 6f 6e 74 72 6f 6c 20 6f 70 20 2a 2f  le_control op */
2ef0: 0a 20 20 20 20 73 77 69 74 63 68 28 20 6f 70 20  .    switch( op 
2f00: 29 7b 0a 20 20 20 20 20 20 63 61 73 65 20 31 3a  ){.      case 1:
2f10: 20 0a 20 20 20 20 20 20 20 20 6f 70 20 3d 20 4d   .        op = M
2f20: 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e  ULTIPLEX_CTRL_EN
2f30: 41 42 4c 45 3b 20 0a 20 20 20 20 20 20 20 20 62  ABLE; .        b
2f40: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
2f50: 20 32 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20   2: .        op 
2f60: 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c  = MULTIPLEX_CTRL
2f70: 5f 53 45 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b  _SET_CHUNK_SIZE;
2f80: 20 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b   .        break;
2f90: 0a 20 20 20 20 20 20 63 61 73 65 20 33 3a 20 0a  .      case 3: .
2fa0: 20 20 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c          op = MUL
2fb0: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f  TIPLEX_CTRL_SET_
2fc0: 4d 41 58 5f 43 48 55 4e 4b 53 3b 20 0a 20 20 20  MAX_CHUNKS; .   
2fd0: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
2fe0: 20 20 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20    default:.     
2ff0: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e     rc = SQLITE_N
3000: 4f 54 46 4f 55 4e 44 3b 0a 20 20 20 20 20 20 20  OTFOUND;.       
3010: 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20   break;.    }.  
3020: 7d 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49  }.  if( rc==SQLI
3030: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20  TE_OK ){.    rc 
3040: 3d 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f 63  = sqlite3_file_c
3050: 6f 6e 74 72 6f 6c 28 64 62 2c 20 30 2c 20 6f 70  ontrol(db, 0, op
3060: 2c 20 26 69 56 61 6c 29 3b 0a 20 20 7d 0a 20 20  , &iVal);.  }.  
3070: 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 65  sqlite3_result_e
3080: 72 72 6f 72 5f 63 6f 64 65 28 63 6f 6e 74 65 78  rror_code(contex
3090: 74 2c 20 72 63 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  t, rc);.}../*.**
30a0: 20 54 68 69 73 20 69 73 20 74 68 65 20 65 6e 74   This is the ent
30b0: 72 79 20 70 6f 69 6e 74 20 74 6f 20 72 65 67 69  ry point to regi
30c0: 73 74 65 72 20 74 68 65 20 61 75 74 6f 2d 65 78  ster the auto-ex
30d0: 74 65 6e 73 69 6f 6e 20 66 6f 72 20 74 68 65 20  tension for the 
30e0: 0a 2a 2a 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f  .** multiplex_co
30f0: 6e 74 72 6f 6c 28 29 20 66 75 6e 63 74 69 6f 6e  ntrol() function
3100: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
3110: 6d 75 6c 74 69 70 6c 65 78 46 75 6e 63 49 6e 69  multiplexFuncIni
3120: 74 28 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62  t(.  sqlite3 *db
3130: 2c 20 0a 20 20 63 68 61 72 20 2a 2a 70 7a 45 72  , .  char **pzEr
3140: 72 4d 73 67 2c 20 0a 20 20 63 6f 6e 73 74 20 73  rMsg, .  const s
3150: 71 6c 69 74 65 33 5f 61 70 69 5f 72 6f 75 74 69  qlite3_api_routi
3160: 6e 65 73 20 2a 70 41 70 69 0a 29 7b 0a 20 20 69  nes *pApi.){.  i
3170: 6e 74 20 72 63 3b 0a 20 20 72 63 20 3d 20 73 71  nt rc;.  rc = sq
3180: 6c 69 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e  lite3_create_fun
3190: 63 74 69 6f 6e 28 64 62 2c 20 22 6d 75 6c 74 69  ction(db, "multi
31a0: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 32  plex_control", 2
31b0: 2c 20 53 51 4c 49 54 45 5f 41 4e 59 2c 20 0a 20  , SQLITE_ANY, . 
31c0: 20 20 20 20 20 30 2c 20 6d 75 6c 74 69 70 6c 65       0, multiple
31d0: 78 43 6f 6e 74 72 6f 6c 46 75 6e 63 2c 20 30 2c  xControlFunc, 0,
31e0: 20 30 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63   0);.  return rc
31f0: 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;.}../**********
3200: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
3210: 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61 70 70  VFS Method Wrapp
3220: 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ers ************
3230: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3240: 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69  */../*.** This i
3250: 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65 74 68  s the xOpen meth
3260: 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68 65 20  od used for the 
3270: 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46 53 2e  "multiplex" VFS.
3280: 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66 20 74  .**.** Most of t
3290: 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e 65 20  he work is done 
32a0: 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e  by the underlyin
32b0: 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 20  g original VFS. 
32c0: 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a 2a 20   This method.** 
32d0: 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74 68 65  simply links the
32e0: 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f 20 74   new file into t
32f0: 68 65 20 61 70 70 72 6f 70 72 69 61 74 65 20 6d  he appropriate m
3300: 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 20 69  ultiplex group i
3310: 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66 69 6c  f it is a.** fil
3320: 65 20 74 68 61 74 20 6e 65 65 64 73 20 74 6f 20  e that needs to 
3330: 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f 0a 73  be tracked..*/.s
3340: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
3350: 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c 69 74  lexOpen(.  sqlit
3360: 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20  e3_vfs *pVfs,   
3370: 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c        /* The mul
3380: 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20  tiplex VFS */.  
3390: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d  const char *zNam
33a0: 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61  e,         /* Na
33b0: 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20 62 65  me of file to be
33c0: 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73 71 6c   opened */.  sql
33d0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
33e0: 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c 6c 20  ,       /* Fill 
33f0: 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64 65 73  in this file des
3400: 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69 6e 74  criptor */.  int
3410: 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20 20 20   flags,         
3420: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
3430: 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68 65 20   to control the 
3440: 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e 74  opening */.  int
3450: 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20 20 20   *pOutFlags     
3460: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
3470: 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c 74 73   showing results
3480: 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 29   of opening */.)
3490: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
34a0: 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20  ITE_OK;         
34b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73 75           /* Resu
34c0: 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d 75 6c  lt code */.  mul
34d0: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d 75 6c  tiplexConn *pMul
34e0: 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20 20 20  tiplexOpen;     
34f0: 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d 75 6c    /* The new mul
3500: 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65 73 63  tiplex file desc
3510: 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75 6c 74  riptor */.  mult
3520: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
3530: 75 70 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  up;             
3540: 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64 69 6e   /* Correspondin
3550: 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  g multiplexGroup
3560: 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73 71 6c   object */.  sql
3570: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
3580: 70 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20  pen;            
3590: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
35a0: 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72 69 70  eal file descrip
35b0: 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  tor */.  sqlite3
35c0: 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d  _vfs *pOrigVfs =
35d0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
35e0: 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20  gVfs;   /* Real 
35f0: 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61  VFS */.  int nNa
3600: 6d 65 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69  me;.  int i;.  i
3610: 6e 74 20 73 7a 3b 0a 0a 20 20 55 4e 55 53 45 44  nt sz;..  UNUSED
3620: 5f 50 41 52 41 4d 45 54 45 52 28 70 56 66 73 29  _PARAMETER(pVfs)
3630: 3b 0a 0a 20 20 2f 2a 20 57 65 20 6e 65 65 64 20  ;..  /* We need 
3640: 74 6f 20 63 72 65 61 74 65 20 61 20 67 72 6f 75  to create a grou
3650: 70 20 73 74 72 75 63 74 75 72 65 20 61 6e 64 20  p structure and 
3660: 6d 61 6e 61 67 65 0a 20 20 2a 2a 20 61 63 63 65  manage.  ** acce
3670: 73 73 20 74 6f 20 74 68 69 73 20 67 72 6f 75 70  ss to this group
3680: 20 6f 66 20 66 69 6c 65 73 2e 0a 20 20 2a 2f 0a   of files..  */.
3690: 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72    multiplexEnter
36a0: 28 29 3b 0a 20 20 70 4d 75 6c 74 69 70 6c 65 78  ();.  pMultiplex
36b0: 4f 70 65 6e 20 3d 20 28 6d 75 6c 74 69 70 6c 65  Open = (multiple
36c0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 0a 20  xConn*)pConn;.. 
36d0: 20 2f 2a 20 49 66 20 74 68 65 20 73 65 63 6f 6e   /* If the secon
36e0: 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 74 68  d argument to th
36f0: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 4e  is function is N
3700: 55 4c 4c 2c 20 67 65 6e 65 72 61 74 65 20 61 20  ULL, generate a 
3710: 0a 20 20 2a 2a 20 74 65 6d 70 6f 72 61 72 79 20  .  ** temporary 
3720: 66 69 6c 65 20 6e 61 6d 65 20 74 6f 20 75 73 65  file name to use
3730: 2e 20 20 54 68 69 73 20 77 69 6c 6c 20 62 65 20  .  This will be 
3740: 68 61 6e 64 6c 65 64 20 62 79 20 74 68 65 0a 20  handled by the. 
3750: 20 2a 2a 20 6f 72 69 67 69 6e 61 6c 20 78 4f 70   ** original xOp
3760: 65 6e 20 6d 65 74 68 6f 64 2e 20 20 57 65 20 6a  en method.  We j
3770: 75 73 74 20 6e 65 65 64 20 74 6f 20 61 6c 6c 6f  ust need to allo
3780: 63 61 74 65 20 73 70 61 63 65 20 66 6f 72 0a 20  cate space for. 
3790: 20 2a 2a 20 69 74 2e 0a 20 20 2a 2f 0a 20 20 69   ** it..  */.  i
37a0: 66 28 20 21 7a 4e 61 6d 65 20 29 7b 0a 20 20 20  f( !zName ){.   
37b0: 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 47   rc = multiplexG
37c0: 65 74 54 65 6d 70 6e 61 6d 65 28 70 4f 72 69 67  etTempname(pOrig
37d0: 56 66 73 2c 20 70 4f 72 69 67 56 66 73 2d 3e 6d  Vfs, pOrigVfs->m
37e0: 78 50 61 74 68 6e 61 6d 65 2c 20 67 4d 75 6c 74  xPathname, gMult
37f0: 69 70 6c 65 78 2e 7a 4e 61 6d 65 29 3b 0a 20 20  iplex.zName);.  
3800: 20 20 7a 4e 61 6d 65 20 3d 20 67 4d 75 6c 74 69    zName = gMulti
3810: 70 6c 65 78 2e 7a 4e 61 6d 65 3b 0a 20 20 7d 0a  plex.zName;.  }.
3820: 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54  .  if( rc==SQLIT
3830: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a 20 61  E_OK ){.    /* a
3840: 6c 6c 6f 63 61 74 65 20 73 70 61 63 65 20 66 6f  llocate space fo
3850: 72 20 67 72 6f 75 70 20 2a 2f 0a 20 20 20 20 6e  r group */.    n
3860: 4e 61 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Name = multiplex
3870: 53 74 72 6c 65 6e 33 30 28 7a 4e 61 6d 65 29 3b  Strlen30(zName);
3880: 0a 20 20 20 20 73 7a 20 3d 20 73 69 7a 65 6f 66  .    sz = sizeof
3890: 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 29  (multiplexGroup)
38a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
38b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
38c0: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
38d0: 2f 0a 20 20 20 20 20 20 20 2b 20 28 73 69 7a 65  /.       + (size
38e0: 6f 66 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  of(sqlite3_file 
38f0: 2a 29 2a 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50  *)*SQLITE_MULTIP
3900: 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 29 20  LEX_MAX_CHUNKS) 
3910: 20 2f 2a 20 70 52 65 61 6c 5b 5d 20 2a 2f 0a 20   /* pReal[] */. 
3920: 20 20 20 20 20 20 2b 20 28 70 4f 72 69 67 56 66        + (pOrigVf
3930: 73 2d 3e 73 7a 4f 73 46 69 6c 65 2a 53 51 4c 49  s->szOsFile*SQLI
3940: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4d 41 58  TE_MULTIPLEX_MAX
3950: 5f 43 48 55 4e 4b 53 29 20 20 20 20 20 20 2f 2a  _CHUNKS)      /*
3960: 20 2a 70 52 65 61 6c 20 2a 2f 0a 20 20 20 20 20   *pReal */.     
3970: 20 20 2b 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49    + SQLITE_MULTI
3980: 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 20  PLEX_MAX_CHUNKS 
3990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39a0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 62 4f 70            /* bOp
39b0: 65 6e 5b 5d 20 2a 2f 0a 20 20 20 20 20 20 20 2b  en[] */.       +
39c0: 20 6e 4e 61 6d 65 20 2b 20 31 3b 20 20 20 20 20   nName + 1;     
39d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39f0: 20 20 20 20 20 20 20 2f 2a 20 7a 4e 61 6d 65 20         /* zName 
3a00: 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54  */.#ifndef SQLIT
3a10: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f  E_MULTIPLEX_EXT_
3a20: 4f 56 57 52 0a 20 20 20 20 73 7a 20 2b 3d 20 53  OVWR.    sz += S
3a30: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
3a40: 45 58 54 5f 53 5a 3b 0a 20 20 20 20 61 73 73 65  EXT_SZ;.    asse
3a50: 72 74 28 6e 4e 61 6d 65 2b 53 51 4c 49 54 45 5f  rt(nName+SQLITE_
3a60: 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a  MULTIPLEX_EXT_SZ
3a70: 20 3c 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50   < pOrigVfs->mxP
3a80: 61 74 68 6e 61 6d 65 29 3b 0a 23 65 6c 73 65 0a  athname);.#else.
3a90: 20 20 20 20 61 73 73 65 72 74 28 6e 4e 61 6d 65      assert(nName
3aa0: 20 3e 3d 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49   >= SQLITE_MULTI
3ab0: 50 4c 45 58 5f 45 58 54 5f 53 5a 29 3b 0a 20 20  PLEX_EXT_SZ);.  
3ac0: 20 20 61 73 73 65 72 74 28 6e 4e 61 6d 65 20 3c    assert(nName <
3ad0: 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50 61 74   pOrigVfs->mxPat
3ae0: 68 6e 61 6d 65 29 3b 0a 23 65 6e 64 69 66 0a 20  hname);.#endif. 
3af0: 20 20 20 70 47 72 6f 75 70 20 3d 20 73 71 6c 69     pGroup = sqli
3b00: 74 65 33 5f 6d 61 6c 6c 6f 63 28 20 73 7a 20 29  te3_malloc( sz )
3b10: 3b 0a 20 20 20 20 69 66 28 20 70 47 72 6f 75 70  ;.    if( pGroup
3b20: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 3d  ==0 ){.      rc=
3b30: 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20  SQLITE_NOMEM;.  
3b40: 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72    }.  }..  if( r
3b50: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
3b60: 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a      const char *
3b70: 7a 43 68 75 6e 6b 53 69 7a 65 3b 0a 20 20 20 20  zChunkSize;.    
3b80: 2f 2a 20 61 73 73 69 67 6e 20 70 6f 69 6e 74 65  /* assign pointe
3b90: 72 73 20 74 6f 20 65 78 74 72 61 20 73 70 61 63  rs to extra spac
3ba0: 65 20 61 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20  e allocated */. 
3bb0: 20 20 20 63 68 61 72 20 2a 70 20 3d 20 28 63 68     char *p = (ch
3bc0: 61 72 20 2a 29 26 70 47 72 6f 75 70 5b 31 5d 3b  ar *)&pGroup[1];
3bd0: 0a 20 20 20 20 70 4d 75 6c 74 69 70 6c 65 78 4f  .    pMultiplexO
3be0: 70 65 6e 2d 3e 70 47 72 6f 75 70 20 3d 20 70 47  pen->pGroup = pG
3bf0: 72 6f 75 70 3b 0a 20 20 20 20 6d 65 6d 73 65 74  roup;.    memset
3c00: 28 70 47 72 6f 75 70 2c 20 30 2c 20 73 7a 29 3b  (pGroup, 0, sz);
3c10: 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e  .    pGroup->bEn
3c20: 61 62 6c 65 64 20 3d 20 2d 31 3b 0a 20 20 20 20  abled = -1;.    
3c30: 70 47 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53 69  pGroup->nChunkSi
3c40: 7a 65 20 3d 20 53 51 4c 49 54 45 5f 4d 55 4c 54  ze = SQLITE_MULT
3c50: 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45  IPLEX_CHUNK_SIZE
3c60: 3b 0a 20 20 20 20 7a 43 68 75 6e 6b 53 69 7a 65  ;.    zChunkSize
3c70: 20 3d 20 73 71 6c 69 74 65 33 5f 75 72 69 5f 70   = sqlite3_uri_p
3c80: 61 72 61 6d 65 74 65 72 28 7a 4e 61 6d 65 2c 20  arameter(zName, 
3c90: 22 63 68 75 6e 6b 73 69 7a 65 22 29 3b 0a 20 20  "chunksize");.  
3ca0: 20 20 69 66 28 20 7a 43 68 75 6e 6b 53 69 7a 65    if( zChunkSize
3cb0: 20 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 6e 20   ){.      int n 
3cc0: 3d 20 61 74 6f 69 28 7a 43 68 75 6e 6b 53 69 7a  = atoi(zChunkSiz
3cd0: 65 29 3b 0a 20 20 20 20 20 20 69 66 28 20 6e 3e  e);.      if( n>
3ce0: 30 20 29 20 70 47 72 6f 75 70 2d 3e 6e 43 68 75  0 ) pGroup->nChu
3cf0: 6e 6b 53 69 7a 65 20 3d 20 28 6e 2b 30 78 66 66  nkSize = (n+0xff
3d00: 66 66 29 26 7e 30 78 66 66 66 66 3b 0a 20 20 20  ff)&~0xffff;.   
3d10: 20 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 6e   }.    pGroup->n
3d20: 4d 61 78 43 68 75 6e 6b 73 20 3d 20 53 51 4c 49  MaxChunks = SQLI
3d30: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4d 41 58  TE_MULTIPLEX_MAX
3d40: 5f 43 48 55 4e 4b 53 3b 0a 20 20 20 20 70 47 72  _CHUNKS;.    pGr
3d50: 6f 75 70 2d 3e 70 52 65 61 6c 20 3d 20 28 73 71  oup->pReal = (sq
3d60: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 2a 29 70 3b  lite3_file **)p;
3d70: 0a 20 20 20 20 70 20 2b 3d 20 28 73 69 7a 65 6f  .    p += (sizeo
3d80: 66 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  f(sqlite3_file *
3d90: 29 2a 70 47 72 6f 75 70 2d 3e 6e 4d 61 78 43 68  )*pGroup->nMaxCh
3da0: 75 6e 6b 73 29 3b 0a 20 20 20 20 66 6f 72 28 69  unks);.    for(i
3db0: 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 4d  =0; i<pGroup->nM
3dc0: 61 78 43 68 75 6e 6b 73 3b 20 69 2b 2b 29 7b 0a  axChunks; i++){.
3dd0: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 52        pGroup->pR
3de0: 65 61 6c 5b 69 5d 20 3d 20 28 73 71 6c 69 74 65  eal[i] = (sqlite
3df0: 33 5f 66 69 6c 65 20 2a 29 70 3b 0a 20 20 20 20  3_file *)p;.    
3e00: 20 20 70 20 2b 3d 20 70 4f 72 69 67 56 66 73 2d    p += pOrigVfs-
3e10: 3e 73 7a 4f 73 46 69 6c 65 3b 0a 20 20 20 20 7d  >szOsFile;.    }
3e20: 0a 20 20 20 20 2f 2a 20 62 4f 70 65 6e 5b 5d 20  .    /* bOpen[] 
3e30: 76 61 6c 73 20 73 68 6f 75 6c 64 20 61 6c 6c 20  vals should all 
3e40: 62 65 20 7a 65 72 6f 20 66 72 6f 6d 20 6d 65 6d  be zero from mem
3e50: 73 65 74 20 61 62 6f 76 65 20 2a 2f 0a 20 20 20  set above */.   
3e60: 20 70 47 72 6f 75 70 2d 3e 62 4f 70 65 6e 20 3d   pGroup->bOpen =
3e70: 20 70 3b 0a 20 20 20 20 70 20 2b 3d 20 70 47 72   p;.    p += pGr
3e80: 6f 75 70 2d 3e 6e 4d 61 78 43 68 75 6e 6b 73 3b  oup->nMaxChunks;
3e90: 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e 61  .    pGroup->zNa
3ea0: 6d 65 20 3d 20 70 3b 0a 20 20 20 20 2f 2a 20 73  me = p;.    /* s
3eb0: 61 76 65 20 6f 66 66 20 62 61 73 65 20 66 69 6c  ave off base fil
3ec0: 65 6e 61 6d 65 2c 20 6e 61 6d 65 20 6c 65 6e 67  ename, name leng
3ed0: 74 68 2c 20 61 6e 64 20 6f 72 69 67 69 6e 61 6c  th, and original
3ee0: 20 6f 70 65 6e 20 66 6c 61 67 73 20 20 2a 2f 0a   open flags  */.
3ef0: 20 20 20 20 6d 65 6d 63 70 79 28 70 47 72 6f 75      memcpy(pGrou
3f00: 70 2d 3e 7a 4e 61 6d 65 2c 20 7a 4e 61 6d 65 2c  p->zName, zName,
3f10: 20 6e 4e 61 6d 65 2b 31 29 3b 0a 20 20 20 20 70   nName+1);.    p
3f20: 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 20 3d 20 6e  Group->nName = n
3f30: 4e 61 6d 65 3b 0a 20 20 20 20 70 47 72 6f 75 70  Name;.    pGroup
3f40: 2d 3e 66 6c 61 67 73 20 3d 20 66 6c 61 67 73 3b  ->flags = flags;
3f50: 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20  .    pSubOpen = 
3f60: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
3f70: 28 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 2c  (pMultiplexOpen,
3f80: 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46 6c 61   0, &rc, pOutFla
3f90: 67 73 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75  gs);.    if( pSu
3fa0: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20 2f  bOpen ){.      /
3fb0: 2a 20 69 66 20 74 68 69 73 20 66 69 6c 65 20 69  * if this file i
3fc0: 73 20 61 6c 72 65 61 64 79 20 6c 61 72 67 65 72  s already larger
3fd0: 20 74 68 61 6e 20 63 68 75 6e 6b 20 73 69 7a 65   than chunk size
3fe0: 2c 20 64 69 73 61 62 6c 65 20 0a 20 20 20 20 20  , disable .     
3ff0: 20 2a 2a 20 74 68 65 20 6d 75 6c 74 69 70 6c 65   ** the multiple
4000: 78 20 66 65 61 74 75 72 65 2e 0a 20 20 20 20 20  x feature..     
4010: 20 2a 2f 0a 20 20 20 20 20 20 73 71 6c 69 74 65   */.      sqlite
4020: 33 5f 69 6e 74 36 34 20 73 7a 3b 0a 20 20 20 20  3_int64 sz;.    
4030: 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53 75 62    int rc2 = pSub
4040: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
4050: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70  xFileSize(pSubOp
4060: 65 6e 2c 20 26 73 7a 29 3b 0a 20 20 20 20 20 20  en, &sz);.      
4070: 69 66 28 20 28 72 63 32 3d 3d 53 51 4c 49 54 45  if( (rc2==SQLITE
4080: 5f 4f 4b 29 20 26 26 20 28 73 7a 3e 70 47 72 6f  _OK) && (sz>pGro
4090: 75 70 2d 3e 6e 43 68 75 6e 6b 53 69 7a 65 29 20  up->nChunkSize) 
40a0: 29 7b 0a 20 20 20 20 20 20 20 20 70 47 72 6f 75  ){.        pGrou
40b0: 70 2d 3e 62 45 6e 61 62 6c 65 64 20 3d 20 30 3b  p->bEnabled = 0;
40c0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69  .      }.      i
40d0: 66 28 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65  f( pSubOpen->pMe
40e0: 74 68 6f 64 73 2d 3e 69 56 65 72 73 69 6f 6e 3d  thods->iVersion=
40f0: 3d 31 20 29 7b 0a 20 20 20 20 20 20 20 20 70 4d  =1 ){.        pM
4100: 75 6c 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61  ultiplexOpen->ba
4110: 73 65 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67  se.pMethods = &g
4120: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
4130: 68 6f 64 73 56 31 3b 0a 20 20 20 20 20 20 7d 65  hodsV1;.      }e
4140: 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 70 4d 75  lse{.        pMu
4150: 6c 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73  ltiplexOpen->bas
4160: 65 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d  e.pMethods = &gM
4170: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
4180: 6f 64 73 56 32 3b 0a 20 20 20 20 20 20 7d 0a 20  odsV2;.      }. 
4190: 20 20 20 20 20 2f 2a 20 70 6c 61 63 65 20 74 68       /* place th
41a0: 69 73 20 67 72 6f 75 70 20 61 74 20 74 68 65 20  is group at the 
41b0: 68 65 61 64 20 6f 66 20 6f 75 72 20 6c 69 73 74  head of our list
41c0: 20 2a 2f 0a 20 20 20 20 20 20 70 47 72 6f 75 70   */.      pGroup
41d0: 2d 3e 70 4e 65 78 74 20 3d 20 67 4d 75 6c 74 69  ->pNext = gMulti
41e0: 70 6c 65 78 2e 70 47 72 6f 75 70 73 3b 0a 20 20  plex.pGroups;.  
41f0: 20 20 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c      if( gMultipl
4200: 65 78 2e 70 47 72 6f 75 70 73 20 29 20 67 4d 75  ex.pGroups ) gMu
4210: 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 2d  ltiplex.pGroups-
4220: 3e 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70 3b  >pPrev = pGroup;
4230: 0a 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65  .      gMultiple
4240: 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f  x.pGroups = pGro
4250: 75 70 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20  up;.    }else{. 
4260: 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65       sqlite3_fre
4270: 65 28 70 47 72 6f 75 70 29 3b 0a 20 20 20 20 7d  e(pGroup);.    }
4280: 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78  .  }.  multiplex
4290: 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72  Leave();.  retur
42a0: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54  n rc;.}../*.** T
42b0: 68 69 73 20 69 73 20 74 68 65 20 78 44 65 6c 65  his is the xDele
42c0: 74 65 20 6d 65 74 68 6f 64 20 75 73 65 64 20 66  te method used f
42d0: 6f 72 20 74 68 65 20 22 6d 75 6c 74 69 70 6c 65  or the "multiple
42e0: 78 22 20 56 46 53 2e 0a 2a 2a 20 49 74 20 61 74  x" VFS..** It at
42f0: 74 65 6d 70 74 73 20 74 6f 20 64 65 6c 65 74 65  tempts to delete
4300: 20 74 68 65 20 66 69 6c 65 6e 61 6d 65 20 73 70   the filename sp
4310: 65 63 69 66 69 65 64 2c 20 61 73 20 77 65 6c 6c  ecified, as well
4320: 0a 2a 2a 20 61 73 20 61 64 64 69 74 69 6f 6e 61  .** as additiona
4330: 6c 20 66 69 6c 65 73 20 77 69 74 68 20 74 68 65  l files with the
4340: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
4350: 58 5f 45 58 54 5f 46 4d 54 20 65 78 74 65 6e 73  X_EXT_FMT extens
4360: 69 6f 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ion..*/.static i
4370: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c 65  nt multiplexDele
4380: 74 65 28 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  te(.  sqlite3_vf
4390: 73 20 2a 70 56 66 73 2c 20 20 20 20 20 20 20 20  s *pVfs,        
43a0: 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65   /* The multiple
43b0: 78 20 56 46 53 20 2a 2f 0a 20 20 63 6f 6e 73 74  x VFS */.  const
43c0: 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c 20 20 20   char *zName,   
43d0: 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66        /* Name of
43e0: 20 66 69 6c 65 20 74 6f 20 64 65 6c 65 74 65 20   file to delete 
43f0: 2a 2f 0a 20 20 69 6e 74 20 73 79 6e 63 44 69 72  */.  int syncDir
4400: 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  .){.  sqlite3_vf
4410: 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d  s *pOrigVfs = gM
4420: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
4430: 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53  s;   /* Real VFS
4440: 20 2a 2f 0a 20 20 69 6e 74 20 72 63 20 3d 20 53   */.  int rc = S
4450: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
4460: 6e 4e 61 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65  nName = multiple
4470: 78 53 74 72 6c 65 6e 33 30 28 7a 4e 61 6d 65 29  xStrlen30(zName)
4480: 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 55 4e  ;.  int i;..  UN
4490: 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 70  USED_PARAMETER(p
44a0: 56 66 73 29 3b 0a 0a 20 20 6d 75 6c 74 69 70 6c  Vfs);..  multipl
44b0: 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 65 6d  exEnter();.  mem
44c0: 63 70 79 28 67 4d 75 6c 74 69 70 6c 65 78 2e 7a  cpy(gMultiplex.z
44d0: 4e 61 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61  Name, zName, nNa
44e0: 6d 65 2b 31 29 3b 0a 20 20 66 6f 72 28 69 3d 30  me+1);.  for(i=0
44f0: 3b 20 69 3c 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ; i<SQLITE_MULTI
4500: 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 3b  PLEX_MAX_CHUNKS;
4510: 20 69 2b 2b 29 7b 0a 20 20 20 20 69 6e 74 20 72   i++){.    int r
4520: 63 32 3b 0a 20 20 20 20 69 6e 74 20 65 78 69 73  c2;.    int exis
4530: 74 73 20 3d 20 30 3b 0a 20 20 20 20 69 66 28 20  ts = 0;.    if( 
4540: 69 20 29 7b 0a 23 69 66 64 65 66 20 53 51 4c 49  i ){.#ifdef SQLI
4550: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
4560: 5f 4f 56 57 52 0a 20 20 20 20 20 20 20 20 73 71  _OVWR.        sq
4570: 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 53  lite3_snprintf(S
4580: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
4590: 45 58 54 5f 53 5a 2b 31 2c 20 0a 20 20 20 20 20  EXT_SZ+1, .     
45a0: 20 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65         gMultiple
45b0: 78 2e 7a 4e 61 6d 65 2b 6e 4e 61 6d 65 2d 53 51  x.zName+nName-SQ
45c0: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
45d0: 58 54 5f 53 5a 2c 20 0a 20 20 20 20 20 20 20 20  XT_SZ, .        
45e0: 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49      SQLITE_MULTI
45f0: 50 4c 45 58 5f 45 58 54 5f 46 4d 54 2c 20 69 29  PLEX_EXT_FMT, i)
4600: 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20 20 20 20  ;.#else.        
4610: 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74 66  sqlite3_snprintf
4620: 28 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45  (SQLITE_MULTIPLE
4630: 58 5f 45 58 54 5f 53 5a 2b 31 2c 20 0a 20 20 20  X_EXT_SZ+1, .   
4640: 20 20 20 20 20 20 20 20 20 67 4d 75 6c 74 69 70           gMultip
4650: 6c 65 78 2e 7a 4e 61 6d 65 2b 6e 4e 61 6d 65 2c  lex.zName+nName,
4660: 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 53 51   .            SQ
4670: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
4680: 58 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6e 64  XT_FMT, i);.#end
4690: 69 66 0a 20 20 20 20 7d 0a 20 20 20 20 72 63 32  if.    }.    rc2
46a0: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63   = pOrigVfs->xAc
46b0: 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 67  cess(pOrigVfs, g
46c0: 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c  Multiplex.zName,
46d0: 20 0a 20 20 20 20 20 20 20 20 53 51 4c 49 54 45   .        SQLITE
46e0: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20  _ACCESS_EXISTS, 
46f0: 26 65 78 69 73 74 73 29 3b 0a 20 20 20 20 69 66  &exists);.    if
4700: 28 20 72 63 32 3d 3d 53 51 4c 49 54 45 5f 4f 4b  ( rc2==SQLITE_OK
4710: 20 26 26 20 65 78 69 73 74 73 20 29 7b 0a 20 20   && exists ){.  
4720: 20 20 20 20 2f 2a 20 69 66 20 69 74 20 65 78 69      /* if it exi
4730: 73 74 73 2c 20 64 65 6c 65 74 65 20 69 74 20 2a  sts, delete it *
4740: 2f 0a 20 20 20 20 20 20 72 63 32 20 3d 20 70 4f  /.      rc2 = pO
4750: 72 69 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28  rigVfs->xDelete(
4760: 70 4f 72 69 67 56 66 73 2c 20 67 4d 75 6c 74 69  pOrigVfs, gMulti
4770: 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20 73 79 6e 63  plex.zName, sync
4780: 44 69 72 29 3b 0a 20 20 20 20 20 20 69 66 28 20  Dir);.      if( 
4790: 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29  rc2!=SQLITE_OK )
47a0: 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20 20 7d   rc = rc2;.    }
47b0: 65 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20 73  else{.      /* s
47c0: 74 6f 70 20 61 74 20 66 69 72 73 74 20 22 67 61  top at first "ga
47d0: 70 22 20 2a 2f 0a 20 20 20 20 20 20 62 72 65 61  p" */.      brea
47e0: 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d  k;.    }.  }.  m
47f0: 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b  ultiplexLeave();
4800: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
4810: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
4820: 69 70 6c 65 78 41 63 63 65 73 73 28 73 71 6c 69  iplexAccess(sqli
4830: 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e 73  te3_vfs *a, cons
4840: 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74 20 63  t char *b, int c
4850: 2c 20 69 6e 74 20 2a 64 29 7b 0a 20 20 72 65 74  , int *d){.  ret
4860: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
4870: 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73  OrigVfs->xAccess
4880: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
4890: 67 56 66 73 2c 20 62 2c 20 63 2c 20 64 29 3b 0a  gVfs, b, c, d);.
48a0: 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  }.static int mul
48b0: 74 69 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61  tiplexFullPathna
48c0: 6d 65 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  me(sqlite3_vfs *
48d0: 61 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 62  a, const char *b
48e0: 2c 20 69 6e 74 20 63 2c 20 63 68 61 72 20 2a 64  , int c, char *d
48f0: 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c  ){.  return gMul
4900: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d  tiplex.pOrigVfs-
4910: 3e 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 67  >xFullPathname(g
4920: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4930: 66 73 2c 20 62 2c 20 63 2c 20 64 29 3b 0a 7d 0a  fs, b, c, d);.}.
4940: 73 74 61 74 69 63 20 76 6f 69 64 20 2a 6d 75 6c  static void *mul
4950: 74 69 70 6c 65 78 44 6c 4f 70 65 6e 28 73 71 6c  tiplexDlOpen(sql
4960: 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e  ite3_vfs *a, con
4970: 73 74 20 63 68 61 72 20 2a 62 29 7b 0a 20 20 72  st char *b){.  r
4980: 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78  eturn gMultiplex
4990: 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 4f 70  .pOrigVfs->xDlOp
49a0: 65 6e 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  en(gMultiplex.pO
49b0: 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74  rigVfs, b);.}.st
49c0: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
49d0: 6c 65 78 44 6c 45 72 72 6f 72 28 73 71 6c 69 74  lexDlError(sqlit
49e0: 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62  e3_vfs *a, int b
49f0: 2c 20 63 68 61 72 20 2a 63 29 7b 0a 20 20 67 4d  , char *c){.  gM
4a00: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
4a10: 73 2d 3e 78 44 6c 45 72 72 6f 72 28 67 4d 75 6c  s->xDlError(gMul
4a20: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
4a30: 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63   b, c);.}.static
4a40: 20 76 6f 69 64 20 28 2a 6d 75 6c 74 69 70 6c 65   void (*multiple
4a50: 78 44 6c 53 79 6d 28 73 71 6c 69 74 65 33 5f 76  xDlSym(sqlite3_v
4a60: 66 73 20 2a 61 2c 20 76 6f 69 64 20 2a 62 2c 20  fs *a, void *b, 
4a70: 63 6f 6e 73 74 20 63 68 61 72 20 2a 63 29 29 28  const char *c))(
4a80: 76 6f 69 64 29 7b 0a 20 20 72 65 74 75 72 6e 20  void){.  return 
4a90: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4aa0: 56 66 73 2d 3e 78 44 6c 53 79 6d 28 67 4d 75 6c  Vfs->xDlSym(gMul
4ab0: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
4ac0: 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63   b, c);.}.static
4ad0: 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 44   void multiplexD
4ae0: 6c 43 6c 6f 73 65 28 73 71 6c 69 74 65 33 5f 76  lClose(sqlite3_v
4af0: 66 73 20 2a 61 2c 20 76 6f 69 64 20 2a 62 29 7b  fs *a, void *b){
4b00: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  .  gMultiplex.pO
4b10: 72 69 67 56 66 73 2d 3e 78 44 6c 43 6c 6f 73 65  rigVfs->xDlClose
4b20: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
4b30: 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74  gVfs, b);.}.stat
4b40: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
4b50: 52 61 6e 64 6f 6d 6e 65 73 73 28 73 71 6c 69 74  Randomness(sqlit
4b60: 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62  e3_vfs *a, int b
4b70: 2c 20 63 68 61 72 20 2a 63 29 7b 0a 20 20 72 65  , char *c){.  re
4b80: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
4b90: 70 4f 72 69 67 56 66 73 2d 3e 78 52 61 6e 64 6f  pOrigVfs->xRando
4ba0: 6d 6e 65 73 73 28 67 4d 75 6c 74 69 70 6c 65 78  mness(gMultiplex
4bb0: 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29  .pOrigVfs, b, c)
4bc0: 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  ;.}.static int m
4bd0: 75 6c 74 69 70 6c 65 78 53 6c 65 65 70 28 73 71  ultiplexSleep(sq
4be0: 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e  lite3_vfs *a, in
4bf0: 74 20 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67  t b){.  return g
4c00: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4c10: 66 73 2d 3e 78 53 6c 65 65 70 28 67 4d 75 6c 74  fs->xSleep(gMult
4c20: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
4c30: 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  b);.}.static int
4c40: 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e   multiplexCurren
4c50: 74 54 69 6d 65 28 73 71 6c 69 74 65 33 5f 76 66  tTime(sqlite3_vf
4c60: 73 20 2a 61 2c 20 64 6f 75 62 6c 65 20 2a 62 29  s *a, double *b)
4c70: 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74  {.  return gMult
4c80: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e  iplex.pOrigVfs->
4c90: 78 43 75 72 72 65 6e 74 54 69 6d 65 28 67 4d 75  xCurrentTime(gMu
4ca0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
4cb0: 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69  , b);.}.static i
4cc0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c  nt multiplexGetL
4cd0: 61 73 74 45 72 72 6f 72 28 73 71 6c 69 74 65 33  astError(sqlite3
4ce0: 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20  _vfs *a, int b, 
4cf0: 63 68 61 72 20 2a 63 29 7b 0a 20 20 72 65 74 75  char *c){.  retu
4d00: 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  rn gMultiplex.pO
4d10: 72 69 67 56 66 73 2d 3e 78 47 65 74 4c 61 73 74  rigVfs->xGetLast
4d20: 45 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65 78  Error(gMultiplex
4d30: 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29  .pOrigVfs, b, c)
4d40: 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  ;.}.static int m
4d50: 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e 74 54  ultiplexCurrentT
4d60: 69 6d 65 49 6e 74 36 34 28 73 71 6c 69 74 65 33  imeInt64(sqlite3
4d70: 5f 76 66 73 20 2a 61 2c 20 73 71 6c 69 74 65 33  _vfs *a, sqlite3
4d80: 5f 69 6e 74 36 34 20 2a 62 29 7b 0a 20 20 72 65  _int64 *b){.  re
4d90: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
4da0: 70 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72 65  pOrigVfs->xCurre
4db0: 6e 74 54 69 6d 65 49 6e 74 36 34 28 67 4d 75 6c  ntTimeInt64(gMul
4dc0: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
4dd0: 20 62 29 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a   b);.}../*******
4de0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4df0: 2a 20 49 2f 4f 20 4d 65 74 68 6f 64 20 57 72 61  * I/O Method Wra
4e00: 70 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ppers **********
4e10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4e20: 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 78 43 6c 6f 73  *****/../* xClos
4e30: 65 20 72 65 71 75 65 73 74 73 20 67 65 74 20 70  e requests get p
4e40: 61 73 73 65 64 20 74 68 72 6f 75 67 68 20 74 6f  assed through to
4e50: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
4e60: 53 2e 0a 2a 2a 20 57 65 20 6c 6f 6f 70 20 6f 76  S..** We loop ov
4e70: 65 72 20 61 6c 6c 20 6f 70 65 6e 20 63 68 75 6e  er all open chun
4e80: 6b 20 68 61 6e 64 6c 65 73 20 61 6e 64 20 63 6c  k handles and cl
4e90: 6f 73 65 20 74 68 65 6d 2e 0a 2a 2a 20 54 68 65  ose them..** The
4ea0: 20 67 72 6f 75 70 20 73 74 72 75 63 74 75 72 65   group structure
4eb0: 20 66 6f 72 20 74 68 69 73 20 66 69 6c 65 20 69   for this file i
4ec0: 73 20 75 6e 6c 69 6e 6b 65 64 20 66 72 6f 6d 20  s unlinked from 
4ed0: 0a 2a 2a 20 6f 75 72 20 6c 69 73 74 20 6f 66 20  .** our list of 
4ee0: 67 72 6f 75 70 73 20 61 6e 64 20 66 72 65 65 64  groups and freed
4ef0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
4f00: 6d 75 6c 74 69 70 6c 65 78 43 6c 6f 73 65 28 73  multiplexClose(s
4f10: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
4f20: 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  nn){.  multiplex
4f30: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
4f40: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
4f50: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
4f60: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
4f70: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
4f80: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69  = SQLITE_OK;.  i
4f90: 6e 74 20 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  nt i;.  multiple
4fa0: 78 45 6e 74 65 72 28 29 3b 0a 20 20 2f 2a 20 63  xEnter();.  /* c
4fb0: 6c 6f 73 65 20 61 6e 79 20 6f 70 65 6e 20 68 61  lose any open ha
4fc0: 6e 64 6c 65 73 20 2a 2f 0a 20 20 66 6f 72 28 69  ndles */.  for(i
4fd0: 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 4d  =0; i<pGroup->nM
4fe0: 61 78 43 68 75 6e 6b 73 3b 20 69 2b 2b 29 7b 0a  axChunks; i++){.
4ff0: 20 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e      if( pGroup->
5000: 62 4f 70 65 6e 5b 69 5d 20 29 7b 0a 20 20 20 20  bOpen[i] ){.    
5010: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
5020: 70 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75  pSubOpen = pGrou
5030: 70 2d 3e 70 52 65 61 6c 5b 69 5d 3b 0a 20 20 20  p->pReal[i];.   
5040: 20 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53 75     int rc2 = pSu
5050: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
5060: 3e 78 43 6c 6f 73 65 28 70 53 75 62 4f 70 65 6e  >xClose(pSubOpen
5070: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 32  );.      if( rc2
5080: 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63  !=SQLITE_OK ) rc
5090: 20 3d 20 72 63 32 3b 0a 20 20 20 20 20 20 70 47   = rc2;.      pG
50a0: 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 5d 20 3d  roup->bOpen[i] =
50b0: 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20   0;.    }.  }.  
50c0: 2f 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20 6c  /* remove from l
50d0: 69 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20 20  inked list */.  
50e0: 69 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78  if( pGroup->pNex
50f0: 74 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78  t ) pGroup->pNex
5100: 74 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f 75  t->pPrev = pGrou
5110: 70 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28 20  p->pPrev;.  if( 
5120: 70 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29 7b  pGroup->pPrev ){
5130: 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50 72  .    pGroup->pPr
5140: 65 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72 6f  ev->pNext = pGro
5150: 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c  up->pNext;.  }el
5160: 73 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70 6c  se{.    gMultipl
5170: 65 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72  ex.pGroups = pGr
5180: 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a  oup->pNext;.  }.
5190: 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70    sqlite3_free(p
51a0: 47 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69 70  Group);.  multip
51b0: 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65  lexLeave();.  re
51c0: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50  turn rc;.}../* P
51d0: 61 73 73 20 78 52 65 61 64 20 72 65 71 75 65 73  ass xRead reques
51e0: 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f  ts thru to the o
51f0: 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65  riginal VFS afte
5200: 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67  r.** determining
5210: 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68 75   the correct chu
5220: 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e  nk to operate on
5230: 2e 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72 65  ..** Break up re
5240: 61 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b  ads across chunk
5250: 20 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a   boundaries..*/.
5260: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
5270: 70 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c 69  plexRead(.  sqli
5280: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
5290: 0a 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a 20  .  void *pBuf,. 
52a0: 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71 6c   int iAmt,.  sql
52b0: 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73 74  ite3_int64 iOfst
52c0: 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  .){.  multiplexC
52d0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
52e0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
52f0: 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70    multiplexGroup
5300: 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47   *pGroup = p->pG
5310: 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d  roup;.  int rc =
5320: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75   SQLITE_OK;.  mu
5330: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
5340: 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62    if( !pGroup->b
5350: 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73  Enabled ){.    s
5360: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
5370: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
5380: 78 53 75 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26  xSubOpen(p, 0, &
5390: 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 69  rc, NULL);.    i
53a0: 66 28 20 21 70 53 75 62 4f 70 65 6e 20 29 7b 0a  f( !pSubOpen ){.
53b0: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
53c0: 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b 0a 20 20  E_IOERR_READ;.  
53d0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72    }else{.      r
53e0: 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  c = pSubOpen->pM
53f0: 65 74 68 6f 64 73 2d 3e 78 52 65 61 64 28 70 53  ethods->xRead(pS
5400: 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41  ubOpen, pBuf, iA
5410: 6d 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20 20  mt, iOfst);.    
5420: 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 77  }.  }else{.    w
5430: 68 69 6c 65 28 20 69 41 6d 74 20 3e 20 30 20 29  hile( iAmt > 0 )
5440: 7b 0a 20 20 20 20 20 20 69 6e 74 20 69 20 3d 20  {.      int i = 
5450: 28 69 6e 74 29 28 69 4f 66 73 74 20 2f 20 70 47  (int)(iOfst / pG
5460: 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53 69 7a 65  roup->nChunkSize
5470: 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33  );.      sqlite3
5480: 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20  _file *pSubOpen 
5490: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
54a0: 65 6e 28 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55  en(p, i, &rc, NU
54b0: 4c 4c 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70  LL);.      if( p
54c0: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20  SubOpen ){.     
54d0: 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28     int extra = (
54e0: 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70 47  (int)(iOfst % pG
54f0: 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53 69 7a 65  roup->nChunkSize
5500: 29 20 2b 20 69 41 6d 74 29 20 2d 0a 20 20 20 20  ) + iAmt) -.    
5510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5540: 20 20 20 20 70 47 72 6f 75 70 2d 3e 6e 43 68 75      pGroup->nChu
5550: 6e 6b 53 69 7a 65 3b 0a 20 20 20 20 20 20 20 20  nkSize;.        
5560: 69 66 28 20 65 78 74 72 61 3c 30 20 29 20 65 78  if( extra<0 ) ex
5570: 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  tra = 0;.       
5580: 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61 3b 0a   iAmt -= extra;.
5590: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
55a0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
55b0: 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65 6e 2c  >xRead(pSubOpen,
55c0: 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20 20 20   pBuf, iAmt,.   
55d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
55e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
55f0: 20 20 20 20 69 4f 66 73 74 20 25 20 70 47 72 6f      iOfst % pGro
5600: 75 70 2d 3e 6e 43 68 75 6e 6b 53 69 7a 65 29 3b  up->nChunkSize);
5610: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 21  .        if( rc!
5620: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65  =SQLITE_OK ) bre
5630: 61 6b 3b 0a 20 20 20 20 20 20 20 20 70 42 75 66  ak;.        pBuf
5640: 20 3d 20 28 63 68 61 72 20 2a 29 70 42 75 66 20   = (char *)pBuf 
5650: 2b 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20  + iAmt;.        
5660: 69 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20  iOfst += iAmt;. 
5670: 20 20 20 20 20 20 20 69 41 6d 74 20 3d 20 65 78         iAmt = ex
5680: 74 72 61 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65  tra;.      }else
5690: 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53  {.        rc = S
56a0: 51 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45 41 44  QLITE_IOERR_READ
56b0: 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b  ;.        break;
56c0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
56d0: 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65   }.  multiplexLe
56e0: 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20  ave();.  return 
56f0: 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78  rc;.}../* Pass x
5700: 57 72 69 74 65 20 72 65 71 75 65 73 74 73 20 74  Write requests t
5710: 68 72 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69  hru to the origi
5720: 6e 61 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a  nal VFS after.**
5730: 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65   determining the
5740: 20 63 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74   correct chunk t
5750: 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a  o operate on..**
5760: 20 42 72 65 61 6b 20 75 70 20 77 72 69 74 65 73   Break up writes
5770: 20 61 63 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f   across chunk bo
5780: 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61  undaries..*/.sta
5790: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
57a0: 78 57 72 69 74 65 28 0a 20 20 73 71 6c 69 74 65  xWrite(.  sqlite
57b0: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20  3_file *pConn,. 
57c0: 20 63 6f 6e 73 74 20 76 6f 69 64 20 2a 70 42 75   const void *pBu
57d0: 66 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20  f,.  int iAmt,. 
57e0: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 69   sqlite3_int64 i
57f0: 4f 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70  Ofst.){.  multip
5800: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
5810: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
5820: 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47  nn;.  multiplexG
5830: 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70  roup *pGroup = p
5840: 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20  ->pGroup;.  int 
5850: 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  rc = SQLITE_OK;.
5860: 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72    multiplexEnter
5870: 28 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75  ();.  if( !pGrou
5880: 70 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20  p->bEnabled ){. 
5890: 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20     sqlite3_file 
58a0: 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74  *pSubOpen = mult
58b0: 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c 20  iplexSubOpen(p, 
58c0: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20  0, &rc, NULL);. 
58d0: 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 3d     if( pSubOpen=
58e0: 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  =0 ){.      rc =
58f0: 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 57 52   SQLITE_IOERR_WR
5900: 49 54 45 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  ITE;.    }else{.
5910: 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f        rc = pSubO
5920: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
5930: 57 72 69 74 65 28 70 53 75 62 4f 70 65 6e 2c 20  Write(pSubOpen, 
5940: 70 42 75 66 2c 20 69 41 6d 74 2c 20 69 4f 66 73  pBuf, iAmt, iOfs
5950: 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73  t);.    }.  }els
5960: 65 7b 0a 20 20 20 20 77 68 69 6c 65 28 20 69 41  e{.    while( iA
5970: 6d 74 20 3e 20 30 20 29 7b 0a 20 20 20 20 20 20  mt > 0 ){.      
5980: 69 6e 74 20 69 20 3d 20 28 69 6e 74 29 28 69 4f  int i = (int)(iO
5990: 66 73 74 20 2f 20 70 47 72 6f 75 70 2d 3e 6e 43  fst / pGroup->nC
59a0: 68 75 6e 6b 53 69 7a 65 29 3b 0a 20 20 20 20 20  hunkSize);.     
59b0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
59c0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
59d0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c 20 69 2c  lexSubOpen(p, i,
59e0: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20   &rc, NULL);.   
59f0: 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20     if( pSubOpen 
5a00: 29 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 65  ){.        int e
5a10: 78 74 72 61 20 3d 20 28 28 69 6e 74 29 28 69 4f  xtra = ((int)(iO
5a20: 66 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 6e 43  fst % pGroup->nC
5a30: 68 75 6e 6b 53 69 7a 65 29 20 2b 20 69 41 6d 74  hunkSize) + iAmt
5a40: 29 20 2d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ) -.            
5a50: 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e          pGroup->
5a60: 6e 43 68 75 6e 6b 53 69 7a 65 3b 0a 20 20 20 20  nChunkSize;.    
5a70: 20 20 20 20 69 66 28 20 65 78 74 72 61 3c 30 20      if( extra<0 
5a80: 29 20 65 78 74 72 61 20 3d 20 30 3b 0a 20 20 20  ) extra = 0;.   
5a90: 20 20 20 20 20 69 41 6d 74 20 2d 3d 20 65 78 74       iAmt -= ext
5aa0: 72 61 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d  ra;.        rc =
5ab0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
5ac0: 6f 64 73 2d 3e 78 57 72 69 74 65 28 70 53 75 62  ods->xWrite(pSub
5ad0: 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74  Open, pBuf, iAmt
5ae0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
5af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b00: 20 20 20 20 20 20 20 20 20 20 69 4f 66 73 74 20            iOfst 
5b10: 25 20 70 47 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b  % pGroup->nChunk
5b20: 53 69 7a 65 29 3b 0a 20 20 20 20 20 20 20 20 69  Size);.        i
5b30: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
5b40: 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20   ) break;.      
5b50: 20 20 70 42 75 66 20 3d 20 28 63 68 61 72 20 2a    pBuf = (char *
5b60: 29 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20  )pBuf + iAmt;.  
5b70: 20 20 20 20 20 20 69 4f 66 73 74 20 2b 3d 20 69        iOfst += i
5b80: 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 41 6d  Amt;.        iAm
5b90: 74 20 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20  t = extra;.     
5ba0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
5bb0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
5bc0: 52 5f 57 52 49 54 45 3b 0a 20 20 20 20 20 20 20  R_WRITE;.       
5bd0: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a   break;.      }.
5be0: 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74      }.  }.  mult
5bf0: 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20  iplexLeave();.  
5c00: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
5c10: 20 50 61 73 73 20 78 54 72 75 6e 63 61 74 65 20   Pass xTruncate 
5c20: 72 65 71 75 65 73 74 73 20 74 68 72 75 20 74 6f  requests thru to
5c30: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
5c40: 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72  S after.** deter
5c50: 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65  mining the corre
5c60: 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72  ct chunk to oper
5c70: 61 74 65 20 6f 6e 2e 20 20 44 65 6c 65 74 65 20  ate on.  Delete 
5c80: 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b 73 20 61 62  any.** chunks ab
5c90: 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61 74 65  ove the truncate
5ca0: 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74 61 74 69 63   mark..*/.static
5cb0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 54 72   int multiplexTr
5cc0: 75 6e 63 61 74 65 28 73 71 6c 69 74 65 33 5f 66  uncate(sqlite3_f
5cd0: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71 6c 69  ile *pConn, sqli
5ce0: 74 65 33 5f 69 6e 74 36 34 20 73 69 7a 65 29 7b  te3_int64 size){
5cf0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
5d00: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
5d10: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d  Conn*)pConn;.  m
5d20: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
5d30: 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75  Group = p->pGrou
5d40: 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  p;.  int rc = SQ
5d50: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69  LITE_OK;.  multi
5d60: 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 69  plexEnter();.  i
5d70: 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61  f( !pGroup->bEna
5d80: 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71 6c 69  bled ){.    sqli
5d90: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
5da0: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
5db0: 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c  bOpen(p, 0, &rc,
5dc0: 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20   NULL);.    if( 
5dd0: 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20  pSubOpen==0 ){. 
5de0: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
5df0: 5f 49 4f 45 52 52 5f 54 52 55 4e 43 41 54 45 3b  _IOERR_TRUNCATE;
5e00: 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  .    }else{.    
5e10: 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d    rc = pSubOpen-
5e20: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 54 72 75 6e  >pMethods->xTrun
5e30: 63 61 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 73  cate(pSubOpen, s
5e40: 69 7a 65 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65  ize);.    }.  }e
5e50: 6c 73 65 7b 0a 20 20 20 20 69 6e 74 20 72 63 32  lse{.    int rc2
5e60: 3b 0a 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20  ;.    int i;.   
5e70: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
5e80: 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 73 71 6c  SubOpen;.    sql
5e90: 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56  ite3_vfs *pOrigV
5ea0: 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e  fs = gMultiplex.
5eb0: 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a 20 52  pOrigVfs;   /* R
5ec0: 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 20 20 6d  eal VFS */.    m
5ed0: 65 6d 63 70 79 28 67 4d 75 6c 74 69 70 6c 65 78  emcpy(gMultiplex
5ee0: 2e 7a 4e 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e  .zName, pGroup->
5ef0: 7a 4e 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 6e  zName, pGroup->n
5f00: 4e 61 6d 65 2b 31 29 3b 0a 20 20 20 20 2f 2a 20  Name+1);.    /* 
5f10: 64 65 6c 65 74 65 20 74 68 65 20 63 68 75 6e 6b  delete the chunk
5f20: 73 20 61 62 6f 76 65 20 74 68 65 20 74 72 75 6e  s above the trun
5f30: 63 61 74 65 20 6c 69 6d 69 74 20 2a 2f 0a 20 20  cate limit */.  
5f40: 20 20 66 6f 72 28 69 3d 28 69 6e 74 29 28 73 69    for(i=(int)(si
5f50: 7a 65 20 2f 20 70 47 72 6f 75 70 2d 3e 6e 43 68  ze / pGroup->nCh
5f60: 75 6e 6b 53 69 7a 65 29 2b 31 3b 20 69 3c 70 47  unkSize)+1; i<pG
5f70: 72 6f 75 70 2d 3e 6e 4d 61 78 43 68 75 6e 6b 73  roup->nMaxChunks
5f80: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 2f 2a  ; i++){.      /*
5f90: 20 63 6c 6f 73 65 20 61 6e 79 20 6f 70 65 6e 20   close any open 
5fa0: 63 68 75 6e 6b 73 20 62 65 66 6f 72 65 20 64 65  chunks before de
5fb0: 6c 65 74 69 6e 67 20 74 68 65 6d 20 2a 2f 0a 20  leting them */. 
5fc0: 20 20 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d       if( pGroup-
5fd0: 3e 62 4f 70 65 6e 5b 69 5d 20 29 7b 0a 20 20 20  >bOpen[i] ){.   
5fe0: 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20       pSubOpen = 
5ff0: 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c 5b 69 5d  pGroup->pReal[i]
6000: 3b 0a 20 20 20 20 20 20 20 20 72 63 32 20 3d 20  ;.        rc2 = 
6010: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
6020: 64 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75 62 4f  ds->xClose(pSubO
6030: 70 65 6e 29 3b 0a 20 20 20 20 20 20 20 20 69 66  pen);.        if
6040: 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b  ( rc2!=SQLITE_OK
6050: 20 29 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49   ) rc = SQLITE_I
6060: 4f 45 52 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20  OERR_TRUNCATE;. 
6070: 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 62         pGroup->b
6080: 4f 70 65 6e 5b 69 5d 20 3d 20 30 3b 0a 20 20 20  Open[i] = 0;.   
6090: 20 20 20 7d 0a 23 69 66 64 65 66 20 53 51 4c 49     }.#ifdef SQLI
60a0: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
60b0: 5f 4f 56 57 52 0a 20 20 20 20 20 20 73 71 6c 69  _OVWR.      sqli
60c0: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c  te3_snprintf(SQL
60d0: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
60e0: 54 5f 53 5a 2b 31 2c 20 0a 20 20 20 20 20 20 20  T_SZ+1, .       
60f0: 20 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e     gMultiplex.zN
6100: 61 6d 65 2b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  ame+pGroup->nNam
6110: 65 2d 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  e-SQLITE_MULTIPL
6120: 45 58 5f 45 58 54 5f 53 5a 2c 20 0a 20 20 20 20  EX_EXT_SZ, .    
6130: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c        SQLITE_MUL
6140: 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54 2c 20  TIPLEX_EXT_FMT, 
6150: 69 29 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20 20  i);.#else.      
6160: 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74 66  sqlite3_snprintf
6170: 28 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45  (SQLITE_MULTIPLE
6180: 58 5f 45 58 54 5f 53 5a 2b 31 2c 20 0a 20 20 20  X_EXT_SZ+1, .   
6190: 20 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65         gMultiple
61a0: 78 2e 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e  x.zName+pGroup->
61b0: 6e 4e 61 6d 65 2c 20 0a 20 20 20 20 20 20 20 20  nName, .        
61c0: 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c    SQLITE_MULTIPL
61d0: 45 58 5f 45 58 54 5f 46 4d 54 2c 20 69 29 3b 0a  EX_EXT_FMT, i);.
61e0: 23 65 6e 64 69 66 0a 20 20 20 20 20 20 72 63 32  #endif.      rc2
61f0: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65   = pOrigVfs->xDe
6200: 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 67  lete(pOrigVfs, g
6210: 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c  Multiplex.zName,
6220: 20 30 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72   0);.      if( r
6230: 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20  c2!=SQLITE_OK ) 
6240: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
6250: 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20 20  R_TRUNCATE;.    
6260: 7d 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d  }.    pSubOpen =
6270: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
6280: 6e 28 70 2c 20 28 69 6e 74 29 28 73 69 7a 65 2f  n(p, (int)(size/
6290: 70 47 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53 69  pGroup->nChunkSi
62a0: 7a 65 29 2c 20 26 72 63 32 2c 20 4e 55 4c 4c 29  ze), &rc2, NULL)
62b0: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
62c0: 65 6e 20 29 7b 0a 20 20 20 20 20 20 72 63 32 20  en ){.      rc2 
62d0: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
62e0: 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28  hods->xTruncate(
62f0: 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 20 25  pSubOpen, size %
6300: 20 70 47 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53   pGroup->nChunkS
6310: 69 7a 65 29 3b 0a 20 20 20 20 20 20 69 66 28 20  ize);.      if( 
6320: 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29  rc2!=SQLITE_OK )
6330: 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20 20 7d   rc = rc2;.    }
6340: 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d  else{.      rc =
6350: 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 54 52   SQLITE_IOERR_TR
6360: 55 4e 43 41 54 45 3b 0a 20 20 20 20 7d 0a 20 20  UNCATE;.    }.  
6370: 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  }.  multiplexLea
6380: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
6390: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53  c;.}../* Pass xS
63a0: 79 6e 63 20 72 65 71 75 65 73 74 73 20 74 68 72  ync requests thr
63b0: 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67  ough to the orig
63c0: 69 6e 61 6c 20 56 46 53 20 77 69 74 68 6f 75 74  inal VFS without
63d0: 20 63 68 61 6e 67 65 0a 2a 2f 0a 73 74 61 74 69   change.*/.stati
63e0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53  c int multiplexS
63f0: 79 6e 63 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ync(sqlite3_file
6400: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 66 6c 61   *pConn, int fla
6410: 67 73 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  gs){.  multiplex
6420: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
6430: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
6440: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
6450: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
6460: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
6470: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69  = SQLITE_OK;.  i
6480: 6e 74 20 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  nt i;.  multiple
6490: 78 45 6e 74 65 72 28 29 3b 0a 20 20 66 6f 72 28  xEnter();.  for(
64a0: 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e  i=0; i<pGroup->n
64b0: 4d 61 78 43 68 75 6e 6b 73 3b 20 69 2b 2b 29 7b  MaxChunks; i++){
64c0: 0a 20 20 20 20 2f 2a 20 69 66 20 77 65 20 64 6f  .    /* if we do
64d0: 6e 27 74 20 68 61 76 65 20 69 74 20 6f 70 65 6e  n't have it open
64e0: 2c 20 77 65 20 64 6f 6e 27 74 20 6e 65 65 64 20  , we don't need 
64f0: 74 6f 20 73 79 6e 63 20 69 74 20 2a 2f 0a 20 20  to sync it */.  
6500: 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 62 4f    if( pGroup->bO
6510: 70 65 6e 5b 69 5d 20 29 7b 0a 20 20 20 20 20 20  pen[i] ){.      
6520: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
6530: 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d  ubOpen = pGroup-
6540: 3e 70 52 65 61 6c 5b 69 5d 3b 0a 20 20 20 20 20  >pReal[i];.     
6550: 20 69 6e 74 20 72 63 32 20 3d 20 70 53 75 62 4f   int rc2 = pSubO
6560: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
6570: 53 79 6e 63 28 70 53 75 62 4f 70 65 6e 2c 20 66  Sync(pSubOpen, f
6580: 6c 61 67 73 29 3b 0a 20 20 20 20 20 20 69 66 28  lags);.      if(
6590: 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20   rc2!=SQLITE_OK 
65a0: 29 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20 20  ) rc = rc2;.    
65b0: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
65c0: 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75  xLeave();.  retu
65d0: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
65e0: 73 20 78 46 69 6c 65 53 69 7a 65 20 72 65 71 75  s xFileSize requ
65f0: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
6600: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
6610: 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74 65 20 74  ..** Aggregate t
6620: 68 65 20 73 69 7a 65 20 6f 66 20 61 6c 6c 20 74  he size of all t
6630: 68 65 20 63 68 75 6e 6b 73 20 62 65 66 6f 72 65  he chunks before
6640: 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a 2f 0a 73   returning..*/.s
6650: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6660: 6c 65 78 46 69 6c 65 53 69 7a 65 28 73 71 6c 69  lexFileSize(sqli
6670: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
6680: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 2a   sqlite3_int64 *
6690: 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c 74 69 70  pSize){.  multip
66a0: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
66b0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
66c0: 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47  nn;.  multiplexG
66d0: 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70  roup *pGroup = p
66e0: 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20  ->pGroup;.  int 
66f0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  rc = SQLITE_OK;.
6700: 20 20 69 6e 74 20 72 63 32 3b 0a 20 20 69 6e 74    int rc2;.  int
6710: 20 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45   i;.  multiplexE
6720: 6e 74 65 72 28 29 3b 0a 20 20 69 66 28 20 21 70  nter();.  if( !p
6730: 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20  Group->bEnabled 
6740: 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66  ){.    sqlite3_f
6750: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
6760: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
6770: 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  (p, 0, &rc, NULL
6780: 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f  );.    if( pSubO
6790: 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  pen==0 ){.      
67a0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
67b0: 52 5f 46 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c  R_FSTAT;.    }el
67c0: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
67d0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
67e0: 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70 53 75  s->xFileSize(pSu
67f0: 62 4f 70 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20  bOpen, pSize);. 
6800: 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20     }.  }else{.  
6810: 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20    *pSize = 0;.  
6820: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 47 72    for(i=0; i<pGr
6830: 6f 75 70 2d 3e 6e 4d 61 78 43 68 75 6e 6b 73 3b  oup->nMaxChunks;
6840: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 73 71 6c   i++){.      sql
6850: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
6860: 70 65 6e 20 3d 20 4e 55 4c 4c 3b 0a 20 20 20 20  pen = NULL;.    
6870: 20 20 2f 2a 20 69 66 20 6e 6f 74 20 6f 70 65 6e    /* if not open
6880: 65 64 20 61 6c 72 65 61 64 79 2c 20 63 68 65 63  ed already, chec
6890: 6b 20 74 6f 20 73 65 65 20 69 66 20 74 68 65 20  k to see if the 
68a0: 63 68 75 6e 6b 20 65 78 69 73 74 73 20 2a 2f 0a  chunk exists */.
68b0: 20 20 20 20 20 20 69 66 28 20 70 47 72 6f 75 70        if( pGroup
68c0: 2d 3e 62 4f 70 65 6e 5b 69 5d 20 29 7b 0a 20 20  ->bOpen[i] ){.  
68d0: 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d        pSubOpen =
68e0: 20 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c 5b 69   pGroup->pReal[i
68f0: 5d 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a  ];.      }else{.
6900: 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f          sqlite3_
6910: 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20  vfs *pOrigVfs = 
6920: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
6930: 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20 56  Vfs;   /* Real V
6940: 46 53 20 2a 2f 0a 20 20 20 20 20 20 20 20 69 6e  FS */.        in
6950: 74 20 65 78 69 73 74 73 20 3d 20 30 3b 0a 20 20  t exists = 0;.  
6960: 20 20 20 20 20 20 6d 65 6d 63 70 79 28 67 4d 75        memcpy(gMu
6970: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20 70  ltiplex.zName, p
6980: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 70 47  Group->zName, pG
6990: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2b 31 29 3b 0a  roup->nName+1);.
69a0: 20 20 20 20 20 20 20 20 69 66 28 20 69 20 29 7b          if( i ){
69b0: 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f 4d  .#ifdef SQLITE_M
69c0: 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 4f 56 57  ULTIPLEX_EXT_OVW
69d0: 52 0a 20 20 20 20 20 20 20 20 20 20 73 71 6c 69  R.          sqli
69e0: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c  te3_snprintf(SQL
69f0: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
6a00: 54 5f 53 5a 2b 31 2c 20 0a 20 20 20 20 20 20 20  T_SZ+1, .       
6a10: 20 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65         gMultiple
6a20: 78 2e 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e  x.zName+pGroup->
6a30: 6e 4e 61 6d 65 2d 53 51 4c 49 54 45 5f 4d 55 4c  nName-SQLITE_MUL
6a40: 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a 2c 20 0a  TIPLEX_EXT_SZ, .
6a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 53 51                SQ
6a60: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
6a70: 58 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6c 73  XT_FMT, i);.#els
6a80: 65 0a 20 20 20 20 20 20 20 20 20 20 73 71 6c 69  e.          sqli
6a90: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c  te3_snprintf(SQL
6aa0: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
6ab0: 54 5f 53 5a 2b 31 2c 20 0a 20 20 20 20 20 20 20  T_SZ+1, .       
6ac0: 20 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65         gMultiple
6ad0: 78 2e 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e  x.zName+pGroup->
6ae0: 6e 4e 61 6d 65 2c 20 0a 20 20 20 20 20 20 20 20  nName, .        
6af0: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c        SQLITE_MUL
6b00: 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54 2c 20  TIPLEX_EXT_FMT, 
6b10: 69 29 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20  i);.#endif.     
6b20: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 72 63 32     }.        rc2
6b30: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63   = pOrigVfs->xAc
6b40: 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 67  cess(pOrigVfs, g
6b50: 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c  Multiplex.zName,
6b60: 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 53 51   .            SQ
6b70: 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49 53  LITE_ACCESS_EXIS
6b80: 54 53 2c 20 26 65 78 69 73 74 73 29 3b 0a 20 20  TS, &exists);.  
6b90: 20 20 20 20 20 20 69 66 28 20 72 63 32 3d 3d 53        if( rc2==S
6ba0: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 65 78 69 73  QLITE_OK && exis
6bb0: 74 73 29 7b 0a 20 20 20 20 20 20 20 20 20 20 2f  ts){.          /
6bc0: 2a 20 69 66 20 69 74 20 65 78 69 73 74 73 2c 20  * if it exists, 
6bd0: 6f 70 65 6e 20 69 74 20 2a 2f 0a 20 20 20 20 20  open it */.     
6be0: 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20       pSubOpen = 
6bf0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
6c00: 28 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c  (p, i, &rc, NULL
6c10: 29 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65  );.        }else
6c20: 7b 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 73  {.          /* s
6c30: 74 6f 70 20 61 74 20 66 69 72 73 74 20 22 67 61  top at first "ga
6c40: 70 22 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20  p" */.          
6c50: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 7d  break;.        }
6c60: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69  .      }.      i
6c70: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
6c80: 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69         sqlite3_i
6c90: 6e 74 36 34 20 73 7a 3b 0a 20 20 20 20 20 20 20  nt64 sz;.       
6ca0: 20 72 63 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d   rc2 = pSubOpen-
6cb0: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 46 69 6c 65  >pMethods->xFile
6cc0: 53 69 7a 65 28 70 53 75 62 4f 70 65 6e 2c 20 26  Size(pSubOpen, &
6cd0: 73 7a 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  sz);.        if(
6ce0: 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20   rc2!=SQLITE_OK 
6cf0: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20  ){.          rc 
6d00: 3d 20 72 63 32 3b 0a 20 20 20 20 20 20 20 20 7d  = rc2;.        }
6d10: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20  else{.          
6d20: 69 66 28 20 73 7a 3e 70 47 72 6f 75 70 2d 3e 6e  if( sz>pGroup->n
6d30: 43 68 75 6e 6b 53 69 7a 65 20 29 7b 0a 20 20 20  ChunkSize ){.   
6d40: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51           rc = SQ
6d50: 4c 49 54 45 5f 49 4f 45 52 52 5f 46 53 54 41 54  LITE_IOERR_FSTAT
6d60: 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20  ;.          }.  
6d70: 20 20 20 20 20 20 20 20 2a 70 53 69 7a 65 20 2b          *pSize +
6d80: 3d 20 73 7a 3b 0a 20 20 20 20 20 20 20 20 7d 0a  = sz;.        }.
6d90: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
6da0: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
6db0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20    }.    }.  }.  
6dc0: 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29  multiplexLeave()
6dd0: 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  ;.  return rc;.}
6de0: 0a 0a 2f 2a 20 50 61 73 73 20 78 4c 6f 63 6b 20  ../* Pass xLock 
6df0: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
6e00: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
6e10: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
6e20: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
6e30: 6c 74 69 70 6c 65 78 4c 6f 63 6b 28 73 71 6c 69  ltiplexLock(sqli
6e40: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
6e50: 20 69 6e 74 20 6c 6f 63 6b 29 7b 0a 20 20 6d 75   int lock){.  mu
6e60: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
6e70: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
6e80: 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63  )pConn;.  int rc
6e90: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  ;.  sqlite3_file
6ea0: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
6eb0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c  tiplexSubOpen(p,
6ec0: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
6ed0: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
6ee0: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75  {.    return pSu
6ef0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
6f00: 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c  >xLock(pSubOpen,
6f10: 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72 65   lock);.  }.  re
6f20: 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59  turn SQLITE_BUSY
6f30: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55 6e  ;.}../* Pass xUn
6f40: 6c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74 68  lock requests th
6f50: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
6f60: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
6f70: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
6f80: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c 6f  nt multiplexUnlo
6f90: 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  ck(sqlite3_file 
6fa0: 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b  *pConn, int lock
6fb0: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6fc0: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6fd0: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6fe0: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
6ff0: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
7000: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
7010: 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20  Open(p, 0, &rc, 
7020: 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75  NULL);.  if( pSu
7030: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74  bOpen ){.    ret
7040: 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  urn pSubOpen->pM
7050: 65 74 68 6f 64 73 2d 3e 78 55 6e 6c 6f 63 6b 28  ethods->xUnlock(
7060: 70 53 75 62 4f 70 65 6e 2c 20 6c 6f 63 6b 29 3b  pSubOpen, lock);
7070: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51  .  }.  return SQ
7080: 4c 49 54 45 5f 49 4f 45 52 52 5f 55 4e 4c 4f 43  LITE_IOERR_UNLOC
7090: 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 43  K;.}../* Pass xC
70a0: 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b  heckReservedLock
70b0: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
70c0: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
70d0: 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e  l VFS unchanged.
70e0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
70f0: 75 6c 74 69 70 6c 65 78 43 68 65 63 6b 52 65 73  ultiplexCheckRes
7100: 65 72 76 65 64 4c 6f 63 6b 28 73 71 6c 69 74 65  ervedLock(sqlite
7110: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69  3_file *pConn, i
7120: 6e 74 20 2a 70 52 65 73 4f 75 74 29 7b 0a 20 20  nt *pResOut){.  
7130: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
7140: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
7150: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
7160: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
7170: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
7180: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
7190: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29  p, 0, &rc, NULL)
71a0: 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e  ;.  if( pSubOpen
71b0: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70   ){.    return p
71c0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
71d0: 73 2d 3e 78 43 68 65 63 6b 52 65 73 65 72 76 65  s->xCheckReserve
71e0: 64 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c 20  dLock(pSubOpen, 
71f0: 70 52 65 73 4f 75 74 29 3b 0a 20 20 7d 0a 20 20  pResOut);.  }.  
7200: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f  return SQLITE_IO
7210: 45 52 52 5f 43 48 45 43 4b 52 45 53 45 52 56 45  ERR_CHECKRESERVE
7220: 44 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  DLOCK;.}../* Pas
7230: 73 20 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 20 72  s xFileControl r
7240: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
7250: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
7260: 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2c 0a 2a  VFS unchanged,.*
7270: 2a 20 65 78 63 65 70 74 20 66 6f 72 20 61 6e 79  * except for any
7280: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
7290: 2a 20 72 65 71 75 65 73 74 73 20 68 65 72 65 2e  * requests here.
72a0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
72b0: 75 6c 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e 74  ultiplexFileCont
72c0: 72 6f 6c 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  rol(sqlite3_file
72d0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6f 70 2c   *pConn, int op,
72e0: 20 76 6f 69 64 20 2a 70 41 72 67 29 7b 0a 20 20   void *pArg){.  
72f0: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
7300: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
7310: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74  n*)pConn;.  mult
7320: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
7330: 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a  up = p->pGroup;.
7340: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
7350: 45 5f 45 52 52 4f 52 3b 0a 20 20 73 71 6c 69 74  E_ERROR;.  sqlit
7360: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
7370: 6e 3b 0a 0a 20 20 69 66 28 20 21 67 4d 75 6c 74  n;..  if( !gMult
7380: 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69  iplex.isInitiali
7390: 7a 65 64 20 29 20 72 65 74 75 72 6e 20 53 51 4c  zed ) return SQL
73a0: 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 73 77  ITE_MISUSE;.  sw
73b0: 69 74 63 68 28 20 6f 70 20 29 7b 0a 20 20 20 20  itch( op ){.    
73c0: 63 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43  case MULTIPLEX_C
73d0: 54 52 4c 5f 45 4e 41 42 4c 45 3a 0a 20 20 20 20  TRL_ENABLE:.    
73e0: 20 20 69 66 28 20 70 41 72 67 20 29 20 7b 0a 20    if( pArg ) {. 
73f0: 20 20 20 20 20 20 20 69 6e 74 20 62 45 6e 61 62         int bEnab
7400: 6c 65 64 20 3d 20 2a 28 69 6e 74 20 2a 29 70 41  led = *(int *)pA
7410: 72 67 3b 0a 20 20 20 20 20 20 20 20 70 47 72 6f  rg;.        pGro
7420: 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 3d 20 62  up->bEnabled = b
7430: 45 6e 61 62 6c 65 64 3b 0a 20 20 20 20 20 20 20  Enabled;.       
7440: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
7450: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62  .      }.      b
7460: 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 4d  reak;.    case M
7470: 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45  ULTIPLEX_CTRL_SE
7480: 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3a 0a 20 20  T_CHUNK_SIZE:.  
7490: 20 20 20 20 69 66 28 20 70 41 72 67 20 29 20 7b      if( pArg ) {
74a0: 0a 20 20 20 20 20 20 20 20 69 6e 74 20 6e 43 68  .        int nCh
74b0: 75 6e 6b 53 69 7a 65 20 3d 20 2a 28 69 6e 74 20  unkSize = *(int 
74c0: 2a 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20 20  *)pArg;.        
74d0: 69 66 28 20 6e 43 68 75 6e 6b 53 69 7a 65 3c 31  if( nChunkSize<1
74e0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
74f0: 20 3d 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45   = SQLITE_MISUSE
7500: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b  ;.        }else{
7510: 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 6f  .          /* Ro
7520: 75 6e 64 20 75 70 20 74 6f 20 6e 65 61 72 65 73  und up to neares
7530: 74 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41  t multiple of MA
7540: 58 5f 50 41 47 45 5f 53 49 5a 45 2e 20 2a 2f 0a  X_PAGE_SIZE. */.
7550: 20 20 20 20 20 20 20 20 20 20 6e 43 68 75 6e 6b            nChunk
7560: 53 69 7a 65 20 3d 20 28 6e 43 68 75 6e 6b 53 69  Size = (nChunkSi
7570: 7a 65 20 2b 20 28 4d 41 58 5f 50 41 47 45 5f 53  ze + (MAX_PAGE_S
7580: 49 5a 45 2d 31 29 29 3b 0a 20 20 20 20 20 20 20  IZE-1));.       
7590: 20 20 20 6e 43 68 75 6e 6b 53 69 7a 65 20 26 3d     nChunkSize &=
75a0: 20 7e 28 4d 41 58 5f 50 41 47 45 5f 53 49 5a 45   ~(MAX_PAGE_SIZE
75b0: 2d 31 29 3b 0a 20 20 20 20 20 20 20 20 20 20 70  -1);.          p
75c0: 47 72 6f 75 70 2d 3e 6e 43 68 75 6e 6b 53 69 7a  Group->nChunkSiz
75d0: 65 20 3d 20 6e 43 68 75 6e 6b 53 69 7a 65 3b 0a  e = nChunkSize;.
75e0: 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53            rc = S
75f0: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20  QLITE_OK;.      
7600: 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20    }.      }.    
7610: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73    break;.    cas
7620: 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c  e MULTIPLEX_CTRL
7630: 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3a  _SET_MAX_CHUNKS:
7640: 0a 20 20 20 20 20 20 69 66 28 20 70 41 72 67 20  .      if( pArg 
7650: 29 20 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20  ) {.        int 
7660: 6e 4d 61 78 43 68 75 6e 6b 73 20 3d 20 2a 28 69  nMaxChunks = *(i
7670: 6e 74 20 2a 29 70 41 72 67 3b 0a 20 20 20 20 20  nt *)pArg;.     
7680: 20 20 20 69 66 28 28 20 6e 4d 61 78 43 68 75 6e     if(( nMaxChun
7690: 6b 73 3c 31 20 29 20 7c 7c 20 28 20 6e 4d 61 78  ks<1 ) || ( nMax
76a0: 43 68 75 6e 6b 73 3e 53 51 4c 49 54 45 5f 4d 55  Chunks>SQLITE_MU
76b0: 4c 54 49 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e  LTIPLEX_MAX_CHUN
76c0: 4b 53 20 29 29 7b 0a 20 20 20 20 20 20 20 20 20  KS )){.         
76d0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4d 49 53   rc = SQLITE_MIS
76e0: 55 53 45 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c  USE;.        }el
76f0: 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20 70 47  se{.          pG
7700: 72 6f 75 70 2d 3e 6e 4d 61 78 43 68 75 6e 6b 73  roup->nMaxChunks
7710: 20 3d 20 6e 4d 61 78 43 68 75 6e 6b 73 3b 0a 20   = nMaxChunks;. 
7720: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51           rc = SQ
7730: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 20  LITE_OK;.       
7740: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20   }.      }.     
7750: 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65   break;.    case
7760: 20 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 53 49   SQLITE_FCNTL_SI
7770: 5a 45 5f 48 49 4e 54 3a 0a 20 20 20 20 63 61 73  ZE_HINT:.    cas
7780: 65 20 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 43  e SQLITE_FCNTL_C
7790: 48 55 4e 4b 5f 53 49 5a 45 3a 0a 20 20 20 20 20  HUNK_SIZE:.     
77a0: 20 2f 2a 20 6e 6f 2d 6f 70 20 74 68 65 73 65 20   /* no-op these 
77b0: 2a 2f 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51  */.      rc = SQ
77c0: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62  LITE_OK;.      b
77d0: 72 65 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c  reak;.    defaul
77e0: 74 3a 0a 20 20 20 20 20 20 70 53 75 62 4f 70 65  t:.      pSubOpe
77f0: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
7800: 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20  Open(p, 0, &rc, 
7810: 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20 69 66 28  NULL);.      if(
7820: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
7830: 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70       rc = pSubOp
7840: 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 46  en->pMethods->xF
7850: 69 6c 65 43 6f 6e 74 72 6f 6c 28 70 53 75 62 4f  ileControl(pSubO
7860: 70 65 6e 2c 20 6f 70 2c 20 70 41 72 67 29 3b 0a  pen, op, pArg);.
7870: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72        }.      br
7880: 65 61 6b 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  eak;.  }.  retur
7890: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73  n rc;.}../* Pass
78a0: 20 78 53 65 63 74 6f 72 53 69 7a 65 20 72 65 71   xSectorSize req
78b0: 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f  uests through to
78c0: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
78d0: 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a  S unchanged..*/.
78e0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
78f0: 70 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 28 73  plexSectorSize(s
7900: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
7910: 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  nn){.  multiplex
7920: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
7930: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
7940: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c  .  int rc;.  sql
7950: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
7960: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
7970: 75 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63  ubOpen(p, 0, &rc
7980: 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70  , NULL);.  if( p
7990: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72  SubOpen ){.    r
79a0: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e  eturn pSubOpen->
79b0: 70 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f  pMethods->xSecto
79c0: 72 53 69 7a 65 28 70 53 75 62 4f 70 65 6e 29 3b  rSize(pSubOpen);
79d0: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 44 45  .  }.  return DE
79e0: 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f 53 49 5a  FAULT_SECTOR_SIZ
79f0: 45 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 44  E;.}../* Pass xD
7a00: 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69 73  eviceCharacteris
7a10: 74 69 63 73 20 72 65 71 75 65 73 74 73 20 74 68  tics requests th
7a20: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
7a30: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
7a40: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
7a50: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 76 69  nt multiplexDevi
7a60: 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63  ceCharacteristic
7a70: 73 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  s(sqlite3_file *
7a80: 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70  pConn){.  multip
7a90: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
7aa0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
7ab0: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
7ac0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7ad0: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
7ae0: 65 78 53 75 62 4f 70 65 6e 28 70 2c 20 30 2c 20  exSubOpen(p, 0, 
7af0: 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66  &rc, NULL);.  if
7b00: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
7b10: 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65    return pSubOpe
7b20: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 44 65  n->pMethods->xDe
7b30: 76 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74  viceCharacterist
7b40: 69 63 73 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20  ics(pSubOpen);. 
7b50: 20 7d 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d   }.  return 0;.}
7b60: 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 4d 61  ../* Pass xShmMa
7b70: 70 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  p requests throu
7b80: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
7b90: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
7ba0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
7bb0: 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70 28  multiplexShmMap(
7bc0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
7bd0: 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20 20 20 20  *pConn,         
7be0: 20 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6f 70 65     /* Handle ope
7bf0: 6e 20 6f 6e 20 64 61 74 61 62 61 73 65 20 66 69  n on database fi
7c00: 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 69 52 65 67  le */.  int iReg
7c10: 69 6f 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20  ion,            
7c20: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 67 69 6f          /* Regio
7c30: 6e 20 74 6f 20 72 65 74 72 69 65 76 65 20 2a 2f  n to retrieve */
7c40: 0a 20 20 69 6e 74 20 73 7a 52 65 67 69 6f 6e 2c  .  int szRegion,
7c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c60: 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 72 65     /* Size of re
7c70: 67 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74 20 62  gions */.  int b
7c80: 45 78 74 65 6e 64 2c 20 20 20 20 20 20 20 20 20  Extend,         
7c90: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
7ca0: 75 65 20 74 6f 20 65 78 74 65 6e 64 20 66 69 6c  ue to extend fil
7cb0: 65 20 69 66 20 6e 65 63 65 73 73 61 72 79 20 2a  e if necessary *
7cc0: 2f 0a 20 20 76 6f 69 64 20 76 6f 6c 61 74 69 6c  /.  void volatil
7cd0: 65 20 2a 2a 70 70 20 20 20 20 20 20 20 20 20 20  e **pp          
7ce0: 20 20 20 20 2f 2a 20 4f 55 54 3a 20 4d 61 70 70      /* OUT: Mapp
7cf0: 65 64 20 6d 65 6d 6f 72 79 20 2a 2f 0a 29 7b 0a  ed memory */.){.
7d00: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
7d10: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
7d20: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
7d30: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
7d40: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
7d50: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
7d60: 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  n(p, 0, &rc, NUL
7d70: 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  L);.  if( pSubOp
7d80: 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  en ){.    return
7d90: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7da0: 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28 70 53 75  ods->xShmMap(pSu
7db0: 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f 6e 2c 20  bOpen, iRegion, 
7dc0: 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78 74 65 6e  szRegion, bExten
7dd0: 64 2c 70 70 29 3b 0a 20 20 7d 0a 20 20 72 65 74  d,pp);.  }.  ret
7de0: 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  urn SQLITE_IOERR
7df0: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68  ;.}../* Pass xSh
7e00: 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  mLock requests t
7e10: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7e20: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7e30: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7e40: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  int multiplexShm
7e50: 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74 65 33 5f  Lock(.  sqlite3_
7e60: 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20 20  file *pConn,    
7e70: 20 20 20 2f 2a 20 44 61 74 61 62 61 73 65 20 66     /* Database f
7e80: 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68 65 20  ile holding the 
7e90: 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 20 2a 2f  shared memory */
7ea0: 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20 20 20 20  .  int ofst,    
7eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
7ec0: 20 46 69 72 73 74 20 6c 6f 63 6b 20 74 6f 20 61   First lock to a
7ed0: 63 71 75 69 72 65 20 6f 72 20 72 65 6c 65 61 73  cquire or releas
7ee0: 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c 20 20 20  e */.  int n,   
7ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7f00: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 6c    /* Number of l
7f10: 6f 63 6b 73 20 74 6f 20 61 63 71 75 69 72 65 20  ocks to acquire 
7f20: 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f 0a 20 20  or release */.  
7f30: 69 6e 74 20 66 6c 61 67 73 20 20 20 20 20 20 20  int flags       
7f40: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 57 68             /* Wh
7f50: 61 74 20 74 6f 20 64 6f 20 77 69 74 68 20 74 68  at to do with th
7f60: 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a 20 20 6d  e lock */.){.  m
7f70: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
7f80: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
7f90: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
7fa0: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
7fb0: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
7fc0: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
7fd0: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b  , 0, &rc, NULL);
7fe0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
7ff0: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
8000: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
8010: 2d 3e 78 53 68 6d 4c 6f 63 6b 28 70 53 75 62 4f  ->xShmLock(pSubO
8020: 70 65 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20 66 6c  pen, ofst, n, fl
8030: 61 67 73 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75  ags);.  }.  retu
8040: 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59 3b 0a  rn SQLITE_BUSY;.
8050: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 42  }../* Pass xShmB
8060: 61 72 72 69 65 72 20 72 65 71 75 65 73 74 73 20  arrier requests 
8070: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
8080: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
8090: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
80a0: 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 53   void multiplexS
80b0: 68 6d 42 61 72 72 69 65 72 28 73 71 6c 69 74 65  hmBarrier(sqlite
80c0: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a  3_file *pConn){.
80d0: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
80e0: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
80f0: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
8100: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
8110: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
8120: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
8130: 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  n(p, 0, &rc, NUL
8140: 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  L);.  if( pSubOp
8150: 65 6e 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70  en ){.    pSubOp
8160: 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53  en->pMethods->xS
8170: 68 6d 42 61 72 72 69 65 72 28 70 53 75 62 4f 70  hmBarrier(pSubOp
8180: 65 6e 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 20 50  en);.  }.}../* P
8190: 61 73 73 20 78 53 68 6d 55 6e 6d 61 70 20 72 65  ass xShmUnmap re
81a0: 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74  quests through t
81b0: 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56  o the original V
81c0: 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f  FS unchanged..*/
81d0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
81e0: 69 70 6c 65 78 53 68 6d 55 6e 6d 61 70 28 73 71  iplexShmUnmap(sq
81f0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
8200: 6e 2c 20 69 6e 74 20 64 65 6c 65 74 65 46 6c 61  n, int deleteFla
8210: 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  g){.  multiplexC
8220: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
8230: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
8240: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
8250: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
8260: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
8270: 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c  bOpen(p, 0, &rc,
8280: 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53   NULL);.  if( pS
8290: 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65  ubOpen ){.    re
82a0: 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70  turn pSubOpen->p
82b0: 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 55 6e 6d  Methods->xShmUnm
82c0: 61 70 28 70 53 75 62 4f 70 65 6e 2c 20 64 65 6c  ap(pSubOpen, del
82d0: 65 74 65 46 6c 61 67 29 3b 0a 20 20 7d 0a 20 20  eteFlag);.  }.  
82e0: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
82f0: 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;.}../**********
8300: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8310: 20 50 75 62 6c 69 63 20 49 6e 74 65 72 66 61 63   Public Interfac
8320: 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  es *************
8330: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8340: 2f 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20 49 6e  /./*.** CAPI: In
8350: 69 74 69 61 6c 69 7a 65 20 74 68 65 20 6d 75 6c  itialize the mul
8360: 74 69 70 6c 65 78 20 56 46 53 20 73 68 69 6d 20  tiplex VFS shim 
8370: 2d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  - sqlite3_multip
8380: 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 29  lex_initialize()
8390: 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74 68 65 20 56  .**.** Use the V
83a0: 46 53 20 6e 61 6d 65 64 20 7a 4f 72 69 67 56 66  FS named zOrigVf
83b0: 73 4e 61 6d 65 20 61 73 20 74 68 65 20 56 46 53  sName as the VFS
83c0: 20 74 68 61 74 20 64 6f 65 73 20 74 68 65 20 61   that does the a
83d0: 63 74 75 61 6c 20 77 6f 72 6b 2e 20 20 0a 2a 2a  ctual work.  .**
83e0: 20 55 73 65 20 74 68 65 20 64 65 66 61 75 6c 74   Use the default
83f0: 20 69 66 20 7a 4f 72 69 67 56 66 73 4e 61 6d 65   if zOrigVfsName
8400: 3d 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a 0a 2a 2a 20  ==NULL.  .**.** 
8410: 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46  The multiplex VF
8420: 53 20 73 68 69 6d 20 69 73 20 6e 61 6d 65 64 20  S shim is named 
8430: 22 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20 49 74  "multiplex".  It
8440: 20 77 69 6c 6c 20 62 65 63 6f 6d 65 20 74 68 65   will become the
8450: 20 64 65 66 61 75 6c 74 0a 2a 2a 20 56 46 53 20   default.** VFS 
8460: 69 66 20 6d 61 6b 65 44 65 66 61 75 6c 74 20 69  if makeDefault i
8470: 73 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a 2a 2a 0a 2a  s non-zero..**.*
8480: 2a 20 54 48 49 53 20 52 4f 55 54 49 4e 45 20 49  * THIS ROUTINE I
8490: 53 20 4e 4f 54 20 54 48 52 45 41 44 53 41 46 45  S NOT THREADSAFE
84a0: 2e 20 20 43 61 6c 6c 20 74 68 69 73 20 72 6f 75  .  Call this rou
84b0: 74 69 6e 65 20 65 78 61 63 74 6c 79 20 6f 6e 63  tine exactly onc
84c0: 65 0a 2a 2a 20 64 75 72 69 6e 67 20 73 74 61 72  e.** during star
84d0: 74 2d 75 70 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c  t-up..*/.int sql
84e0: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69  ite3_multiplex_i
84f0: 6e 69 74 69 61 6c 69 7a 65 28 63 6f 6e 73 74 20  nitialize(const 
8500: 63 68 61 72 20 2a 7a 4f 72 69 67 56 66 73 4e 61  char *zOrigVfsNa
8510: 6d 65 2c 20 69 6e 74 20 6d 61 6b 65 44 65 66 61  me, int makeDefa
8520: 75 6c 74 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f  ult){.  sqlite3_
8530: 76 66 73 20 2a 70 4f 72 69 67 56 66 73 3b 0a 20  vfs *pOrigVfs;. 
8540: 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e   if( gMultiplex.
8550: 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 29 20  isInitialized ) 
8560: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49  return SQLITE_MI
8570: 53 55 53 45 3b 0a 20 20 70 4f 72 69 67 56 66 73  SUSE;.  pOrigVfs
8580: 20 3d 20 73 71 6c 69 74 65 33 5f 76 66 73 5f 66   = sqlite3_vfs_f
8590: 69 6e 64 28 7a 4f 72 69 67 56 66 73 4e 61 6d 65  ind(zOrigVfsName
85a0: 29 3b 0a 20 20 69 66 28 20 70 4f 72 69 67 56 66  );.  if( pOrigVf
85b0: 73 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 53 51  s==0 ) return SQ
85c0: 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20 61 73  LITE_ERROR;.  as
85d0: 73 65 72 74 28 20 70 4f 72 69 67 56 66 73 21 3d  sert( pOrigVfs!=
85e0: 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69  &gMultiplex.sThi
85f0: 73 56 66 73 20 29 3b 0a 20 20 67 4d 75 6c 74 69  sVfs );.  gMulti
8600: 70 6c 65 78 2e 70 4d 75 74 65 78 20 3d 20 73 71  plex.pMutex = sq
8610: 6c 69 74 65 33 5f 6d 75 74 65 78 5f 61 6c 6c 6f  lite3_mutex_allo
8620: 63 28 53 51 4c 49 54 45 5f 4d 55 54 45 58 5f 46  c(SQLITE_MUTEX_F
8630: 41 53 54 29 3b 0a 20 20 69 66 28 20 21 67 4d 75  AST);.  if( !gMu
8640: 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20 29  ltiplex.pMutex )
8650: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c  {.    return SQL
8660: 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d 0a 20  ITE_NOMEM;.  }. 
8670: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d   gMultiplex.zNam
8680: 65 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  e = sqlite3_mall
8690: 6f 63 28 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50  oc(pOrigVfs->mxP
86a0: 61 74 68 6e 61 6d 65 29 3b 0a 20 20 69 66 28 20  athname);.  if( 
86b0: 21 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d  !gMultiplex.zNam
86c0: 65 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33  e ){.    sqlite3
86d0: 5f 6d 75 74 65 78 5f 66 72 65 65 28 67 4d 75 6c  _mutex_free(gMul
86e0: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 0a  tiplex.pMutex);.
86f0: 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54      return SQLIT
8700: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d 0a 20 20 67  E_NOMEM;.  }.  g
8710: 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70  Multiplex.pGroup
8720: 73 20 3d 20 4e 55 4c 4c 3b 0a 20 20 67 4d 75 6c  s = NULL;.  gMul
8730: 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c  tiplex.isInitial
8740: 69 7a 65 64 20 3d 20 31 3b 0a 20 20 67 4d 75 6c  ized = 1;.  gMul
8750: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 20  tiplex.pOrigVfs 
8760: 3d 20 70 4f 72 69 67 56 66 73 3b 0a 20 20 67 4d  = pOrigVfs;.  gM
8770: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
8780: 73 20 3d 20 2a 70 4f 72 69 67 56 66 73 3b 0a 20  s = *pOrigVfs;. 
8790: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
87a0: 73 56 66 73 2e 73 7a 4f 73 46 69 6c 65 20 2b 3d  sVfs.szOsFile +=
87b0: 20 73 69 7a 65 6f 66 28 6d 75 6c 74 69 70 6c 65   sizeof(multiple
87c0: 78 43 6f 6e 6e 29 3b 0a 20 20 67 4d 75 6c 74 69  xConn);.  gMulti
87d0: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 7a 4e  plex.sThisVfs.zN
87e0: 61 6d 65 20 3d 20 53 51 4c 49 54 45 5f 4d 55 4c  ame = SQLITE_MUL
87f0: 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d 45 3b  TIPLEX_VFS_NAME;
8800: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
8810: 68 69 73 56 66 73 2e 78 4f 70 65 6e 20 3d 20 6d  hisVfs.xOpen = m
8820: 75 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 0a 20 20  ultiplexOpen;.  
8830: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
8840: 56 66 73 2e 78 44 65 6c 65 74 65 20 3d 20 6d 75  Vfs.xDelete = mu
8850: 6c 74 69 70 6c 65 78 44 65 6c 65 74 65 3b 0a 20  ltiplexDelete;. 
8860: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
8870: 73 56 66 73 2e 78 41 63 63 65 73 73 20 3d 20 6d  sVfs.xAccess = m
8880: 75 6c 74 69 70 6c 65 78 41 63 63 65 73 73 3b 0a  ultiplexAccess;.
8890: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
88a0: 69 73 56 66 73 2e 78 46 75 6c 6c 50 61 74 68 6e  isVfs.xFullPathn
88b0: 61 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 46  ame = multiplexF
88c0: 75 6c 6c 50 61 74 68 6e 61 6d 65 3b 0a 20 20 67  ullPathname;.  g
88d0: 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56  Multiplex.sThisV
88e0: 66 73 2e 78 44 6c 4f 70 65 6e 20 3d 20 6d 75 6c  fs.xDlOpen = mul
88f0: 74 69 70 6c 65 78 44 6c 4f 70 65 6e 3b 0a 20 20  tiplexDlOpen;.  
8900: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
8910: 56 66 73 2e 78 44 6c 45 72 72 6f 72 20 3d 20 6d  Vfs.xDlError = m
8920: 75 6c 74 69 70 6c 65 78 44 6c 45 72 72 6f 72 3b  ultiplexDlError;
8930: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
8940: 68 69 73 56 66 73 2e 78 44 6c 53 79 6d 20 3d 20  hisVfs.xDlSym = 
8950: 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79 6d 3b 0a  multiplexDlSym;.
8960: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
8970: 69 73 56 66 73 2e 78 44 6c 43 6c 6f 73 65 20 3d  isVfs.xDlClose =
8980: 20 6d 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73   multiplexDlClos
8990: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
89a0: 73 54 68 69 73 56 66 73 2e 78 52 61 6e 64 6f 6d  sThisVfs.xRandom
89b0: 6e 65 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78  ness = multiplex
89c0: 52 61 6e 64 6f 6d 6e 65 73 73 3b 0a 20 20 67 4d  Randomness;.  gM
89d0: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
89e0: 73 2e 78 53 6c 65 65 70 20 3d 20 6d 75 6c 74 69  s.xSleep = multi
89f0: 70 6c 65 78 53 6c 65 65 70 3b 0a 20 20 67 4d 75  plexSleep;.  gMu
8a00: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
8a10: 2e 78 43 75 72 72 65 6e 74 54 69 6d 65 20 3d 20  .xCurrentTime = 
8a20: 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e 74  multiplexCurrent
8a30: 54 69 6d 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Time;.  gMultipl
8a40: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 47 65 74  ex.sThisVfs.xGet
8a50: 4c 61 73 74 45 72 72 6f 72 20 3d 20 6d 75 6c 74  LastError = mult
8a60: 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72 72 6f  iplexGetLastErro
8a70: 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  r;.  gMultiplex.
8a80: 73 54 68 69 73 56 66 73 2e 78 43 75 72 72 65 6e  sThisVfs.xCurren
8a90: 74 54 69 6d 65 49 6e 74 36 34 20 3d 20 6d 75 6c  tTimeInt64 = mul
8aa0: 74 69 70 6c 65 78 43 75 72 72 65 6e 74 54 69 6d  tiplexCurrentTim
8ab0: 65 49 6e 74 36 34 3b 0a 0a 20 20 67 4d 75 6c 74  eInt64;..  gMult
8ac0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
8ad0: 56 31 2e 69 56 65 72 73 69 6f 6e 20 3d 20 31 3b  V1.iVersion = 1;
8ae0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
8af0: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 43 6c 6f 73  oMethodsV1.xClos
8b00: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 6c 6f  e = multiplexClo
8b10: 73 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  se;.  gMultiplex
8b20: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 52  .sIoMethodsV1.xR
8b30: 65 61 64 20 3d 20 6d 75 6c 74 69 70 6c 65 78 52  ead = multiplexR
8b40: 65 61 64 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ead;.  gMultiple
8b50: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
8b60: 57 72 69 74 65 20 3d 20 6d 75 6c 74 69 70 6c 65  Write = multiple
8b70: 78 57 72 69 74 65 3b 0a 20 20 67 4d 75 6c 74 69  xWrite;.  gMulti
8b80: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
8b90: 31 2e 78 54 72 75 6e 63 61 74 65 20 3d 20 6d 75  1.xTruncate = mu
8ba0: 6c 74 69 70 6c 65 78 54 72 75 6e 63 61 74 65 3b  ltiplexTruncate;
8bb0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
8bc0: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53 79 6e 63  oMethodsV1.xSync
8bd0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63   = multiplexSync
8be0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
8bf0: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46 69 6c  IoMethodsV1.xFil
8c00: 65 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c 65  eSize = multiple
8c10: 78 46 69 6c 65 53 69 7a 65 3b 0a 20 20 67 4d 75  xFileSize;.  gMu
8c20: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
8c30: 64 73 56 31 2e 78 4c 6f 63 6b 20 3d 20 6d 75 6c  dsV1.xLock = mul
8c40: 74 69 70 6c 65 78 4c 6f 63 6b 3b 0a 20 20 67 4d  tiplexLock;.  gM
8c50: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8c60: 6f 64 73 56 31 2e 78 55 6e 6c 6f 63 6b 20 3d 20  odsV1.xUnlock = 
8c70: 6d 75 6c 74 69 70 6c 65 78 55 6e 6c 6f 63 6b 3b  multiplexUnlock;
8c80: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
8c90: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 43 68 65 63  oMethodsV1.xChec
8ca0: 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 20 3d 20  kReservedLock = 
8cb0: 6d 75 6c 74 69 70 6c 65 78 43 68 65 63 6b 52 65  multiplexCheckRe
8cc0: 73 65 72 76 65 64 4c 6f 63 6b 3b 0a 20 20 67 4d  servedLock;.  gM
8cd0: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8ce0: 6f 64 73 56 31 2e 78 46 69 6c 65 43 6f 6e 74 72  odsV1.xFileContr
8cf0: 6f 6c 20 3d 20 6d 75 6c 74 69 70 6c 65 78 46 69  ol = multiplexFi
8d00: 6c 65 43 6f 6e 74 72 6f 6c 3b 0a 20 20 67 4d 75  leControl;.  gMu
8d10: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
8d20: 64 73 56 31 2e 78 53 65 63 74 6f 72 53 69 7a 65  dsV1.xSectorSize
8d30: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 65 63 74   = multiplexSect
8d40: 6f 72 53 69 7a 65 3b 0a 20 20 67 4d 75 6c 74 69  orSize;.  gMulti
8d50: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
8d60: 31 2e 78 44 65 76 69 63 65 43 68 61 72 61 63 74  1.xDeviceCharact
8d70: 65 72 69 73 74 69 63 73 20 3d 0a 20 20 20 20 20  eristics =.     
8d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8da0: 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78         multiplex
8db0: 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69  DeviceCharacteri
8dc0: 73 74 69 63 73 3b 0a 20 20 67 4d 75 6c 74 69 70  stics;.  gMultip
8dd0: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32  lex.sIoMethodsV2
8de0: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49   = gMultiplex.sI
8df0: 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 67 4d  oMethodsV1;.  gM
8e00: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8e10: 6f 64 73 56 32 2e 69 56 65 72 73 69 6f 6e 20 3d  odsV2.iVersion =
8e20: 20 32 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78   2;.  gMultiplex
8e30: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53  .sIoMethodsV2.xS
8e40: 68 6d 4d 61 70 20 3d 20 6d 75 6c 74 69 70 6c 65  hmMap = multiple
8e50: 78 53 68 6d 4d 61 70 3b 0a 20 20 67 4d 75 6c 74  xShmMap;.  gMult
8e60: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
8e70: 56 32 2e 78 53 68 6d 4c 6f 63 6b 20 3d 20 6d 75  V2.xShmLock = mu
8e80: 6c 74 69 70 6c 65 78 53 68 6d 4c 6f 63 6b 3b 0a  ltiplexShmLock;.
8e90: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
8ea0: 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 42 61  MethodsV2.xShmBa
8eb0: 72 72 69 65 72 20 3d 20 6d 75 6c 74 69 70 6c 65  rrier = multiple
8ec0: 78 53 68 6d 42 61 72 72 69 65 72 3b 0a 20 20 67  xShmBarrier;.  g
8ed0: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
8ee0: 68 6f 64 73 56 32 2e 78 53 68 6d 55 6e 6d 61 70  hodsV2.xShmUnmap
8ef0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 55   = multiplexShmU
8f00: 6e 6d 61 70 3b 0a 20 20 73 71 6c 69 74 65 33 5f  nmap;.  sqlite3_
8f10: 76 66 73 5f 72 65 67 69 73 74 65 72 28 26 67 4d  vfs_register(&gM
8f20: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
8f30: 73 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29 3b  s, makeDefault);
8f40: 0a 0a 20 20 73 71 6c 69 74 65 33 5f 61 75 74 6f  ..  sqlite3_auto
8f50: 5f 65 78 74 65 6e 73 69 6f 6e 28 28 76 6f 69 64  _extension((void
8f60: 2a 29 6d 75 6c 74 69 70 6c 65 78 46 75 6e 63 49  *)multiplexFuncI
8f70: 6e 69 74 29 3b 0a 0a 20 20 72 65 74 75 72 6e 20  nit);..  return 
8f80: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
8f90: 0a 2a 2a 20 43 41 50 49 3a 20 53 68 75 74 64 6f  .** CAPI: Shutdo
8fa0: 77 6e 20 74 68 65 20 6d 75 6c 74 69 70 6c 65 78  wn the multiplex
8fb0: 20 73 79 73 74 65 6d 20 2d 20 73 71 6c 69 74 65   system - sqlite
8fc0: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74  3_multiplex_shut
8fd0: 64 6f 77 6e 28 29 0a 2a 2a 0a 2a 2a 20 41 6c 6c  down().**.** All
8fe0: 20 53 51 4c 69 74 65 20 64 61 74 61 62 61 73 65   SQLite database
8ff0: 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 6d 75 73   connections mus
9000: 74 20 62 65 20 63 6c 6f 73 65 64 20 62 65 66 6f  t be closed befo
9010: 72 65 20 63 61 6c 6c 69 6e 67 20 74 68 69 73 0a  re calling this.
9020: 2a 2a 20 72 6f 75 74 69 6e 65 2e 0a 2a 2a 0a 2a  ** routine..**.*
9030: 2a 20 54 48 49 53 20 52 4f 55 54 49 4e 45 20 49  * THIS ROUTINE I
9040: 53 20 4e 4f 54 20 54 48 52 45 41 44 53 41 46 45  S NOT THREADSAFE
9050: 2e 20 20 43 61 6c 6c 20 74 68 69 73 20 72 6f 75  .  Call this rou
9060: 74 69 6e 65 20 65 78 61 63 74 6c 79 20 6f 6e 63  tine exactly onc
9070: 65 20 77 68 69 6c 65 0a 2a 2a 20 73 68 75 74 74  e while.** shutt
9080: 69 6e 67 20 64 6f 77 6e 20 69 6e 20 6f 72 64 65  ing down in orde
9090: 72 20 74 6f 20 66 72 65 65 20 61 6c 6c 20 72 65  r to free all re
90a0: 6d 61 69 6e 69 6e 67 20 6d 75 6c 74 69 70 6c 65  maining multiple
90b0: 78 20 67 72 6f 75 70 73 2e 0a 2a 2f 0a 69 6e 74  x groups..*/.int
90c0: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
90d0: 65 78 5f 73 68 75 74 64 6f 77 6e 28 76 6f 69 64  ex_shutdown(void
90e0: 29 7b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70  ){.  if( gMultip
90f0: 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65  lex.isInitialize
9100: 64 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 53 51  d==0 ) return SQ
9110: 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 69  LITE_MISUSE;.  i
9120: 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47  f( gMultiplex.pG
9130: 72 6f 75 70 73 20 29 20 72 65 74 75 72 6e 20 53  roups ) return S
9140: 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20  QLITE_MISUSE;.  
9150: 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69  gMultiplex.isIni
9160: 74 69 61 6c 69 7a 65 64 20 3d 20 30 3b 0a 20 20  tialized = 0;.  
9170: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 67 4d 75  sqlite3_free(gMu
9180: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 29 3b 0a  ltiplex.zName);.
9190: 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f    sqlite3_mutex_
91a0: 66 72 65 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e  free(gMultiplex.
91b0: 70 4d 75 74 65 78 29 3b 0a 20 20 73 71 6c 69 74  pMutex);.  sqlit
91c0: 65 33 5f 76 66 73 5f 75 6e 72 65 67 69 73 74 65  e3_vfs_unregiste
91d0: 72 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  r(&gMultiplex.sT
91e0: 68 69 73 56 66 73 29 3b 0a 20 20 6d 65 6d 73 65  hisVfs);.  memse
91f0: 74 28 26 67 4d 75 6c 74 69 70 6c 65 78 2c 20 30  t(&gMultiplex, 0
9200: 2c 20 73 69 7a 65 6f 66 28 67 4d 75 6c 74 69 70  , sizeof(gMultip
9210: 6c 65 78 29 29 3b 0a 20 20 72 65 74 75 72 6e 20  lex));.  return 
9220: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
9230: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9240: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 54 65 73  ************ Tes
9250: 74 20 43 6f 64 65 20 2a 2a 2a 2a 2a 2a 2a 2a 2a  t Code *********
9260: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9270: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 23 69 66 64  **********/.#ifd
9280: 65 66 20 53 51 4c 49 54 45 5f 54 45 53 54 0a 23  ef SQLITE_TEST.#
9290: 69 6e 63 6c 75 64 65 20 3c 74 63 6c 2e 68 3e 0a  include <tcl.h>.
92a0: 65 78 74 65 72 6e 20 63 6f 6e 73 74 20 63 68 61  extern const cha
92b0: 72 20 2a 73 71 6c 69 74 65 33 54 65 73 74 45 72  r *sqlite3TestEr
92c0: 72 6f 72 4e 61 6d 65 28 69 6e 74 29 3b 0a 0a 0a  rorName(int);...
92d0: 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71  /*.** tclcmd: sq
92e0: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
92f0: 69 6e 69 74 69 61 6c 69 7a 65 20 4e 41 4d 45 20  initialize NAME 
9300: 4d 41 4b 45 44 45 46 41 55 4c 54 0a 2a 2f 0a 73  MAKEDEFAULT.*/.s
9310: 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d  tatic int test_m
9320: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
9330: 69 7a 65 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c  ize(.  void * cl
9340: 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f  ientData,.  Tcl_
9350: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
9360: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
9370: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
9380: 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 63  v[].){.  const c
9390: 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20  har *zName;     
93a0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
93b0: 20 6f 66 20 6e 65 77 20 6d 75 6c 74 69 70 6c 65   of new multiple
93c0: 78 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6d  x VFS */.  int m
93d0: 61 6b 65 44 65 66 61 75 6c 74 3b 20 20 20 20 20  akeDefault;     
93e0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
93f0: 75 65 20 74 6f 20 6d 61 6b 65 20 74 68 65 20 6e  ue to make the n
9400: 65 77 20 56 46 53 20 74 68 65 20 64 65 66 61 75  ew VFS the defau
9410: 6c 74 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20  lt */.  int rc; 
9420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9430: 20 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65          /* Value
9440: 20 72 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c   returned by mul
9450: 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a  tiplex_initializ
9460: 65 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45 44  e() */..  UNUSED
9470: 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e  _PARAMETER(clien
9480: 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 50 72  tData);..  /* Pr
9490: 6f 63 65 73 73 20 61 72 67 75 6d 65 6e 74 73 20  ocess arguments 
94a0: 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 33  */.  if( objc!=3
94b0: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
94c0: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
94d0: 20 31 2c 20 6f 62 6a 76 2c 20 22 4e 41 4d 45 20   1, objv, "NAME 
94e0: 4d 41 4b 45 44 45 46 41 55 4c 54 22 29 3b 0a 20  MAKEDEFAULT");. 
94f0: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
9500: 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e 61 6d 65  ROR;.  }.  zName
9510: 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67   = Tcl_GetString
9520: 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20 69 66 28  (objv[1]);.  if(
9530: 20 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61 6e 46   Tcl_GetBooleanF
9540: 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f  romObj(interp, o
9550: 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65 44 65 66  bjv[2], &makeDef
9560: 61 75 6c 74 29 20 29 20 72 65 74 75 72 6e 20 54  ault) ) return T
9570: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 69 66 28 20  CL_ERROR;.  if( 
9580: 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30 27 20 29  zName[0]=='\0' )
9590: 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a 20 20 2f   zName = 0;..  /
95a0: 2a 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d  * Call sqlite3_m
95b0: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
95c0: 69 7a 65 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20  ize() */.  rc = 
95d0: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
95e0: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 7a 4e 61  x_initialize(zNa
95f0: 6d 65 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29  me, makeDefault)
9600: 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c  ;.  Tcl_SetResul
9610: 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20  t(interp, (char 
9620: 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45 72 72  *)sqlite3TestErr
9630: 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f  orName(rc), TCL_
9640: 53 54 41 54 49 43 29 3b 0a 0a 20 20 72 65 74 75  STATIC);..  retu
9650: 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn TCL_OK;.}../*
9660: 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71 6c 69  .** tclcmd: sqli
9670: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
9680: 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74 61 74 69 63  utdown.*/.static
9690: 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69 70   int test_multip
96a0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 0a 20 20  lex_shutdown(.  
96b0: 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74  void * clientDat
96c0: 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20  a,.  Tcl_Interp 
96d0: 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f  *interp,.  int o
96e0: 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a  bjc,.  Tcl_Obj *
96f0: 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a  CONST objv[].){.
9700: 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20    int rc;       
9710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9720: 20 20 2f 2a 20 56 61 6c 75 65 20 72 65 74 75 72    /* Value retur
9730: 6e 65 64 20 62 79 20 6d 75 6c 74 69 70 6c 65 78  ned by multiplex
9740: 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a 2f 0a 0a  _shutdown() */..
9750: 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54    UNUSED_PARAMET
9760: 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b 0a  ER(clientData);.
9770: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 31 20 29  .  if( objc!=1 )
9780: 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e  {.    Tcl_WrongN
9790: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31  umArgs(interp, 1
97a0: 2c 20 6f 62 6a 76 2c 20 22 22 29 3b 0a 20 20 20  , objv, "");.   
97b0: 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f   return TCL_ERRO
97c0: 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 61 6c  R;.  }..  /* Cal
97d0: 6c 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  l sqlite3_multip
97e0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a  lex_shutdown() *
97f0: 2f 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33  /.  rc = sqlite3
9800: 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64  _multiplex_shutd
9810: 6f 77 6e 28 29 3b 0a 20 20 54 63 6c 5f 53 65 74  own();.  Tcl_Set
9820: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28  Result(interp, (
9830: 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65  char *)sqlite3Te
9840: 73 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c  stErrorName(rc),
9850: 20 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20   TCL_STATIC);.. 
9860: 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a   return TCL_OK;.
9870: 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a  }../*.** tclcmd:
9880: 20 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70    sqlite3_multip
9890: 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a 73 74 61 74  lex_dump.*/.stat
98a0: 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74  ic int test_mult
98b0: 69 70 6c 65 78 5f 64 75 6d 70 28 0a 20 20 76 6f  iplex_dump(.  vo
98c0: 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74 61 2c  id * clientData,
98d0: 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69  .  Tcl_Interp *i
98e0: 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a  nterp,.  int obj
98f0: 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f  c,.  Tcl_Obj *CO
9900: 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20  NST objv[].){.  
9910: 54 63 6c 5f 4f 62 6a 20 2a 70 52 65 73 75 6c 74  Tcl_Obj *pResult
9920: 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 47 72  ;.  Tcl_Obj *pGr
9930: 6f 75 70 54 65 72 6d 3b 0a 20 20 6d 75 6c 74 69  oupTerm;.  multi
9940: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
9950: 70 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e  p;.  int i;.  in
9960: 74 20 6e 43 68 75 6e 6b 73 20 3d 20 30 3b 0a 0a  t nChunks = 0;..
9970: 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54    UNUSED_PARAMET
9980: 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b 0a  ER(clientData);.
9990: 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54    UNUSED_PARAMET
99a0: 45 52 28 6f 62 6a 63 29 3b 0a 20 20 55 4e 55 53  ER(objc);.  UNUS
99b0: 45 44 5f 50 41 52 41 4d 45 54 45 52 28 6f 62 6a  ED_PARAMETER(obj
99c0: 76 29 3b 0a 0a 20 20 70 52 65 73 75 6c 74 20 3d  v);..  pResult =
99d0: 20 54 63 6c 5f 4e 65 77 4f 62 6a 28 29 3b 0a 20   Tcl_NewObj();. 
99e0: 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28   multiplexEnter(
99f0: 29 3b 0a 20 20 66 6f 72 28 70 47 72 6f 75 70 3d  );.  for(pGroup=
9a00: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75  gMultiplex.pGrou
9a10: 70 73 3b 20 70 47 72 6f 75 70 3b 20 70 47 72 6f  ps; pGroup; pGro
9a20: 75 70 3d 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74  up=pGroup->pNext
9a30: 29 7b 0a 20 20 20 20 70 47 72 6f 75 70 54 65 72  ){.    pGroupTer
9a40: 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28 29  m = Tcl_NewObj()
9a50: 3b 0a 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a  ;..    pGroup->z
9a60: 4e 61 6d 65 5b 70 47 72 6f 75 70 2d 3e 6e 4e 61  Name[pGroup->nNa
9a70: 6d 65 5d 20 3d 20 27 5c 30 27 3b 0a 20 20 20 20  me] = '\0';.    
9a80: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
9a90: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
9aa0: 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20   pGroupTerm,.   
9ab0: 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 53 74         Tcl_NewSt
9ac0: 72 69 6e 67 4f 62 6a 28 70 47 72 6f 75 70 2d 3e  ringObj(pGroup->
9ad0: 7a 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a 20 20 20  zName, -1));.   
9ae0: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65   Tcl_ListObjAppe
9af0: 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70  ndElement(interp
9b00: 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20  , pGroupTerm,.  
9b10: 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49          Tcl_NewI
9b20: 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 6e 4e  ntObj(pGroup->nN
9b30: 61 6d 65 29 29 3b 0a 20 20 20 20 54 63 6c 5f 4c  ame));.    Tcl_L
9b40: 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d  istObjAppendElem
9b50: 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f  ent(interp, pGro
9b60: 75 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20  upTerm,.        
9b70: 20 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28    Tcl_NewIntObj(
9b80: 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73 29 29 3b  pGroup->flags));
9b90: 0a 0a 20 20 20 20 2f 2a 20 63 6f 75 6e 74 20 6e  ..    /* count n
9ba0: 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73 20  umber of chunks 
9bb0: 77 69 74 68 20 6f 70 65 6e 20 68 61 6e 64 6c 65  with open handle
9bc0: 73 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d 30  s */.    for(i=0
9bd0: 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 4d 61 78  ; i<pGroup->nMax
9be0: 43 68 75 6e 6b 73 3b 20 69 2b 2b 29 7b 0a 20 20  Chunks; i++){.  
9bf0: 20 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e      if( pGroup->
9c00: 62 4f 70 65 6e 5b 69 5d 20 29 20 6e 43 68 75 6e  bOpen[i] ) nChun
9c10: 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20 20 20  ks++;.    }.    
9c20: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
9c30: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
9c40: 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20   pGroupTerm,.   
9c50: 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e         Tcl_NewIn
9c60: 74 4f 62 6a 28 6e 43 68 75 6e 6b 73 29 29 3b 0a  tObj(nChunks));.
9c70: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
9c80: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
9c90: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
9ca0: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
9cb0: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
9cc0: 2d 3e 6e 43 68 75 6e 6b 53 69 7a 65 29 29 3b 0a  ->nChunkSize));.
9cd0: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
9ce0: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
9cf0: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
9d00: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
9d10: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
9d20: 3e 6e 4d 61 78 43 68 75 6e 6b 73 29 29 3b 0a 0a  >nMaxChunks));..
9d30: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
9d40: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
9d50: 65 72 70 2c 20 70 52 65 73 75 6c 74 2c 20 70 47  erp, pResult, pG
9d60: 72 6f 75 70 54 65 72 6d 29 3b 0a 20 20 7d 0a 20  roupTerm);.  }. 
9d70: 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28   multiplexLeave(
9d80: 29 3b 0a 20 20 54 63 6c 5f 53 65 74 4f 62 6a 52  );.  Tcl_SetObjR
9d90: 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 70 52  esult(interp, pR
9da0: 65 73 75 6c 74 29 3b 0a 20 20 72 65 74 75 72 6e  esult);.  return
9db0: 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a   TCL_OK;.}../*.*
9dc0: 2a 20 54 63 6c 63 6d 64 3a 20 74 65 73 74 5f 6d  * Tclcmd: test_m
9dd0: 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c  ultiplex_control
9de0: 20 48 41 4e 44 4c 45 20 44 42 4e 41 4d 45 20 53   HANDLE DBNAME S
9df0: 55 42 2d 43 4f 4d 4d 41 4e 44 20 3f 49 4e 54 2d  UB-COMMAND ?INT-
9e00: 56 41 4c 55 45 3f 0a 2a 2f 0a 73 74 61 74 69 63  VALUE?.*/.static
9e10: 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69 70   int test_multip
9e20: 6c 65 78 5f 63 6f 6e 74 72 6f 6c 28 0a 20 20 43  lex_control(.  C
9e30: 6c 69 65 6e 74 44 61 74 61 20 63 64 2c 0a 20 20  lientData cd,.  
9e40: 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65  Tcl_Interp *inte
9e50: 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a  rp,.  int objc,.
9e60: 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54    Tcl_Obj *CONST
9e70: 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74   objv[].){.  int
9e80: 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20   rc;            
9e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9ea0: 52 65 74 75 72 6e 20 63 6f 64 65 20 66 72 6f 6d  Return code from
9eb0: 20 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 29 20   file_control() 
9ec0: 2a 2f 0a 20 20 69 6e 74 20 69 64 78 3b 20 20 20  */.  int idx;   
9ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9ee0: 20 20 20 20 20 2f 2a 20 49 6e 64 65 78 20 69 6e       /* Index in
9ef0: 20 61 53 75 62 5b 5d 20 2a 2f 0a 20 20 54 63 6c   aSub[] */.  Tcl
9f00: 5f 43 6d 64 49 6e 66 6f 20 63 6d 64 49 6e 66 6f  _CmdInfo cmdInfo
9f10: 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ;            /* 
9f20: 43 6f 6d 6d 61 6e 64 20 69 6e 66 6f 20 73 74 72  Command info str
9f30: 75 63 74 75 72 65 20 66 6f 72 20 48 41 4e 44 4c  ucture for HANDL
9f40: 45 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 20 2a  E */.  sqlite3 *
9f50: 64 62 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  db;             
9f60: 20 20 20 20 20 20 20 2f 2a 20 55 6e 64 65 72 6c         /* Underl
9f70: 79 69 6e 67 20 64 62 20 68 61 6e 64 6c 65 20 66  ying db handle f
9f80: 6f 72 20 48 41 4e 44 4c 45 20 2a 2f 0a 20 20 69  or HANDLE */.  i
9f90: 6e 74 20 69 56 61 6c 75 65 20 3d 20 30 3b 0a 20  nt iValue = 0;. 
9fa0: 20 76 6f 69 64 20 2a 70 41 72 67 20 3d 20 30 3b   void *pArg = 0;
9fb0: 0a 0a 20 20 73 74 72 75 63 74 20 53 75 62 43 6f  ..  struct SubCo
9fc0: 6d 6d 61 6e 64 20 7b 0a 20 20 20 20 63 6f 6e 73  mmand {.    cons
9fd0: 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20  t char *zName;. 
9fe0: 20 20 20 69 6e 74 20 6f 70 3b 0a 20 20 20 20 69     int op;.    i
9ff0: 6e 74 20 61 72 67 74 79 70 65 3b 0a 20 20 7d 20  nt argtype;.  } 
a000: 61 53 75 62 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b  aSub[] = {.    {
a010: 20 22 65 6e 61 62 6c 65 22 2c 20 20 20 20 20 20   "enable",      
a020: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
a030: 45 4e 41 42 4c 45 2c 20 20 20 20 20 20 20 20 20  ENABLE,         
a040: 20 20 31 20 7d 2c 0a 20 20 20 20 7b 20 22 63 68    1 },.    { "ch
a050: 75 6e 6b 5f 73 69 7a 65 22 2c 20 20 20 4d 55 4c  unk_size",   MUL
a060: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f  TIPLEX_CTRL_SET_
a070: 43 48 55 4e 4b 5f 53 49 5a 45 2c 20 20 20 31 20  CHUNK_SIZE,   1 
a080: 7d 2c 0a 20 20 20 20 7b 20 22 6d 61 78 5f 63 68  },.    { "max_ch
a090: 75 6e 6b 73 22 2c 20 20 20 4d 55 4c 54 49 50 4c  unks",   MULTIPL
a0a0: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41 58 5f  EX_CTRL_SET_MAX_
a0b0: 43 48 55 4e 4b 53 2c 20 20 20 31 20 7d 2c 0a 20  CHUNKS,   1 },. 
a0c0: 20 20 20 7b 20 30 2c 20 30 2c 20 30 20 7d 0a 20     { 0, 0, 0 }. 
a0d0: 20 7d 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63 21   };..  if( objc!
a0e0: 3d 35 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72  =5 ){.    Tcl_Wr
a0f0: 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72  ongNumArgs(inter
a100: 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 48 41 4e  p, 1, objv, "HAN
a110: 44 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43  DLE DBNAME SUB-C
a120: 4f 4d 4d 41 4e 44 20 49 4e 54 2d 56 41 4c 55 45  OMMAND INT-VALUE
a130: 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54  ");.    return T
a140: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20  CL_ERROR;.  }.. 
a150: 20 69 66 28 20 30 3d 3d 54 63 6c 5f 47 65 74 43   if( 0==Tcl_GetC
a160: 6f 6d 6d 61 6e 64 49 6e 66 6f 28 69 6e 74 65 72  ommandInfo(inter
a170: 70 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67  p, Tcl_GetString
a180: 28 6f 62 6a 76 5b 31 5d 29 2c 20 26 63 6d 64 49  (objv[1]), &cmdI
a190: 6e 66 6f 29 20 29 7b 0a 20 20 20 20 54 63 6c 5f  nfo) ){.    Tcl_
a1a0: 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e 74  AppendResult(int
a1b0: 65 72 70 2c 20 22 65 78 70 65 63 74 65 64 20 64  erp, "expected d
a1c0: 61 74 61 62 61 73 65 20 68 61 6e 64 6c 65 2c 20  atabase handle, 
a1d0: 67 6f 74 20 5c 22 22 2c 20 30 29 3b 0a 20 20 20  got \"", 0);.   
a1e0: 20 54 63 6c 5f 41 70 70 65 6e 64 52 65 73 75 6c   Tcl_AppendResul
a1f0: 74 28 69 6e 74 65 72 70 2c 20 54 63 6c 5f 47 65  t(interp, Tcl_Ge
a200: 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 31 5d 29  tString(objv[1])
a210: 2c 20 22 5c 22 22 2c 20 30 29 3b 0a 20 20 20 20  , "\"", 0);.    
a220: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
a230: 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 64  ;.  }else{.    d
a240: 62 20 3d 20 2a 28 73 71 6c 69 74 65 33 20 2a 2a  b = *(sqlite3 **
a250: 29 63 6d 64 49 6e 66 6f 2e 6f 62 6a 43 6c 69 65  )cmdInfo.objClie
a260: 6e 74 44 61 74 61 3b 0a 20 20 7d 0a 0a 20 20 72  ntData;.  }..  r
a270: 63 20 3d 20 54 63 6c 5f 47 65 74 49 6e 64 65 78  c = Tcl_GetIndex
a280: 46 72 6f 6d 4f 62 6a 53 74 72 75 63 74 28 0a 20  FromObjStruct(. 
a290: 20 20 20 20 20 69 6e 74 65 72 70 2c 20 6f 62 6a       interp, obj
a2a0: 76 5b 33 5d 2c 20 61 53 75 62 2c 20 73 69 7a 65  v[3], aSub, size
a2b0: 6f 66 28 61 53 75 62 5b 30 5d 29 2c 20 22 73 75  of(aSub[0]), "su
a2c0: 62 2d 63 6f 6d 6d 61 6e 64 22 2c 20 30 2c 20 26  b-command", 0, &
a2d0: 69 64 78 0a 20 20 29 3b 0a 20 20 69 66 28 20 72  idx.  );.  if( r
a2e0: 63 21 3d 54 43 4c 5f 4f 4b 20 29 20 72 65 74 75  c!=TCL_OK ) retu
a2f0: 72 6e 20 72 63 3b 0a 0a 20 20 73 77 69 74 63 68  rn rc;..  switch
a300: 28 20 61 53 75 62 5b 69 64 78 5d 2e 61 72 67 74  ( aSub[idx].argt
a310: 79 70 65 20 29 7b 0a 20 20 20 20 63 61 73 65 20  ype ){.    case 
a320: 31 3a 0a 20 20 20 20 20 20 69 66 28 20 54 63 6c  1:.      if( Tcl
a330: 5f 47 65 74 49 6e 74 46 72 6f 6d 4f 62 6a 28 69  _GetIntFromObj(i
a340: 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 34 5d 2c 20  nterp, objv[4], 
a350: 26 69 56 61 6c 75 65 29 20 29 7b 0a 20 20 20 20  &iValue) ){.    
a360: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
a370: 52 52 4f 52 3b 0a 20 20 20 20 20 20 7d 0a 20 20  RROR;.      }.  
a380: 20 20 20 20 70 41 72 67 20 3d 20 28 76 6f 69 64      pArg = (void
a390: 20 2a 29 26 69 56 61 6c 75 65 3b 0a 20 20 20 20   *)&iValue;.    
a3a0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 64 65 66    break;.    def
a3b0: 61 75 6c 74 3a 0a 20 20 20 20 20 20 54 63 6c 5f  ault:.      Tcl_
a3c0: 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74  WrongNumArgs(int
a3d0: 65 72 70 2c 20 34 2c 20 6f 62 6a 76 2c 20 22 53  erp, 4, objv, "S
a3e0: 55 42 2d 43 4f 4d 4d 41 4e 44 22 29 3b 0a 20 20  UB-COMMAND");.  
a3f0: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
a400: 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 72 63 20  RROR;.  }..  rc 
a410: 3d 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f 63  = sqlite3_file_c
a420: 6f 6e 74 72 6f 6c 28 64 62 2c 20 54 63 6c 5f 47  ontrol(db, Tcl_G
a430: 65 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 32 5d  etString(objv[2]
a440: 29 2c 20 61 53 75 62 5b 69 64 78 5d 2e 6f 70 2c  ), aSub[idx].op,
a450: 20 70 41 72 67 29 3b 0a 20 20 54 63 6c 5f 53 65   pArg);.  Tcl_Se
a460: 74 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20  tResult(interp, 
a470: 28 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54  (char *)sqlite3T
a480: 65 73 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29  estErrorName(rc)
a490: 2c 20 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 20  , TCL_STATIC);. 
a4a0: 20 72 65 74 75 72 6e 20 28 72 63 3d 3d 53 51 4c   return (rc==SQL
a4b0: 49 54 45 5f 4f 4b 29 20 3f 20 54 43 4c 5f 4f 4b  ITE_OK) ? TCL_OK
a4c0: 20 3a 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 7d 0a   : TCL_ERROR;.}.
a4d0: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74  ./*.** This rout
a4e0: 69 6e 65 20 72 65 67 69 73 74 65 72 73 20 74 68  ine registers th
a4f0: 65 20 63 75 73 74 6f 6d 20 54 43 4c 20 63 6f 6d  e custom TCL com
a500: 6d 61 6e 64 73 20 64 65 66 69 6e 65 64 20 69 6e  mands defined in
a510: 20 74 68 69 73 0a 2a 2a 20 6d 6f 64 75 6c 65 2e   this.** module.
a520: 20 20 54 68 69 73 20 73 68 6f 75 6c 64 20 62 65    This should be
a530: 20 74 68 65 20 6f 6e 6c 79 20 70 72 6f 63 65 64   the only proced
a540: 75 72 65 20 76 69 73 69 62 6c 65 20 66 72 6f 6d  ure visible from
a550: 20 6f 75 74 73 69 64 65 0a 2a 2a 20 6f 66 20 74   outside.** of t
a560: 68 69 73 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 69  his module..*/.i
a570: 6e 74 20 53 71 6c 69 74 65 6d 75 6c 74 69 70 6c  nt Sqlitemultipl
a580: 65 78 5f 49 6e 69 74 28 54 63 6c 5f 49 6e 74 65  ex_Init(Tcl_Inte
a590: 72 70 20 2a 69 6e 74 65 72 70 29 7b 0a 20 20 73  rp *interp){.  s
a5a0: 74 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a 20  tatic struct {. 
a5b0: 20 20 20 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b      char *zName;
a5c0: 0a 20 20 20 20 20 54 63 6c 5f 4f 62 6a 43 6d 64  .     Tcl_ObjCmd
a5d0: 50 72 6f 63 20 2a 78 50 72 6f 63 3b 0a 20 20 7d  Proc *xProc;.  }
a5e0: 20 61 43 6d 64 5b 5d 20 3d 20 7b 0a 20 20 20 20   aCmd[] = {.    
a5f0: 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69  { "sqlite3_multi
a600: 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 22  plex_initialize"
a610: 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78  , test_multiplex
a620: 5f 69 6e 69 74 69 61 6c 69 7a 65 20 7d 2c 0a 20  _initialize },. 
a630: 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75     { "sqlite3_mu
a640: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
a650: 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65  ", test_multiple
a660: 78 5f 73 68 75 74 64 6f 77 6e 20 7d 2c 0a 20 20  x_shutdown },.  
a670: 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c    { "sqlite3_mul
a680: 74 69 70 6c 65 78 5f 64 75 6d 70 22 2c 20 74 65  tiplex_dump", te
a690: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d  st_multiplex_dum
a6a0: 70 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c 69  p },.    { "sqli
a6b0: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 63 6f  te3_multiplex_co
a6c0: 6e 74 72 6f 6c 22 2c 20 74 65 73 74 5f 6d 75 6c  ntrol", test_mul
a6d0: 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20 7d  tiplex_control }
a6e0: 2c 0a 20 20 7d 3b 0a 20 20 69 6e 74 20 69 3b 0a  ,.  };.  int i;.
a6f0: 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 73 69  .  for(i=0; i<si
a700: 7a 65 6f 66 28 61 43 6d 64 29 2f 73 69 7a 65 6f  zeof(aCmd)/sizeo
a710: 66 28 61 43 6d 64 5b 30 5d 29 3b 20 69 2b 2b 29  f(aCmd[0]); i++)
a720: 7b 0a 20 20 20 20 54 63 6c 5f 43 72 65 61 74 65  {.    Tcl_Create
a730: 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74 65 72  ObjCommand(inter
a740: 70 2c 20 61 43 6d 64 5b 69 5d 2e 7a 4e 61 6d 65  p, aCmd[i].zName
a750: 2c 20 61 43 6d 64 5b 69 5d 2e 78 50 72 6f 63 2c  , aCmd[i].xProc,
a760: 20 30 2c 20 30 29 3b 0a 20 20 7d 0a 0a 20 20 72   0, 0);.  }..  r
a770: 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a  eturn TCL_OK;.}.
a780: 23 65 6e 64 69 66 0a                             #endif.