/ Hex Artifact Content
Login

Artifact 655cb3b663f87db7d3d2427ea127c9daacae4abc:


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 2e 0a 2a 2a 0a 2a 2a 20 54  eal VFS..**.** T
01e0: 68 69 73 20 70 61 72 74 69 63 75 6c 61 72 20 73  his particular s
01f0: 68 69 6d 20 65 6e 66 6f 72 63 65 73 20 61 20 6d  him enforces a m
0200: 75 6c 74 69 70 6c 65 78 20 73 79 73 74 65 6d 20  ultiplex system 
0210: 6f 6e 20 44 42 20 66 69 6c 65 73 2e 20 20 0a 2a  on DB files.  .*
0220: 2a 20 54 68 69 73 20 73 68 69 6d 20 73 68 61 72  * This shim shar
0230: 64 73 2f 70 61 72 74 69 74 69 6f 6e 73 20 61 20  ds/partitions a 
0240: 73 69 6e 67 6c 65 20 44 42 20 66 69 6c 65 20 69  single DB file i
0250: 6e 74 6f 20 73 6d 61 6c 6c 65 72 20 0a 2a 2a 20  nto smaller .** 
0260: 22 63 68 75 6e 6b 73 22 20 73 75 63 68 20 74 68  "chunks" such th
0270: 61 74 20 74 68 65 20 74 6f 74 61 6c 20 44 42 20  at the total DB 
0280: 66 69 6c 65 20 73 69 7a 65 20 6d 61 79 20 65 78  file size may ex
0290: 63 65 65 64 20 74 68 65 20 6d 61 78 69 6d 75 6d  ceed the maximum
02a0: 0a 2a 2a 20 66 69 6c 65 20 73 69 7a 65 20 6f 66  .** file size of
02b0: 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20   the underlying 
02c0: 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a 2a 0a  file system..**.
02d0: 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22 73 71 6c  */.#include "sql
02e0: 69 74 65 33 2e 68 22 0a 23 69 6e 63 6c 75 64 65  ite3.h".#include
02f0: 20 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63   <string.h>.#inc
0300: 6c 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a  lude <assert.h>.
0310: 23 69 6e 63 6c 75 64 65 20 22 73 71 6c 69 74 65  #include "sqlite
0320: 49 6e 74 2e 68 22 0a 0a 2f 2a 0a 2a 2a 20 46 6f  Int.h"../*.** Fo
0330: 72 20 61 20 62 75 69 6c 64 20 77 69 74 68 6f 75  r a build withou
0340: 74 20 6d 75 74 65 78 65 73 2c 20 6e 6f 2d 6f 70  t mutexes, no-op
0350: 20 74 68 65 20 6d 75 74 65 78 20 63 61 6c 6c 73   the mutex calls
0360: 2e 0a 2a 2f 0a 23 69 66 20 64 65 66 69 6e 65 64  ..*/.#if defined
0370: 28 53 51 4c 49 54 45 5f 54 48 52 45 41 44 53 41  (SQLITE_THREADSA
0380: 46 45 29 20 26 26 20 53 51 4c 49 54 45 5f 54 48  FE) && SQLITE_TH
0390: 52 45 41 44 53 41 46 45 3d 3d 30 0a 23 64 65 66  READSAFE==0.#def
03a0: 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  ine sqlite3_mute
03b0: 78 5f 61 6c 6c 6f 63 28 58 29 20 20 20 20 28 28  x_alloc(X)    ((
03c0: 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 2a 29 38  sqlite3_mutex*)8
03d0: 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65  ).#define sqlite
03e0: 33 5f 6d 75 74 65 78 5f 66 72 65 65 28 58 29 0a  3_mutex_free(X).
03f0: 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f  #define sqlite3_
0400: 6d 75 74 65 78 5f 65 6e 74 65 72 28 58 29 0a 23  mutex_enter(X).#
0410: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0420: 75 74 65 78 5f 74 72 79 28 58 29 20 20 20 20 20  utex_try(X)     
0430: 20 53 51 4c 49 54 45 5f 4f 4b 0a 23 64 65 66 69   SQLITE_OK.#defi
0440: 6e 65 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  ne sqlite3_mutex
0450: 5f 6c 65 61 76 65 28 58 29 0a 23 64 65 66 69 6e  _leave(X).#defin
0460: 65 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  e sqlite3_mutex_
0470: 68 65 6c 64 28 58 29 20 20 20 20 20 28 28 76 6f  held(X)     ((vo
0480: 69 64 29 28 58 29 2c 31 29 0a 23 64 65 66 69 6e  id)(X),1).#defin
0490: 65 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  e sqlite3_mutex_
04a0: 6e 6f 74 68 65 6c 64 28 58 29 20 20 28 28 76 6f  notheld(X)  ((vo
04b0: 69 64 29 28 58 29 2c 31 29 0a 23 65 6e 64 69 66  id)(X),1).#endif
04c0: 20 2f 2a 20 53 51 4c 49 54 45 5f 54 48 52 45 41   /* SQLITE_THREA
04d0: 44 53 41 46 45 3d 3d 30 20 2a 2f 0a 0a 0a 2f 2a  DSAFE==0 */.../*
04e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
04f0: 2a 2a 2a 2a 2a 2a 2a 20 53 68 69 6d 20 44 65 66  ******* Shim Def
0500: 69 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a  initions *******
0510: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0520: 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 54 68 69  *******/../* Thi
0530: 73 20 69 73 20 74 68 65 20 6c 69 6d 69 74 20 6f  s is the limit o
0540: 6e 20 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65  n the chunk size
0550: 2e 20 20 49 74 20 6d 61 79 20 62 65 20 63 68 61  .  It may be cha
0560: 6e 67 65 64 20 62 79 20 63 61 6c 6c 69 6e 67 0a  nged by calling.
0570: 2a 2a 20 74 68 65 20 73 71 6c 69 74 65 33 5f 6d  ** the sqlite3_m
0580: 75 6c 74 69 70 6c 65 78 5f 73 65 74 28 29 20 69  ultiplex_set() i
0590: 6e 74 65 72 66 61 63 65 2e 0a 2a 2f 0a 23 64 65  nterface..*/.#de
05a0: 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54  fine SQLITE_MULT
05b0: 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45  IPLEX_CHUNK_SIZE
05c0: 20 30 78 34 30 30 30 30 30 30 30 0a 2f 2a 20 44   0x40000000./* D
05d0: 65 66 61 75 6c 74 20 6c 69 6d 69 74 20 6f 6e 20  efault limit on 
05e0: 6e 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73  number of chunks
05f0: 2e 20 20 43 61 72 65 20 73 68 6f 75 6c 64 20 62  .  Care should b
0600: 65 20 74 61 6b 65 6e 0a 2a 2a 20 73 6f 20 74 68  e taken.** so th
0610: 61 74 20 76 61 6c 75 65 73 20 66 6f 72 20 63 68  at values for ch
0620: 75 6e 6b 73 20 6e 75 6d 62 65 72 73 20 66 69 74  unks numbers fit
0630: 20 69 6e 20 74 68 65 20 53 51 4c 49 54 45 5f 4d   in the SQLITE_M
0640: 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54  ULTIPLEX_EXT_FMT
0650: 0a 2a 2a 20 66 6f 72 6d 61 74 20 73 70 65 63 69  .** format speci
0660: 66 69 65 72 2e 20 49 74 20 6d 61 79 20 62 65 20  fier. It may be 
0670: 63 68 61 6e 67 65 64 20 62 79 20 63 61 6c 6c 69  changed by calli
0680: 6e 67 0a 2a 2a 20 74 68 65 20 73 71 6c 69 74 65  ng.** the sqlite
0690: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 65 74 28  3_multiplex_set(
06a0: 29 20 69 6e 74 65 72 66 61 63 65 2e 0a 2a 2f 0a  ) interface..*/.
06b0: 23 64 65 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d  #define SQLITE_M
06c0: 55 4c 54 49 50 4c 45 58 5f 4d 41 58 5f 43 48 55  ULTIPLEX_MAX_CHU
06d0: 4e 4b 53 20 33 32 0a 0a 2f 2a 20 49 66 20 53 51  NKS 32../* If SQ
06e0: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
06f0: 58 54 5f 4f 56 57 52 20 69 73 20 64 65 66 69 6e  XT_OVWR is defin
0700: 65 64 2c 20 74 68 65 20 0a 2a 2a 20 6c 61 73 74  ed, the .** last
0710: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0720: 58 5f 45 58 54 5f 53 5a 20 63 68 61 72 61 63 74  X_EXT_SZ charact
0730: 65 72 73 20 6f 66 20 74 68 65 20 0a 2a 2a 20 66  ers of the .** f
0740: 69 6c 65 6e 61 6d 65 20 77 69 6c 6c 20 62 65 20  ilename will be 
0750: 6f 76 65 72 77 72 69 74 74 65 6e 2c 20 6f 74 68  overwritten, oth
0760: 65 72 77 69 73 65 2c 20 74 68 65 20 0a 2a 2a 20  erwise, the .** 
0770: 6d 75 6c 74 69 70 6c 65 78 20 65 78 74 65 6e 73  multiplex extens
0780: 69 6f 6e 20 69 73 20 73 69 6d 70 6c 79 20 61 70  ion is simply ap
0790: 70 65 6e 64 65 64 20 74 6f 20 74 68 65 20 66 69  pended to the fi
07a0: 6c 65 6e 61 6d 65 2e 0a 2a 2a 20 45 78 2e 20 20  lename..** Ex.  
07b0: 28 75 6e 64 65 66 69 6e 65 64 29 20 74 65 73 74  (undefined) test
07c0: 2e 64 62 20 2d 3e 20 74 65 73 74 2e 64 62 30 31  .db -> test.db01
07d0: 0a 2a 2a 20 20 20 20 20 20 28 64 65 66 69 6e 65  .**      (define
07e0: 64 29 20 20 20 74 65 73 74 2e 64 62 20 2d 3e 20  d)   test.db -> 
07f0: 74 65 73 74 2e 30 31 0a 2a 2a 20 43 68 75 6e 6b  test.01.** Chunk
0800: 20 30 20 64 6f 65 73 20 6e 6f 74 20 68 61 76 65   0 does not have
0810: 20 61 20 6d 6f 64 69 66 69 65 64 20 65 78 74 65   a modified exte
0820: 6e 73 69 6f 6e 2e 0a 2a 2f 0a 23 64 65 66 69 6e  nsion..*/.#defin
0830: 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  e SQLITE_MULTIPL
0840: 45 58 5f 45 58 54 5f 46 4d 54 20 20 20 20 22 25  EX_EXT_FMT    "%
0850: 30 32 64 22 0a 23 64 65 66 69 6e 65 20 53 51 4c  02d".#define SQL
0860: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
0870: 54 5f 53 5a 20 20 20 20 20 32 0a 0a 2f 2a 2a 2a  T_SZ     2../***
0880: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0890: 2a 2a 2a 2a 2a 20 4f 62 6a 65 63 74 20 44 65 66  ***** Object Def
08a0: 69 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a  initions *******
08b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
08c0: 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72  *******/../* For
08d0: 77 61 72 64 20 64 65 63 6c 61 72 61 74 69 6f 6e  ward declaration
08e0: 20 6f 66 20 61 6c 6c 20 6f 62 6a 65 63 74 20 74   of all object t
08f0: 79 70 65 73 20 2a 2f 0a 74 79 70 65 64 65 66 20  ypes */.typedef 
0900: 73 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78  struct multiplex
0910: 47 72 6f 75 70 20 6d 75 6c 74 69 70 6c 65 78 47  Group multiplexG
0920: 72 6f 75 70 3b 0a 74 79 70 65 64 65 66 20 73 74  roup;.typedef st
0930: 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ruct multiplexCo
0940: 6e 6e 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  nn multiplexConn
0950: 3b 0a 0a 2f 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74  ;../*.** A "mult
0960: 69 70 6c 65 78 20 67 72 6f 75 70 22 20 69 73 20  iplex group" is 
0970: 61 20 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f 66 20  a collection of 
0980: 66 69 6c 65 73 20 74 68 61 74 20 63 6f 6c 6c 65  files that colle
0990: 63 74 69 76 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75  ctively.** makeu
09a0: 70 20 61 20 73 69 6e 67 6c 65 20 53 51 4c 69 74  p a single SQLit
09b0: 65 20 44 42 20 66 69 6c 65 2e 20 20 54 68 69 73  e DB file.  This
09c0: 20 61 6c 6c 6f 77 73 20 74 68 65 20 73 69 7a 65   allows the size
09d0: 20 6f 66 20 74 68 65 20 44 42 0a 2a 2a 20 74 6f   of the DB.** to
09e0: 20 65 78 63 65 65 64 20 74 68 65 20 6c 69 6d 69   exceed the limi
09f0: 74 73 20 69 6d 70 6f 73 65 64 20 62 79 20 74 68  ts imposed by th
0a00: 65 20 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a  e file system..*
0a10: 2a 0a 2a 2a 20 54 68 65 72 65 20 69 73 20 61 6e  *.** There is an
0a20: 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65   instance of the
0a30: 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63   following objec
0a40: 74 20 66 6f 72 20 65 61 63 68 20 64 65 66 69 6e  t for each defin
0a50: 65 64 20 6d 75 6c 74 69 70 6c 65 78 0a 2a 2a 20  ed multiplex.** 
0a60: 67 72 6f 75 70 2e 0a 2a 2f 0a 73 74 72 75 63 74  group..*/.struct
0a70: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
0a80: 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  {.  sqlite3_file
0a90: 20 2a 2a 70 52 65 61 6c 3b 20 20 20 20 20 20 20   **pReal;       
0aa0: 20 20 20 20 20 2f 2a 20 48 61 6e 64 6c 65 73 20       /* Handles 
0ab0: 74 6f 20 65 61 63 68 20 63 68 75 6e 6b 20 2a 2f  to each chunk */
0ac0: 0a 20 20 63 68 61 72 20 2a 62 4f 70 65 6e 3b 20  .  char *bOpen; 
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ae0: 20 20 20 20 2f 2a 20 61 72 72 61 79 20 6f 66 20      /* array of 
0af0: 62 6f 6f 6c 73 20 2d 20 30 20 69 66 20 63 68 75  bools - 0 if chu
0b00: 6e 6b 20 6e 6f 74 20 6f 70 65 6e 65 64 20 2a 2f  nk not opened */
0b10: 0a 20 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20  .  char *zName; 
0b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b30: 20 20 20 20 2f 2a 20 42 61 73 65 20 66 69 6c 65      /* Base file
0b40: 6e 61 6d 65 20 6f 66 20 74 68 69 73 20 67 72 6f  name of this gro
0b50: 75 70 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d  up */.  int nNam
0b60: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
0b70: 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67           /* Leng
0b80: 74 68 20 6f 66 20 62 61 73 65 20 66 69 6c 65 6e  th of base filen
0b90: 61 6d 65 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61  ame */.  int fla
0ba0: 67 73 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  gs;             
0bb0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61            /* Fla
0bc0: 67 73 20 75 73 65 64 20 66 6f 72 20 6f 72 69 67  gs used for orig
0bd0: 69 6e 61 6c 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a  inal opening */.
0be0: 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70    multiplexGroup
0bf0: 20 2a 70 4e 65 78 74 2c 20 2a 70 50 72 65 76 3b   *pNext, *pPrev;
0c00: 20 20 20 2f 2a 20 44 6f 75 62 6c 79 20 6c 69 6e     /* Doubly lin
0c10: 6b 65 64 20 6c 69 73 74 20 6f 66 20 61 6c 6c 20  ked list of all 
0c20: 67 72 6f 75 70 20 6f 62 6a 65 63 74 73 20 2a 2f  group objects */
0c30: 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6e 20 69 6e  .};../*.** An in
0c40: 73 74 61 6e 63 65 20 6f 66 20 74 68 65 20 66 6f  stance of the fo
0c50: 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74 20 72  llowing object r
0c60: 65 70 72 65 73 65 6e 74 73 20 65 61 63 68 20 6f  epresents each o
0c70: 70 65 6e 20 63 6f 6e 6e 65 63 74 69 6f 6e 0a 2a  pen connection.*
0c80: 2a 20 74 6f 20 61 20 66 69 6c 65 20 74 68 61 74  * to a file that
0c90: 20 69 73 20 6d 75 6c 74 69 70 6c 65 78 27 65 64   is multiplex'ed
0ca0: 2e 20 20 54 68 69 73 20 6f 62 6a 65 63 74 20 69  .  This object i
0cb0: 73 20 61 20 0a 2a 2a 20 73 75 62 63 6c 61 73 73  s a .** subclass
0cc0: 20 6f 66 20 73 71 6c 69 74 65 33 5f 66 69 6c 65   of sqlite3_file
0cd0: 2e 20 20 54 68 65 20 73 71 6c 69 74 65 33 5f 66  .  The sqlite3_f
0ce0: 69 6c 65 20 6f 62 6a 65 63 74 20 66 6f 72 20 74  ile object for t
0cf0: 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 0a 2a 2a  he underlying.**
0d00: 20 56 46 53 20 69 73 20 61 70 70 65 6e 64 65 64   VFS is appended
0d10: 20 74 6f 20 74 68 69 73 20 73 74 72 75 63 74 75   to this structu
0d20: 72 65 2e 0a 2a 2f 0a 73 74 72 75 63 74 20 6d 75  re..*/.struct mu
0d30: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 7b 0a 20 20  ltiplexConn {.  
0d40: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 62 61 73  sqlite3_file bas
0d50: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
0d60: 2f 2a 20 42 61 73 65 20 63 6c 61 73 73 20 2d 20  /* Base class - 
0d70: 6d 75 73 74 20 62 65 20 66 69 72 73 74 20 2a 2f  must be first */
0d80: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
0d90: 70 20 2a 70 47 72 6f 75 70 3b 20 20 20 20 20 20  p *pGroup;      
0da0: 20 20 20 2f 2a 20 54 68 65 20 75 6e 64 65 72 6c     /* The underl
0db0: 79 69 6e 67 20 67 72 6f 75 70 20 6f 66 20 66 69  ying group of fi
0dc0: 6c 65 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 2a 2a 2a  les */.};../****
0dd0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0de0: 2a 2a 2a 2a 2a 20 47 6c 6f 62 61 6c 20 56 61 72  ***** Global Var
0df0: 69 61 62 6c 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a  iables *********
0e00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0e10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a  *********/./*.**
0e20: 20 41 6c 6c 20 67 6c 6f 62 61 6c 20 76 61 72 69   All global vari
0e30: 61 62 6c 65 73 20 75 73 65 64 20 62 79 20 74 68  ables used by th
0e40: 69 73 20 66 69 6c 65 20 61 72 65 20 63 6f 6e 74  is file are cont
0e50: 61 69 6e 69 6e 67 20 77 69 74 68 69 6e 20 74 68  aining within th
0e60: 65 20 66 6f 6c 6c 6f 77 69 6e 67 0a 2a 2a 20 67  e following.** g
0e70: 4d 75 6c 74 69 70 6c 65 78 20 73 74 72 75 63 74  Multiplex struct
0e80: 75 72 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73  ure..*/.static s
0e90: 74 72 75 63 74 20 7b 0a 20 20 2f 2a 20 54 68 65  truct {.  /* The
0ea0: 20 70 4f 72 69 67 56 66 73 20 69 73 20 74 68 65   pOrigVfs is the
0eb0: 20 72 65 61 6c 2c 20 6f 72 69 67 69 6e 61 6c 20   real, original 
0ec0: 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20 69  underlying VFS i
0ed0: 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 2e 0a 20  mplementation.. 
0ee0: 20 2a 2a 20 4d 6f 73 74 20 6f 70 65 72 61 74 69   ** Most operati
0ef0: 6f 6e 73 20 70 61 73 73 2d 74 68 72 6f 75 67 68  ons pass-through
0f00: 20 74 6f 20 74 68 65 20 72 65 61 6c 20 56 46 53   to the real VFS
0f10: 2e 20 20 54 68 69 73 20 76 61 6c 75 65 20 69 73  .  This value is
0f20: 20 72 65 61 64 2d 6f 6e 6c 79 0a 20 20 2a 2a 20   read-only.  ** 
0f30: 64 75 72 69 6e 67 20 6f 70 65 72 61 74 69 6f 6e  during operation
0f40: 2e 20 20 49 74 20 69 73 20 6f 6e 6c 79 20 6d 6f  .  It is only mo
0f50: 64 69 66 69 65 64 20 61 74 20 73 74 61 72 74 2d  dified at start-
0f60: 74 69 6d 65 20 61 6e 64 20 74 68 75 73 20 64 6f  time and thus do
0f70: 65 73 20 6e 6f 74 0a 20 20 2a 2a 20 72 65 71 75  es not.  ** requ
0f80: 69 72 65 20 61 20 6d 75 74 65 78 2e 0a 20 20 2a  ire a mutex..  *
0f90: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  /.  sqlite3_vfs 
0fa0: 2a 70 4f 72 69 67 56 66 73 3b 0a 0a 20 20 2f 2a  *pOrigVfs;..  /*
0fb0: 20 54 68 65 20 73 54 68 69 73 56 66 73 20 69 73   The sThisVfs is
0fc0: 20 74 68 65 20 56 46 53 20 73 74 72 75 63 74 75   the VFS structu
0fd0: 72 65 20 75 73 65 64 20 62 79 20 74 68 69 73 20  re used by this 
0fe0: 73 68 69 6d 2e 20 20 49 74 20 69 73 20 69 6e 69  shim.  It is ini
0ff0: 74 69 61 6c 69 7a 65 64 0a 20 20 2a 2a 20 61 74  tialized.  ** at
1000: 20 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20   start-time and 
1010: 74 68 75 73 20 64 6f 65 73 20 6e 6f 74 20 72 65  thus does not re
1020: 71 75 69 72 65 20 61 20 6d 75 74 65 78 0a 20 20  quire a mutex.  
1030: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73  */.  sqlite3_vfs
1040: 20 73 54 68 69 73 56 66 73 3b 0a 0a 20 20 2f 2a   sThisVfs;..  /*
1050: 20 54 68 65 20 73 49 6f 4d 65 74 68 6f 64 73 20   The sIoMethods 
1060: 64 65 66 69 6e 65 73 20 74 68 65 20 6d 65 74 68  defines the meth
1070: 6f 64 73 20 75 73 65 64 20 62 79 20 73 71 6c 69  ods used by sqli
1080: 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74 73  te3_file objects
1090: 20 0a 20 20 2a 2a 20 61 73 73 6f 63 69 61 74 65   .  ** associate
10a0: 64 20 77 69 74 68 20 74 68 69 73 20 73 68 69 6d  d with this shim
10b0: 2e 20 20 49 74 20 69 73 20 69 6e 69 74 69 61 6c  .  It is initial
10c0: 69 7a 65 64 20 61 74 20 73 74 61 72 74 2d 74 69  ized at start-ti
10d0: 6d 65 20 61 6e 64 20 64 6f 65 73 0a 20 20 2a 2a  me and does.  **
10e0: 20 6e 6f 74 20 72 65 71 75 69 72 65 20 61 20 6d   not require a m
10f0: 75 74 65 78 2e 0a 20 20 2a 2a 0a 20 20 2a 2a 20  utex..  **.  ** 
1100: 57 68 65 6e 20 74 68 65 20 75 6e 64 65 72 6c 79  When the underly
1110: 69 6e 67 20 56 46 53 20 69 73 20 63 61 6c 6c 65  ing VFS is calle
1120: 64 20 74 6f 20 6f 70 65 6e 20 61 20 66 69 6c 65  d to open a file
1130: 2c 20 69 74 20 6d 69 67 68 74 20 72 65 74 75 72  , it might retur
1140: 6e 20 0a 20 20 2a 2a 20 65 69 74 68 65 72 20 61  n .  ** either a
1150: 20 76 65 72 73 69 6f 6e 20 31 20 6f 72 20 61 20   version 1 or a 
1160: 76 65 72 73 69 6f 6e 20 32 20 73 71 6c 69 74 65  version 2 sqlite
1170: 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74 2e 20 20  3_file object.  
1180: 54 68 69 73 20 73 68 69 6d 0a 20 20 2a 2a 20 68  This shim.  ** h
1190: 61 73 20 74 6f 20 63 72 65 61 74 65 20 61 20 77  as to create a w
11a0: 72 61 70 70 65 72 20 73 71 6c 69 74 65 33 5f 66  rapper sqlite3_f
11b0: 69 6c 65 20 6f 66 20 74 68 65 20 73 61 6d 65 20  ile of the same 
11c0: 76 65 72 73 69 6f 6e 2e 20 20 48 65 6e 63 65 0a  version.  Hence.
11d0: 20 20 2a 2a 20 74 68 65 72 65 20 61 72 65 20 74    ** there are t
11e0: 77 6f 20 49 2f 4f 20 6d 65 74 68 6f 64 20 73 74  wo I/O method st
11f0: 72 75 63 74 75 72 65 73 2c 20 6f 6e 65 20 66 6f  ructures, one fo
1200: 72 20 76 65 72 73 69 6f 6e 20 31 20 61 6e 64 20  r version 1 and 
1210: 74 68 65 20 6f 74 68 65 72 0a 20 20 2a 2a 20 66  the other.  ** f
1220: 6f 72 20 76 65 72 73 69 6f 6e 20 32 2e 0a 20 20  or version 2..  
1230: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 69 6f 5f  */.  sqlite3_io_
1240: 6d 65 74 68 6f 64 73 20 73 49 6f 4d 65 74 68 6f  methods sIoMetho
1250: 64 73 56 31 3b 0a 20 20 73 71 6c 69 74 65 33 5f  dsV1;.  sqlite3_
1260: 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49 6f 4d 65  io_methods sIoMe
1270: 74 68 6f 64 73 56 32 3b 0a 0a 20 20 2f 2a 20 54  thodsV2;..  /* T
1280: 72 75 65 20 77 68 65 6e 20 74 68 69 73 20 73 68  rue when this sh
1290: 69 6d 20 68 61 73 20 62 65 65 6e 20 69 6e 69 74  im has been init
12a0: 69 61 6c 69 7a 65 64 2e 0a 20 20 2a 2f 0a 20 20  ialized..  */.  
12b0: 69 6e 74 20 69 73 49 6e 69 74 69 61 6c 69 7a 65  int isInitialize
12c0: 64 3b 0a 0a 20 20 2f 2a 20 46 6f 72 20 72 75 6e  d;..  /* For run
12d0: 2d 74 69 6d 65 20 61 63 63 65 73 73 20 61 6e 79  -time access any
12e0: 20 6f 66 20 74 68 65 20 6f 74 68 65 72 20 67 6c   of the other gl
12f0: 6f 62 61 6c 20 64 61 74 61 20 73 74 72 75 63 74  obal data struct
1300: 75 72 65 73 20 69 6e 20 74 68 69 73 0a 20 20 2a  ures in this.  *
1310: 2a 20 73 68 69 6d 2c 20 74 68 65 20 66 6f 6c 6c  * shim, the foll
1320: 6f 77 69 6e 67 20 6d 75 74 65 78 20 6d 75 73 74  owing mutex must
1330: 20 62 65 20 68 65 6c 64 2e 0a 20 20 2a 2f 0a 20   be held..  */. 
1340: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 20 2a   sqlite3_mutex *
1350: 70 4d 75 74 65 78 3b 0a 0a 20 20 2f 2a 20 4c 69  pMutex;..  /* Li
1360: 73 74 20 6f 66 20 6d 75 6c 74 69 70 6c 65 78 47  st of multiplexG
1370: 72 6f 75 70 20 6f 62 6a 65 63 74 73 2e 0a 20 20  roup objects..  
1380: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  */.  multiplexGr
1390: 6f 75 70 20 2a 70 47 72 6f 75 70 73 3b 0a 0a 20  oup *pGroups;.. 
13a0: 20 2f 2a 20 43 68 75 6e 6b 20 70 61 72 61 6d 73   /* Chunk params
13b0: 2e 0a 20 20 2a 2f 0a 20 20 69 6e 74 20 6e 43 68  ..  */.  int nCh
13c0: 75 6e 6b 53 69 7a 65 3b 0a 20 20 69 6e 74 20 6e  unkSize;.  int n
13d0: 4d 61 78 43 68 75 6e 6b 73 3b 0a 0a 20 20 2f 2a  MaxChunks;..  /*
13e0: 20 53 74 6f 72 61 67 65 20 66 6f 72 20 74 65 6d   Storage for tem
13f0: 70 20 66 69 6c 65 20 6e 61 6d 65 73 2e 20 20 41  p file names.  A
1400: 6c 6c 6f 63 61 74 65 64 20 64 75 72 69 6e 67 20  llocated during 
1410: 0a 20 20 2a 2a 20 69 6e 69 74 69 61 6c 69 7a 61  .  ** initializa
1420: 74 69 6f 6e 20 74 6f 20 74 68 65 20 6d 61 78 20  tion to the max 
1430: 70 61 74 68 6e 61 6d 65 20 6f 66 20 74 68 65 20  pathname of the 
1440: 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 2e 0a  underlying VFS..
1450: 20 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 4e 61    */.  char *zNa
1460: 6d 65 3b 0a 0a 7d 20 67 4d 75 6c 74 69 70 6c 65  me;..} gMultiple
1470: 78 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  x;../***********
1480: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 55  ************** U
1490: 74 69 6c 69 74 79 20 52 6f 75 74 69 6e 65 73 20  tility Routines 
14a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
14b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
14c0: 2a 2f 0a 2f 2a 0a 2a 2a 20 41 63 71 75 69 72 65  */./*.** Acquire
14d0: 20 61 6e 64 20 72 65 6c 65 61 73 65 20 74 68 65   and release the
14e0: 20 6d 75 74 65 78 20 75 73 65 64 20 74 6f 20 73   mutex used to s
14f0: 65 72 69 61 6c 69 7a 65 20 61 63 63 65 73 73 20  erialize access 
1500: 74 6f 20 74 68 65 0a 2a 2a 20 6c 69 73 74 20 6f  to the.** list o
1510: 66 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  f multiplexGroup
1520: 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  s..*/.static voi
1530: 64 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72  d multiplexEnter
1540: 28 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33 5f  (void){ sqlite3_
1550: 6d 75 74 65 78 5f 65 6e 74 65 72 28 67 4d 75 6c  mutex_enter(gMul
1560: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20  tiplex.pMutex); 
1570: 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75  }.static void mu
1580: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 76 6f 69  ltiplexLeave(voi
1590: 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  d){ sqlite3_mute
15a0: 78 5f 6c 65 61 76 65 28 67 4d 75 6c 74 69 70 6c  x_leave(gMultipl
15b0: 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f  ex.pMutex); }../
15c0: 2a 20 54 72 61 6e 73 6c 61 74 65 20 61 6e 20 73  * Translate an s
15d0: 71 6c 69 74 65 33 5f 66 69 6c 65 2a 20 74 68 61  qlite3_file* tha
15e0: 74 20 69 73 20 72 65 61 6c 6c 79 20 61 20 6d 75  t is really a mu
15f0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 2a 20 69 6e  ltiplexGroup* in
1600: 74 6f 0a 2a 2a 20 74 68 65 20 73 71 6c 69 74 65  to.** the sqlite
1610: 33 5f 66 69 6c 65 2a 20 66 6f 72 20 74 68 65 20  3_file* for the 
1620: 75 6e 64 65 72 6c 79 69 6e 67 20 6f 72 69 67 69  underlying origi
1630: 6e 61 6c 20 56 46 53 2e 0a 2a 2f 0a 73 74 61 74  nal VFS..*/.stat
1640: 69 63 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  ic sqlite3_file 
1650: 2a 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65  *multiplexSubOpe
1660: 6e 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20  n(multiplexConn 
1670: 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 69 43 68 75  *pConn, int iChu
1680: 6e 6b 2c 20 69 6e 74 20 2a 72 63 2c 20 69 6e 74  nk, int *rc, int
1690: 20 2a 70 4f 75 74 46 6c 61 67 73 29 7b 0a 20 20   *pOutFlags){.  
16a0: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
16b0: 70 47 72 6f 75 70 20 3d 20 70 43 6f 6e 6e 2d 3e  pGroup = pConn->
16c0: 70 47 72 6f 75 70 3b 0a 20 20 73 71 6c 69 74 65  pGroup;.  sqlite
16d0: 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20  3_vfs *pOrigVfs 
16e0: 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  = gMultiplex.pOr
16f0: 69 67 56 66 73 3b 20 20 20 20 20 20 20 20 2f 2a  igVfs;        /*
1700: 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 69   Real VFS */.  i
1710: 66 28 20 69 43 68 75 6e 6b 3c 67 4d 75 6c 74 69  f( iChunk<gMulti
1720: 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e 6b 73 20  plex.nMaxChunks 
1730: 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66  ){.    sqlite3_f
1740: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
1750: 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c 5b 69 43  pGroup->pReal[iC
1760: 68 75 6e 6b 5d 3b 20 20 20 20 2f 2a 20 52 65 61  hunk];    /* Rea
1770: 6c 20 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f  l file descripto
1780: 72 20 2a 2f 0a 20 20 20 20 69 66 28 20 21 70 47  r */.    if( !pG
1790: 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 43 68 75  roup->bOpen[iChu
17a0: 6e 6b 5d 20 29 7b 0a 20 20 20 20 20 20 6d 65 6d  nk] ){.      mem
17b0: 63 70 79 28 67 4d 75 6c 74 69 70 6c 65 78 2e 7a  cpy(gMultiplex.z
17c0: 4e 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 7a 4e  Name, pGroup->zN
17d0: 61 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 6e 4e 61  ame, pGroup->nNa
17e0: 6d 65 2b 31 29 3b 0a 20 20 20 20 20 20 69 66 28  me+1);.      if(
17f0: 20 69 43 68 75 6e 6b 20 29 7b 0a 23 69 66 64 65   iChunk ){.#ifde
1800: 66 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  f SQLITE_MULTIPL
1810: 45 58 5f 45 58 54 5f 4f 56 57 52 0a 20 20 20 20  EX_EXT_OVWR.    
1820: 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72      sqlite3_snpr
1830: 69 6e 74 66 28 53 51 4c 49 54 45 5f 4d 55 4c 54  intf(SQLITE_MULT
1840: 49 50 4c 45 58 5f 45 58 54 5f 53 5a 2b 31 2c 20  IPLEX_EXT_SZ+1, 
1850: 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65  gMultiplex.zName
1860: 2b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2d 53  +pGroup->nName-S
1870: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
1880: 45 58 54 5f 53 5a 2c 20 53 51 4c 49 54 45 5f 4d  EXT_SZ, SQLITE_M
1890: 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54  ULTIPLEX_EXT_FMT
18a0: 2c 20 69 43 68 75 6e 6b 29 3b 0a 23 65 6c 73 65  , iChunk);.#else
18b0: 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33  .        sqlite3
18c0: 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c 49 54 45  _snprintf(SQLITE
18d0: 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 53  _MULTIPLEX_EXT_S
18e0: 5a 2b 31 2c 20 67 4d 75 6c 74 69 70 6c 65 78 2e  Z+1, gMultiplex.
18f0: 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e 6e 4e  zName+pGroup->nN
1900: 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4d 55 4c 54  ame, SQLITE_MULT
1910: 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54 2c 20 69  IPLEX_EXT_FMT, i
1920: 43 68 75 6e 6b 29 3b 0a 23 65 6e 64 69 66 0a 20  Chunk);.#endif. 
1930: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 2a 72 63       }.      *rc
1940: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 4f 70   = pOrigVfs->xOp
1950: 65 6e 28 70 4f 72 69 67 56 66 73 2c 20 67 4d 75  en(pOrigVfs, gMu
1960: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20 70  ltiplex.zName, p
1970: 53 75 62 4f 70 65 6e 2c 20 70 47 72 6f 75 70 2d  SubOpen, pGroup-
1980: 3e 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c 61 67  >flags, pOutFlag
1990: 73 29 3b 0a 20 20 20 20 20 20 69 66 28 20 2a 72  s);.      if( *r
19a0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
19b0: 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e          pGroup->
19c0: 62 4f 70 65 6e 5b 69 43 68 75 6e 6b 5d 20 3d 20  bOpen[iChunk] = 
19d0: 2d 31 3b 0a 20 20 20 20 20 20 20 20 72 65 74 75  -1;.        retu
19e0: 72 6e 20 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20  rn pSubOpen;.   
19f0: 20 20 20 7d 0a 20 20 20 20 20 20 72 65 74 75 72     }.      retur
1a00: 6e 20 4e 55 4c 4c 3b 0a 20 20 20 20 7d 0a 20 20  n NULL;.    }.  
1a10: 20 20 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f    *rc = SQLITE_O
1a20: 4b 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  K;.    return pS
1a30: 75 62 4f 70 65 6e 3b 0a 20 20 7d 0a 20 20 2a 72  ubOpen;.  }.  *r
1a40: 63 20 3d 20 53 51 4c 49 54 45 5f 46 55 4c 4c 3b  c = SQLITE_FULL;
1a50: 0a 20 20 72 65 74 75 72 6e 20 4e 55 4c 4c 3b 0a  .  return NULL;.
1a60: 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  }../************
1a70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 56 46  ************* VF
1a80: 53 20 4d 65 74 68 6f 64 20 57 72 61 70 70 65 72  S Method Wrapper
1a90: 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  s **************
1aa0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f  ***************/
1ab0: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20  ../*.** This is 
1ac0: 74 68 65 20 78 4f 70 65 6e 20 6d 65 74 68 6f 64  the xOpen method
1ad0: 20 75 73 65 64 20 66 6f 72 20 74 68 65 20 22 6d   used for the "m
1ae0: 75 6c 74 69 70 6c 65 78 22 20 56 46 53 2e 0a 2a  ultiplex" VFS..*
1af0: 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66 20 74 68 65  *.** Most of the
1b00: 20 77 6f 72 6b 20 69 73 20 64 6f 6e 65 20 62 79   work is done by
1b10: 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20   the underlying 
1b20: 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 20 20 54  original VFS.  T
1b30: 68 69 73 20 6d 65 74 68 6f 64 0a 2a 2a 20 73 69  his method.** si
1b40: 6d 70 6c 79 20 6c 69 6e 6b 73 20 74 68 65 20 6e  mply links the n
1b50: 65 77 20 66 69 6c 65 20 69 6e 74 6f 20 74 68 65  ew file into the
1b60: 20 61 70 70 72 6f 70 72 69 61 74 65 20 6d 75 6c   appropriate mul
1b70: 74 69 70 6c 65 78 20 67 72 6f 75 70 20 69 66 20  tiplex group if 
1b80: 69 74 20 69 73 20 61 0a 2a 2a 20 66 69 6c 65 20  it is a.** file 
1b90: 74 68 61 74 20 6e 65 65 64 73 20 74 6f 20 62 65  that needs to be
1ba0: 20 74 72 61 63 6b 65 64 2e 0a 2a 2f 0a 73 74 61   tracked..*/.sta
1bb0: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
1bc0: 78 4f 70 65 6e 28 0a 20 20 73 71 6c 69 74 65 33  xOpen(.  sqlite3
1bd0: 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20 20 20  _vfs *pVfs,     
1be0: 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69      /* The multi
1bf0: 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 63 6f  plex VFS */.  co
1c00: 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c  nst char *zName,
1c10: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
1c20: 20 6f 66 20 66 69 6c 65 20 74 6f 20 62 65 20 6f   of file to be o
1c30: 70 65 6e 65 64 20 2a 2f 0a 20 20 73 71 6c 69 74  pened */.  sqlit
1c40: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
1c50: 20 20 20 20 20 20 2f 2a 20 46 69 6c 6c 20 69 6e        /* Fill in
1c60: 20 74 68 69 73 20 66 69 6c 65 20 64 65 73 63 72   this file descr
1c70: 69 70 74 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 66  iptor */.  int f
1c80: 6c 61 67 73 2c 20 20 20 20 20 20 20 20 20 20 20  lags,           
1c90: 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20 74        /* Flags t
1ca0: 6f 20 63 6f 6e 74 72 6f 6c 20 74 68 65 20 6f 70  o control the op
1cb0: 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e 74 20 2a  ening */.  int *
1cc0: 70 4f 75 74 46 6c 61 67 73 20 20 20 20 20 20 20  pOutFlags       
1cd0: 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20 73        /* Flags s
1ce0: 68 6f 77 69 6e 67 20 72 65 73 75 6c 74 73 20 6f  howing results o
1cf0: 66 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 29 7b 0a  f opening */.){.
1d00: 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20    int rc;       
1d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d30: 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64 65 20   /* Result code 
1d40: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  */.  multiplexCo
1d50: 6e 6e 20 2a 70 4d 75 6c 74 69 70 6c 65 78 4f 70  nn *pMultiplexOp
1d60: 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  en;             
1d70: 20 20 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d      /* The new m
1d80: 75 6c 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65  ultiplex file de
1d90: 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75  scriptor */.  mu
1da0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
1db0: 72 6f 75 70 3b 20 20 20 20 20 20 20 20 20 20 20  roup;           
1dc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
1dd0: 43 6f 72 72 65 73 70 6f 6e 64 69 6e 67 20 6d 75  Corresponding mu
1de0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a  ltiplexGroup obj
1df0: 65 63 74 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  ect */.  sqlite3
1e00: 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 3b  _file *pSubOpen;
1e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e20: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 61 6c 20          /* Real 
1e30: 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f 72 20  file descriptor 
1e40: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73  */.  sqlite3_vfs
1e50: 20 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75   *pOrigVfs = gMu
1e60: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
1e70: 3b 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20  ;   /* Real VFS 
1e80: 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 20 3d  */.  int nName =
1e90: 20 73 71 6c 69 74 65 33 53 74 72 6c 65 6e 33 30   sqlite3Strlen30
1ea0: 28 7a 4e 61 6d 65 29 3b 0a 20 20 69 6e 74 20 69  (zName);.  int i
1eb0: 3b 0a 20 20 69 6e 74 20 73 7a 3b 0a 0a 20 20 55  ;.  int sz;..  U
1ec0: 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28  NUSED_PARAMETER(
1ed0: 70 56 66 73 29 3b 0a 0a 20 20 2f 2a 20 57 65 20  pVfs);..  /* We 
1ee0: 6e 65 65 64 20 74 6f 20 63 72 65 61 74 65 20 61  need to create a
1ef0: 20 67 72 6f 75 70 20 73 74 72 75 63 74 75 72 65   group structure
1f00: 20 61 6e 64 20 6d 61 6e 61 67 65 0a 20 20 2a 2a   and manage.  **
1f10: 20 61 63 63 65 73 73 20 74 6f 20 74 68 69 73 20   access to this 
1f20: 67 72 6f 75 70 20 6f 66 20 66 69 6c 65 73 2e 0a  group of files..
1f30: 20 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78    */.  multiplex
1f40: 45 6e 74 65 72 28 29 3b 0a 20 20 70 4d 75 6c 74  Enter();.  pMult
1f50: 69 70 6c 65 78 4f 70 65 6e 20 3d 20 28 6d 75 6c  iplexOpen = (mul
1f60: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
1f70: 6e 3b 0a 20 20 2f 2a 20 61 6c 6c 6f 63 61 74 65  n;.  /* allocate
1f80: 20 73 70 61 63 65 20 66 6f 72 20 67 72 6f 75 70   space for group
1f90: 20 2a 2f 0a 20 20 73 7a 20 3d 20 73 69 7a 65 6f   */.  sz = sizeo
1fa0: 66 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  f(multiplexGroup
1fb0: 29 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  )               
1fc0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6d 75 6c            /* mul
1fd0: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 2f 0a 20  tiplexGroup */. 
1fe0: 20 20 20 20 2b 20 28 73 69 7a 65 6f 66 28 73 71      + (sizeof(sq
1ff0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 29 2a 67 4d  lite3_file *)*gM
2000: 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75  ultiplex.nMaxChu
2010: 6e 6b 73 29 20 2f 2a 20 70 52 65 61 6c 5b 5d 20  nks) /* pReal[] 
2020: 2a 2f 0a 20 20 20 20 20 2b 20 28 70 4f 72 69 67  */.     + (pOrig
2030: 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 2a 67 4d  Vfs->szOsFile*gM
2040: 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75  ultiplex.nMaxChu
2050: 6e 6b 73 29 20 20 20 20 20 2f 2a 20 2a 70 52 65  nks)     /* *pRe
2060: 61 6c 20 2a 2f 0a 20 20 20 20 20 2b 20 67 4d 75  al */.     + gMu
2070: 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e  ltiplex.nMaxChun
2080: 6b 73 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ks              
2090: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 62              /* b
20a0: 4f 70 65 6e 5b 5d 20 2a 2f 0a 20 20 20 20 20 2b  Open[] */.     +
20b0: 20 6e 4e 61 6d 65 20 2b 20 31 3b 20 20 20 20 20   nName + 1;     
20c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20e0: 2f 2a 20 7a 4e 61 6d 65 20 2a 2f 0a 23 69 66 6e  /* zName */.#ifn
20f0: 64 65 66 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49  def SQLITE_MULTI
2100: 50 4c 45 58 5f 45 58 54 5f 4f 56 57 52 0a 20 20  PLEX_EXT_OVWR.  
2110: 73 7a 20 2b 3d 20 53 51 4c 49 54 45 5f 4d 55 4c  sz += SQLITE_MUL
2120: 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a 3b 0a 20  TIPLEX_EXT_SZ;. 
2130: 20 61 73 73 65 72 74 28 6e 4e 61 6d 65 2b 53 51   assert(nName+SQ
2140: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45  LITE_MULTIPLEX_E
2150: 58 54 5f 53 5a 20 3c 20 70 4f 72 69 67 56 66 73  XT_SZ < pOrigVfs
2160: 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 29 3b 0a 23  ->mxPathname);.#
2170: 65 6c 73 65 0a 20 20 61 73 73 65 72 74 28 6e 4e  else.  assert(nN
2180: 61 6d 65 20 3e 3d 20 53 51 4c 49 54 45 5f 4d 55  ame >= SQLITE_MU
2190: 4c 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a 29 3b  LTIPLEX_EXT_SZ);
21a0: 0a 20 20 61 73 73 65 72 74 28 6e 4e 61 6d 65 20  .  assert(nName 
21b0: 3c 20 70 4f 72 69 67 56 66 73 2d 3e 6d 78 50 61  < pOrigVfs->mxPa
21c0: 74 68 6e 61 6d 65 29 3b 0a 23 65 6e 64 69 66 0a  thname);.#endif.
21d0: 20 20 70 47 72 6f 75 70 20 3d 20 73 71 6c 69 74    pGroup = sqlit
21e0: 65 33 5f 6d 61 6c 6c 6f 63 28 20 73 7a 20 29 3b  e3_malloc( sz );
21f0: 0a 20 20 69 66 28 20 70 47 72 6f 75 70 3d 3d 30  .  if( pGroup==0
2200: 20 29 7b 0a 20 20 20 20 72 63 3d 53 51 4c 49 54   ){.    rc=SQLIT
2210: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d 65 6c 73 65  E_NOMEM;.  }else
2220: 7b 0a 20 20 20 20 2f 2a 20 61 73 73 69 67 6e 20  {.    /* assign 
2230: 70 6f 69 6e 74 65 72 73 20 74 6f 20 65 78 74 72  pointers to extr
2240: 61 20 73 70 61 63 65 20 61 6c 6c 6f 63 61 74 65  a space allocate
2250: 64 20 2a 2f 0a 20 20 20 20 63 68 61 72 20 2a 70  d */.    char *p
2260: 20 3d 20 28 63 68 61 72 20 2a 29 26 70 47 72 6f   = (char *)&pGro
2270: 75 70 5b 31 5d 3b 0a 20 20 20 20 70 4d 75 6c 74  up[1];.    pMult
2280: 69 70 6c 65 78 4f 70 65 6e 2d 3e 70 47 72 6f 75  iplexOpen->pGrou
2290: 70 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20  p = pGroup;.    
22a0: 6d 65 6d 73 65 74 28 70 47 72 6f 75 70 2c 20 30  memset(pGroup, 0
22b0: 2c 20 73 7a 29 3b 0a 20 20 20 20 70 47 72 6f 75  , sz);.    pGrou
22c0: 70 2d 3e 70 52 65 61 6c 20 3d 20 28 73 71 6c 69  p->pReal = (sqli
22d0: 74 65 33 5f 66 69 6c 65 20 2a 2a 29 70 3b 0a 20  te3_file **)p;. 
22e0: 20 20 20 70 20 2b 3d 20 28 73 69 7a 65 6f 66 28     p += (sizeof(
22f0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 29 2a  sqlite3_file *)*
2300: 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43  gMultiplex.nMaxC
2310: 68 75 6e 6b 73 29 3b 0a 20 20 20 20 66 6f 72 28  hunks);.    for(
2320: 69 3d 30 3b 20 69 3c 67 4d 75 6c 74 69 70 6c 65  i=0; i<gMultiple
2330: 78 2e 6e 4d 61 78 43 68 75 6e 6b 73 3b 20 69 2b  x.nMaxChunks; i+
2340: 2b 29 7b 0a 20 20 20 20 20 20 70 47 72 6f 75 70  +){.      pGroup
2350: 2d 3e 70 52 65 61 6c 5b 69 5d 20 3d 20 28 73 71  ->pReal[i] = (sq
2360: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 29 70 3b 0a  lite3_file *)p;.
2370: 20 20 20 20 20 20 70 20 2b 3d 20 70 4f 72 69 67        p += pOrig
2380: 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 3b 0a 20  Vfs->szOsFile;. 
2390: 20 20 20 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d     }.    pGroup-
23a0: 3e 62 4f 70 65 6e 20 3d 20 70 3b 0a 20 20 20 20  >bOpen = p;.    
23b0: 70 20 2b 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e  p += gMultiplex.
23c0: 6e 4d 61 78 43 68 75 6e 6b 73 3b 0a 20 20 20 20  nMaxChunks;.    
23d0: 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 3d 20  pGroup->zName = 
23e0: 70 3b 0a 20 20 20 20 2f 2a 20 73 61 76 65 20 6f  p;.    /* save o
23f0: 66 66 20 62 61 73 65 20 66 69 6c 65 6e 61 6d 65  ff base filename
2400: 2c 20 6e 61 6d 65 20 6c 65 6e 67 74 68 2c 20 61  , name length, a
2410: 6e 64 20 6f 72 69 67 69 6e 61 6c 20 6f 70 65 6e  nd original open
2420: 20 66 6c 61 67 73 20 20 2a 2f 0a 20 20 20 20 6d   flags  */.    m
2430: 65 6d 63 70 79 28 70 47 72 6f 75 70 2d 3e 7a 4e  emcpy(pGroup->zN
2440: 61 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d  ame, zName, nNam
2450: 65 2b 31 29 3b 0a 20 20 20 20 70 47 72 6f 75 70  e+1);.    pGroup
2460: 2d 3e 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d 65 3b  ->nName = nName;
2470: 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 66 6c 61  .    pGroup->fla
2480: 67 73 20 3d 20 66 6c 61 67 73 3b 0a 20 20 20 20  gs = flags;.    
2490: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
24a0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 4d 75 6c  plexSubOpen(pMul
24b0: 74 69 70 6c 65 78 4f 70 65 6e 2c 20 30 2c 20 26  tiplexOpen, 0, &
24c0: 72 63 2c 20 70 4f 75 74 46 6c 61 67 73 29 3b 0a  rc, pOutFlags);.
24d0: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
24e0: 20 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70 53   ){.      if( pS
24f0: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
2500: 2d 3e 69 56 65 72 73 69 6f 6e 3d 3d 31 20 29 7b  ->iVersion==1 ){
2510: 0a 20 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70  .        pMultip
2520: 6c 65 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d  lexOpen->base.pM
2530: 65 74 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69  ethods = &gMulti
2540: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
2550: 31 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a  1;.      }else{.
2560: 20 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70 6c          pMultipl
2570: 65 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d 65  exOpen->base.pMe
2580: 74 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69 70  thods = &gMultip
2590: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32  lex.sIoMethodsV2
25a0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
25b0: 2f 2a 20 70 6c 61 63 65 20 74 68 69 73 20 67 72  /* place this gr
25c0: 6f 75 70 20 61 74 20 74 68 65 20 68 65 61 64 20  oup at the head 
25d0: 6f 66 20 6f 75 72 20 6c 69 73 74 20 2a 2f 0a 20  of our list */. 
25e0: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 4e 65       pGroup->pNe
25f0: 78 74 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e  xt = gMultiplex.
2600: 70 47 72 6f 75 70 73 3b 0a 20 20 20 20 20 20 69  pGroups;.      i
2610: 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47  f( gMultiplex.pG
2620: 72 6f 75 70 73 20 29 20 67 4d 75 6c 74 69 70 6c  roups ) gMultipl
2630: 65 78 2e 70 47 72 6f 75 70 73 2d 3e 70 50 72 65  ex.pGroups->pPre
2640: 76 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20  v = pGroup;.    
2650: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72    gMultiplex.pGr
2660: 6f 75 70 73 20 3d 20 70 47 72 6f 75 70 3b 0a 20  oups = pGroup;. 
2670: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
2680: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72  sqlite3_free(pGr
2690: 6f 75 70 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  oup);.    }.  }.
26a0: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
26b0: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
26c0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69  .}../*.** This i
26d0: 73 20 74 68 65 20 78 44 65 6c 65 74 65 20 6d 65  s the xDelete me
26e0: 74 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68  thod used for th
26f0: 65 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46  e "multiplex" VF
2700: 53 2e 0a 2a 2a 20 49 74 20 61 74 74 65 6d 70 74  S..** It attempt
2710: 73 20 74 6f 20 64 65 6c 65 74 65 20 74 68 65 20  s to delete the 
2720: 66 69 6c 65 6e 61 6d 65 20 73 70 65 63 69 66 69  filename specifi
2730: 65 64 2c 20 61 73 20 77 65 6c 6c 0a 2a 2a 20 61  ed, as well.** a
2740: 73 20 61 64 64 69 74 69 6f 6e 61 6c 20 66 69 6c  s additional fil
2750: 65 73 20 77 69 74 68 20 74 68 65 20 53 51 4c 49  es with the SQLI
2760: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
2770: 5f 46 4d 54 20 65 78 74 65 6e 73 69 6f 6e 2e 0a  _FMT extension..
2780: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
2790: 6c 74 69 70 6c 65 78 44 65 6c 65 74 65 28 0a 20  ltiplexDelete(. 
27a0: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 56   sqlite3_vfs *pV
27b0: 66 73 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 54  fs,         /* T
27c0: 68 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53  he multiplex VFS
27d0: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
27e0: 20 2a 7a 4e 61 6d 65 2c 20 20 20 20 20 20 20 20   *zName,        
27f0: 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 66 69 6c 65   /* Name of file
2800: 20 74 6f 20 64 65 6c 65 74 65 20 2a 2f 0a 20 20   to delete */.  
2810: 69 6e 74 20 73 79 6e 63 44 69 72 0a 29 7b 0a 20  int syncDir.){. 
2820: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f   sqlite3_vfs *pO
2830: 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70  rigVfs = gMultip
2840: 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20  lex.pOrigVfs;   
2850: 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20  /* Real VFS */. 
2860: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
2870: 5f 4f 4b 3b 0a 20 20 69 6e 74 20 6e 4e 61 6d 65  _OK;.  int nName
2880: 20 3d 20 73 71 6c 69 74 65 33 53 74 72 6c 65 6e   = sqlite3Strlen
2890: 33 30 28 7a 4e 61 6d 65 29 3b 0a 20 20 69 6e 74  30(zName);.  int
28a0: 20 69 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41   i;..  UNUSED_PA
28b0: 52 41 4d 45 54 45 52 28 70 56 66 73 29 3b 0a 0a  RAMETER(pVfs);..
28c0: 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72    multiplexEnter
28d0: 28 29 3b 0a 20 20 6d 65 6d 63 70 79 28 67 4d 75  ();.  memcpy(gMu
28e0: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20 7a  ltiplex.zName, z
28f0: 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2b 31 29 3b 0a  Name, nName+1);.
2900: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 67 4d 75    for(i=0; i<gMu
2910: 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e  ltiplex.nMaxChun
2920: 6b 73 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 69 6e  ks; i++){.    in
2930: 74 20 72 63 32 3b 0a 20 20 20 20 69 6e 74 20 65  t rc2;.    int e
2940: 78 69 73 74 73 20 3d 20 30 3b 0a 20 20 20 20 69  xists = 0;.    i
2950: 66 28 20 69 20 29 7b 0a 23 69 66 64 65 66 20 53  f( i ){.#ifdef S
2960: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
2970: 45 58 54 5f 4f 56 57 52 0a 20 20 20 20 20 20 20  EXT_OVWR.       
2980: 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74   sqlite3_snprint
2990: 66 28 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  f(SQLITE_MULTIPL
29a0: 45 58 5f 45 58 54 5f 53 5a 2b 31 2c 20 67 4d 75  EX_EXT_SZ+1, gMu
29b0: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2b 6e 4e  ltiplex.zName+nN
29c0: 61 6d 65 2d 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ame-SQLITE_MULTI
29d0: 50 4c 45 58 5f 45 58 54 5f 53 5a 2c 20 53 51 4c  PLEX_EXT_SZ, SQL
29e0: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
29f0: 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6c 73 65  T_FMT, i);.#else
2a00: 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33  .        sqlite3
2a10: 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c 49 54 45  _snprintf(SQLITE
2a20: 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 53  _MULTIPLEX_EXT_S
2a30: 5a 2b 31 2c 20 67 4d 75 6c 74 69 70 6c 65 78 2e  Z+1, gMultiplex.
2a40: 7a 4e 61 6d 65 2b 6e 4e 61 6d 65 2c 20 53 51 4c  zName+nName, SQL
2a50: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
2a60: 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6e 64 69  T_FMT, i);.#endi
2a70: 66 0a 20 20 20 20 7d 0a 20 20 20 20 72 63 32 20  f.    }.    rc2 
2a80: 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63  = pOrigVfs->xAcc
2a90: 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 67 4d  ess(pOrigVfs, gM
2aa0: 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20  ultiplex.zName, 
2ab0: 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58  SQLITE_ACCESS_EX
2ac0: 49 53 54 53 2c 20 26 65 78 69 73 74 73 29 3b 0a  ISTS, &exists);.
2ad0: 20 20 20 20 69 66 28 20 72 63 32 3d 3d 53 51 4c      if( rc2==SQL
2ae0: 49 54 45 5f 4f 4b 20 26 26 20 65 78 69 73 74 73  ITE_OK && exists
2af0: 29 7b 0a 20 20 20 20 20 20 2f 2a 20 69 66 20 69  ){.      /* if i
2b00: 74 20 65 78 69 73 74 73 2c 20 64 65 6c 65 74 65  t exists, delete
2b10: 20 69 74 20 2a 2f 0a 20 20 20 20 20 20 72 63 32   it */.      rc2
2b20: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65   = pOrigVfs->xDe
2b30: 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 67  lete(pOrigVfs, g
2b40: 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c  Multiplex.zName,
2b50: 20 73 79 6e 63 44 69 72 29 3b 0a 20 20 20 20 20   syncDir);.     
2b60: 20 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45   if( rc2!=SQLITE
2b70: 5f 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a  _OK ) rc = rc2;.
2b80: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
2b90: 20 2f 2a 20 73 74 6f 70 20 61 74 20 66 69 72 73   /* stop at firs
2ba0: 74 20 22 67 61 70 22 20 2a 2f 0a 20 20 20 20 20  t "gap" */.     
2bb0: 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20   break;.    }.  
2bc0: 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  }.  multiplexLea
2bd0: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
2be0: 63 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74  c;.}..static int
2bf0: 20 6d 75 6c 74 69 70 6c 65 78 41 63 63 65 73 73   multiplexAccess
2c00: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
2c10: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 62 2c 20   const char *b, 
2c20: 69 6e 74 20 63 2c 20 69 6e 74 20 2a 64 29 7b 0a  int c, int *d){.
2c30: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
2c40: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 41  lex.pOrigVfs->xA
2c50: 63 63 65 73 73 28 67 4d 75 6c 74 69 70 6c 65 78  ccess(gMultiplex
2c60: 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 2c  .pOrigVfs, b, c,
2c70: 20 64 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e   d);.}.static in
2c80: 74 20 6d 75 6c 74 69 70 6c 65 78 46 75 6c 6c 50  t multiplexFullP
2c90: 61 74 68 6e 61 6d 65 28 73 71 6c 69 74 65 33 5f  athname(sqlite3_
2ca0: 76 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68  vfs *a, const ch
2cb0: 61 72 20 2a 62 2c 20 69 6e 74 20 63 2c 20 63 68  ar *b, int c, ch
2cc0: 61 72 20 2a 64 29 7b 0a 20 20 72 65 74 75 72 6e  ar *d){.  return
2cd0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
2ce0: 67 56 66 73 2d 3e 78 46 75 6c 6c 50 61 74 68 6e  gVfs->xFullPathn
2cf0: 61 6d 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70  ame(gMultiplex.p
2d00: 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 2c 20 64  OrigVfs, b, c, d
2d10: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64  );.}.static void
2d20: 20 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70 65   *multiplexDlOpe
2d30: 6e 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  n(sqlite3_vfs *a
2d40: 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 62 29  , const char *b)
2d50: 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74  {.  return gMult
2d60: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e  iplex.pOrigVfs->
2d70: 78 44 6c 4f 70 65 6e 28 67 4d 75 6c 74 69 70 6c  xDlOpen(gMultipl
2d80: 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b  ex.pOrigVfs, b);
2d90: 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  .}.static void m
2da0: 75 6c 74 69 70 6c 65 78 44 6c 45 72 72 6f 72 28  ultiplexDlError(
2db0: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
2dc0: 69 6e 74 20 62 2c 20 63 68 61 72 20 2a 63 29 7b  int b, char *c){
2dd0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  .  gMultiplex.pO
2de0: 72 69 67 56 66 73 2d 3e 78 44 6c 45 72 72 6f 72  rigVfs->xDlError
2df0: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
2e00: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
2e10: 74 61 74 69 63 20 76 6f 69 64 20 28 2a 6d 75 6c  tatic void (*mul
2e20: 74 69 70 6c 65 78 44 6c 53 79 6d 28 73 71 6c 69  tiplexDlSym(sqli
2e30: 74 65 33 5f 76 66 73 20 2a 61 2c 20 76 6f 69 64  te3_vfs *a, void
2e40: 20 2a 62 2c 20 63 6f 6e 73 74 20 63 68 61 72 20   *b, const char 
2e50: 2a 63 29 29 28 76 6f 69 64 29 7b 0a 20 20 72 65  *c))(void){.  re
2e60: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
2e70: 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 53 79 6d  pOrigVfs->xDlSym
2e80: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
2e90: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
2ea0: 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69  tatic void multi
2eb0: 70 6c 65 78 44 6c 43 6c 6f 73 65 28 73 71 6c 69  plexDlClose(sqli
2ec0: 74 65 33 5f 76 66 73 20 2a 61 2c 20 76 6f 69 64  te3_vfs *a, void
2ed0: 20 2a 62 29 7b 0a 20 20 67 4d 75 6c 74 69 70 6c   *b){.  gMultipl
2ee0: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c  ex.pOrigVfs->xDl
2ef0: 43 6c 6f 73 65 28 67 4d 75 6c 74 69 70 6c 65 78  Close(gMultiplex
2f00: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
2f10: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
2f20: 69 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73 28  iplexRandomness(
2f30: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
2f40: 69 6e 74 20 62 2c 20 63 68 61 72 20 2a 63 29 7b  int b, char *c){
2f50: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
2f60: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
2f70: 52 61 6e 64 6f 6d 6e 65 73 73 28 67 4d 75 6c 74  Randomness(gMult
2f80: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
2f90: 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20  b, c);.}.static 
2fa0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65  int multiplexSle
2fb0: 65 70 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  ep(sqlite3_vfs *
2fc0: 61 2c 20 69 6e 74 20 62 29 7b 0a 20 20 72 65 74  a, int b){.  ret
2fd0: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
2fe0: 4f 72 69 67 56 66 73 2d 3e 78 53 6c 65 65 70 28  OrigVfs->xSleep(
2ff0: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
3000: 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69  Vfs, b);.}.stati
3010: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43  c int multiplexC
3020: 75 72 72 65 6e 74 54 69 6d 65 28 73 71 6c 69 74  urrentTime(sqlit
3030: 65 33 5f 76 66 73 20 2a 61 2c 20 64 6f 75 62 6c  e3_vfs *a, doubl
3040: 65 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20  e *b){.  return 
3050: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
3060: 56 66 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d  Vfs->xCurrentTim
3070: 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72  e(gMultiplex.pOr
3080: 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73 74 61  igVfs, b);.}.sta
3090: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
30a0: 78 47 65 74 4c 61 73 74 45 72 72 6f 72 28 73 71  xGetLastError(sq
30b0: 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 69 6e  lite3_vfs *a, in
30c0: 74 20 62 2c 20 63 68 61 72 20 2a 63 29 7b 0a 20  t b, char *c){. 
30d0: 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c   return gMultipl
30e0: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 47 65  ex.pOrigVfs->xGe
30f0: 74 4c 61 73 74 45 72 72 6f 72 28 67 4d 75 6c 74  tLastError(gMult
3100: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
3110: 62 2c 20 63 29 3b 0a 7d 0a 73 74 61 74 69 63 20  b, c);.}.static 
3120: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43 75 72  int multiplexCur
3130: 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 28 73 71  rentTimeInt64(sq
3140: 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 73 71  lite3_vfs *a, sq
3150: 6c 69 74 65 33 5f 69 6e 74 36 34 20 2a 62 29 7b  lite3_int64 *b){
3160: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
3170: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
3180: 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34  CurrentTimeInt64
3190: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
31a0: 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 0a 2f 2a 2a  gVfs, b);.}../**
31b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
31c0: 2a 2a 2a 2a 2a 2a 20 49 2f 4f 20 4d 65 74 68 6f  ****** I/O Metho
31d0: 64 20 57 72 61 70 70 65 72 73 20 2a 2a 2a 2a 2a  d Wrappers *****
31e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
31f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20  **********/../* 
3200: 78 43 6c 6f 73 65 20 72 65 71 75 65 73 74 73 20  xClose requests 
3210: 67 65 74 20 70 61 73 73 65 64 20 74 68 72 6f 75  get passed throu
3220: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
3230: 61 6c 20 56 46 53 2e 0a 2a 2a 20 57 65 20 6c 6f  al VFS..** We lo
3240: 6f 70 20 6f 76 65 72 20 61 6c 6c 20 6f 70 65 6e  op over all open
3250: 20 63 68 75 6e 6b 20 68 61 6e 64 6c 65 73 20 61   chunk handles a
3260: 6e 64 20 63 6c 6f 73 65 20 74 68 65 6d 2e 0a 2a  nd close them..*
3270: 2a 20 54 68 65 20 67 72 6f 75 70 20 73 74 72 75  * The group stru
3280: 63 74 75 72 65 20 66 6f 72 20 74 68 69 73 20 66  cture for this f
3290: 69 6c 65 20 69 73 20 75 6e 6c 69 6e 6b 65 64 20  ile is unlinked 
32a0: 66 72 6f 6d 20 0a 2a 2a 20 6f 75 72 20 6c 69 73  from .** our lis
32b0: 74 20 6f 66 20 67 72 6f 75 70 73 20 61 6e 64 20  t of groups and 
32c0: 66 72 65 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  freed..*/.static
32d0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 43 6c   int multiplexCl
32e0: 6f 73 65 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ose(sqlite3_file
32f0: 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74   *pConn){.  mult
3300: 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28  iplexConn *p = (
3310: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70  multiplexConn*)p
3320: 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  Conn;.  multiple
3330: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d  xGroup *pGroup =
3340: 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e   p->pGroup;.  in
3350: 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b  t rc = SQLITE_OK
3360: 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75 6c  ;.  int i;.  mul
3370: 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20  tiplexEnter();. 
3380: 20 2f 2a 20 63 6c 6f 73 65 20 61 6e 79 20 6f 70   /* close any op
3390: 65 6e 20 68 61 6e 64 6c 65 73 20 2a 2f 0a 20 20  en handles */.  
33a0: 66 6f 72 28 69 3d 30 3b 20 69 3c 67 4d 75 6c 74  for(i=0; i<gMult
33b0: 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e 6b 73  iplex.nMaxChunks
33c0: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 69 66 28 20  ; i++){.    if( 
33d0: 70 47 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 5d  pGroup->bOpen[i]
33e0: 20 29 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65   ){.      sqlite
33f0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
3400: 20 3d 20 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c   = pGroup->pReal
3410: 5b 69 5d 3b 0a 20 20 20 20 20 20 69 6e 74 20 72  [i];.      int r
3420: 63 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  c2 = pSubOpen->p
3430: 4d 65 74 68 6f 64 73 2d 3e 78 43 6c 6f 73 65 28  Methods->xClose(
3440: 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 20 20 20  pSubOpen);.     
3450: 20 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45   if( rc2!=SQLITE
3460: 5f 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a  _OK ) rc = rc2;.
3470: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 4f        pGroup->bO
3480: 70 65 6e 5b 69 5d 20 3d 20 30 3b 0a 20 20 20 20  pen[i] = 0;.    
3490: 7d 0a 20 20 7d 0a 20 20 2f 2a 20 72 65 6d 6f 76  }.  }.  /* remov
34a0: 65 20 66 72 6f 6d 20 6c 69 6e 6b 65 64 20 6c 69  e from linked li
34b0: 73 74 20 2a 2f 0a 20 20 69 66 28 20 70 47 72 6f  st */.  if( pGro
34c0: 75 70 2d 3e 70 4e 65 78 74 20 29 20 70 47 72 6f  up->pNext ) pGro
34d0: 75 70 2d 3e 70 4e 65 78 74 2d 3e 70 50 72 65 76  up->pNext->pPrev
34e0: 20 3d 20 70 47 72 6f 75 70 2d 3e 70 50 72 65 76   = pGroup->pPrev
34f0: 3b 0a 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e  ;.  if( pGroup->
3500: 70 50 72 65 76 20 29 7b 0a 20 20 20 20 70 47 72  pPrev ){.    pGr
3510: 6f 75 70 2d 3e 70 50 72 65 76 2d 3e 70 4e 65 78  oup->pPrev->pNex
3520: 74 20 3d 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78  t = pGroup->pNex
3530: 74 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  t;.  }else{.    
3540: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75  gMultiplex.pGrou
3550: 70 73 20 3d 20 70 47 72 6f 75 70 2d 3e 70 4e 65  ps = pGroup->pNe
3560: 78 74 3b 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65  xt;.  }.  sqlite
3570: 33 5f 66 72 65 65 28 70 47 72 6f 75 70 29 3b 0a  3_free(pGroup);.
3580: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
3590: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
35a0: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 52 65 61  .}../* Pass xRea
35b0: 64 20 72 65 71 75 65 73 74 73 20 74 68 72 75 20  d requests thru 
35c0: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
35d0: 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74  VFS after.** det
35e0: 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72  ermining the cor
35f0: 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70  rect chunk to op
3600: 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20 42 72 65  erate on..** Bre
3610: 61 6b 20 75 70 20 72 65 61 64 73 20 61 63 72 6f  ak up reads acro
3620: 73 73 20 63 68 75 6e 6b 20 62 6f 75 6e 64 61 72  ss chunk boundar
3630: 69 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ies..*/.static i
3640: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 52 65 61 64  nt multiplexRead
3650: 28 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  (.  sqlite3_file
3660: 20 2a 70 43 6f 6e 6e 2c 0a 20 20 76 6f 69 64 20   *pConn,.  void 
3670: 2a 70 42 75 66 2c 0a 20 20 69 6e 74 20 69 41 6d  *pBuf,.  int iAm
3680: 74 2c 0a 20 20 73 71 6c 69 74 65 33 5f 69 6e 74  t,.  sqlite3_int
3690: 36 34 20 69 4f 66 73 74 0a 29 7b 0a 20 20 6d 75  64 iOfst.){.  mu
36a0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
36b0: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
36c0: 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63  )pConn;.  int rc
36d0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
36e0: 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29  multiplexEnter()
36f0: 3b 0a 20 20 77 68 69 6c 65 28 20 69 41 6d 74 20  ;.  while( iAmt 
3700: 3e 20 30 20 29 7b 0a 20 20 20 20 69 6e 74 20 69  > 0 ){.    int i
3710: 20 3d 20 28 69 6e 74 29 28 69 4f 66 73 74 2f 67   = (int)(iOfst/g
3720: 4d 75 6c 74 69 70 6c 65 78 2e 6e 43 68 75 6e 6b  Multiplex.nChunk
3730: 53 69 7a 65 29 3b 0a 20 20 20 20 73 71 6c 69 74  Size);.    sqlit
3740: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
3750: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
3760: 4f 70 65 6e 28 70 2c 20 69 2c 20 26 72 63 2c 20  Open(p, i, &rc, 
3770: 4e 55 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20 70  NULL);.    if( p
3780: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20  SubOpen ){.     
3790: 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28 28 69   int extra = ((i
37a0: 6e 74 29 28 69 4f 66 73 74 20 25 20 67 4d 75 6c  nt)(iOfst % gMul
37b0: 74 69 70 6c 65 78 2e 6e 43 68 75 6e 6b 53 69 7a  tiplex.nChunkSiz
37c0: 65 29 20 2b 20 69 41 6d 74 29 20 2d 20 67 4d 75  e) + iAmt) - gMu
37d0: 6c 74 69 70 6c 65 78 2e 6e 43 68 75 6e 6b 53 69  ltiplex.nChunkSi
37e0: 7a 65 3b 0a 20 20 20 20 20 20 69 66 28 20 65 78  ze;.      if( ex
37f0: 74 72 61 3c 30 20 29 20 65 78 74 72 61 20 3d 20  tra<0 ) extra = 
3800: 30 3b 0a 20 20 20 20 20 20 69 41 6d 74 20 2d 3d  0;.      iAmt -=
3810: 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20 72 63   extra;.      rc
3820: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
3830: 74 68 6f 64 73 2d 3e 78 52 65 61 64 28 70 53 75  thods->xRead(pSu
3840: 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d  bOpen, pBuf, iAm
3850: 74 2c 20 69 4f 66 73 74 25 67 4d 75 6c 74 69 70  t, iOfst%gMultip
3860: 6c 65 78 2e 6e 43 68 75 6e 6b 53 69 7a 65 29 3b  lex.nChunkSize);
3870: 0a 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53  .      if( rc!=S
3880: 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b  QLITE_OK ) break
3890: 3b 0a 20 20 20 20 20 20 70 42 75 66 20 3d 20 28  ;.      pBuf = (
38a0: 63 68 61 72 20 2a 29 70 42 75 66 20 2b 20 69 41  char *)pBuf + iA
38b0: 6d 74 3b 0a 20 20 20 20 20 20 69 4f 66 73 74 20  mt;.      iOfst 
38c0: 2b 3d 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 69  += iAmt;.      i
38d0: 41 6d 74 20 3d 20 65 78 74 72 61 3b 0a 20 20 20  Amt = extra;.   
38e0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63   }else{.      rc
38f0: 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f   = SQLITE_IOERR_
3900: 52 45 41 44 3b 0a 20 20 20 20 20 20 62 72 65 61  READ;.      brea
3910: 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d  k;.    }.  }.  m
3920: 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b  ultiplexLeave();
3930: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
3940: 0a 2f 2a 20 50 61 73 73 20 78 57 72 69 74 65 20  ./* Pass xWrite 
3950: 72 65 71 75 65 73 74 73 20 74 68 72 75 20 74 6f  requests thru to
3960: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
3970: 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72  S after.** deter
3980: 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65  mining the corre
3990: 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72  ct chunk to oper
39a0: 61 74 65 20 6f 6e 2e 0a 2a 2a 20 42 72 65 61 6b  ate on..** Break
39b0: 20 75 70 20 77 72 69 74 65 73 20 61 63 72 6f 73   up writes acros
39c0: 73 20 63 68 75 6e 6b 20 62 6f 75 6e 64 61 72 69  s chunk boundari
39d0: 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  es..*/.static in
39e0: 74 20 6d 75 6c 74 69 70 6c 65 78 57 72 69 74 65  t multiplexWrite
39f0: 28 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  (.  sqlite3_file
3a00: 20 2a 70 43 6f 6e 6e 2c 0a 20 20 63 6f 6e 73 74   *pConn,.  const
3a10: 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a 20 20 69   void *pBuf,.  i
3a20: 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71 6c 69 74  nt iAmt,.  sqlit
3a30: 65 33 5f 69 6e 74 36 34 20 69 4f 66 73 74 0a 29  e3_int64 iOfst.)
3a40: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
3a50: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
3a60: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
3a70: 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f  int rc = SQLITE_
3a80: 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45  OK;.  multiplexE
3a90: 6e 74 65 72 28 29 3b 0a 20 20 77 68 69 6c 65 28  nter();.  while(
3aa0: 20 69 41 6d 74 20 3e 20 30 20 29 7b 0a 20 20 20   iAmt > 0 ){.   
3ab0: 20 69 6e 74 20 69 20 3d 20 28 69 6e 74 29 28 69   int i = (int)(i
3ac0: 4f 66 73 74 2f 67 4d 75 6c 74 69 70 6c 65 78 2e  Ofst/gMultiplex.
3ad0: 6e 43 68 75 6e 6b 53 69 7a 65 29 3b 0a 20 20 20  nChunkSize);.   
3ae0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
3af0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
3b00: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c 20 69 2c  lexSubOpen(p, i,
3b10: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20   &rc, NULL);.   
3b20: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
3b30: 0a 20 20 20 20 20 20 69 6e 74 20 65 78 74 72 61  .      int extra
3b40: 20 3d 20 28 28 69 6e 74 29 28 69 4f 66 73 74 20   = ((int)(iOfst 
3b50: 25 20 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 43 68  % gMultiplex.nCh
3b60: 75 6e 6b 53 69 7a 65 29 20 2b 20 69 41 6d 74 29  unkSize) + iAmt)
3b70: 20 2d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 43   - gMultiplex.nC
3b80: 68 75 6e 6b 53 69 7a 65 3b 0a 20 20 20 20 20 20  hunkSize;.      
3b90: 69 66 28 20 65 78 74 72 61 3c 30 20 29 20 65 78  if( extra<0 ) ex
3ba0: 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20 20 69  tra = 0;.      i
3bb0: 41 6d 74 20 2d 3d 20 65 78 74 72 61 3b 0a 20 20  Amt -= extra;.  
3bc0: 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65      rc = pSubOpe
3bd0: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 57 72  n->pMethods->xWr
3be0: 69 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 70 42  ite(pSubOpen, pB
3bf0: 75 66 2c 20 69 41 6d 74 2c 20 69 4f 66 73 74 25  uf, iAmt, iOfst%
3c00: 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 43 68 75 6e  gMultiplex.nChun
3c10: 6b 53 69 7a 65 29 3b 0a 20 20 20 20 20 20 69 66  kSize);.      if
3c20: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
3c30: 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 70  ) break;.      p
3c40: 42 75 66 20 3d 20 28 63 68 61 72 20 2a 29 70 42  Buf = (char *)pB
3c50: 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20 20 20 20  uf + iAmt;.     
3c60: 20 69 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b 0a   iOfst += iAmt;.
3c70: 20 20 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74        iAmt = ext
3c80: 72 61 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ra;.    }else{. 
3c90: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
3ca0: 5f 49 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20 20  _IOERR_WRITE;.  
3cb0: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d      break;.    }
3cc0: 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78  .  }.  multiplex
3cd0: 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72  Leave();.  retur
3ce0: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73  n rc;.}../* Pass
3cf0: 20 78 54 72 75 6e 63 61 74 65 20 72 65 71 75 65   xTruncate reque
3d00: 73 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20  sts thru to the 
3d10: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74  original VFS aft
3d20: 65 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e  er.** determinin
3d30: 67 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68  g the correct ch
3d40: 75 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f  unk to operate o
3d50: 6e 2e 20 20 44 65 6c 65 74 65 20 61 6e 79 0a 2a  n.  Delete any.*
3d60: 2a 20 63 68 75 6e 6b 73 20 61 62 6f 76 65 20 74  * chunks above t
3d70: 68 65 20 74 72 75 6e 63 61 74 65 20 6d 61 72 6b  he truncate mark
3d80: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
3d90: 6d 75 6c 74 69 70 6c 65 78 54 72 75 6e 63 61 74  multiplexTruncat
3da0: 65 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  e(sqlite3_file *
3db0: 70 43 6f 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69  pConn, sqlite3_i
3dc0: 6e 74 36 34 20 73 69 7a 65 29 7b 0a 20 20 6d 75  nt64 size){.  mu
3dd0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
3de0: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
3df0: 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70  )pConn;.  multip
3e00: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
3e10: 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20   = p->pGroup;.  
3e20: 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f  int rc = SQLITE_
3e30: 4f 4b 3b 0a 20 20 69 6e 74 20 72 63 32 3b 0a 20  OK;.  int rc2;. 
3e40: 20 69 6e 74 20 69 3b 0a 20 20 73 71 6c 69 74 65   int i;.  sqlite
3e50: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
3e60: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  ;.  sqlite3_vfs 
3e70: 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c  *pOrigVfs = gMul
3e80: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b  tiplex.pOrigVfs;
3e90: 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a     /* Real VFS *
3ea0: 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74  /.  multiplexEnt
3eb0: 65 72 28 29 3b 0a 20 20 6d 65 6d 63 70 79 28 67  er();.  memcpy(g
3ec0: 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c  Multiplex.zName,
3ed0: 20 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20   pGroup->zName, 
3ee0: 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2b 31 29  pGroup->nName+1)
3ef0: 3b 0a 20 20 2f 2a 20 64 65 6c 65 74 65 20 74 68  ;.  /* delete th
3f00: 65 20 63 68 75 6e 6b 73 20 61 62 6f 76 65 20 74  e chunks above t
3f10: 68 65 20 74 72 75 6e 63 61 74 65 20 6c 69 6d 69  he truncate limi
3f20: 74 20 2a 2f 0a 20 20 66 6f 72 28 69 3d 28 69 6e  t */.  for(i=(in
3f30: 74 29 28 73 69 7a 65 2f 67 4d 75 6c 74 69 70 6c  t)(size/gMultipl
3f40: 65 78 2e 6e 43 68 75 6e 6b 53 69 7a 65 29 2b 31  ex.nChunkSize)+1
3f50: 3b 20 69 3c 67 4d 75 6c 74 69 70 6c 65 78 2e 6e  ; i<gMultiplex.n
3f60: 4d 61 78 43 68 75 6e 6b 73 3b 20 69 2b 2b 29 7b  MaxChunks; i++){
3f70: 0a 20 20 20 20 2f 2a 20 63 6c 6f 73 65 20 61 6e  .    /* close an
3f80: 79 20 6f 70 65 6e 20 63 68 75 6e 6b 73 20 62 65  y open chunks be
3f90: 66 6f 72 65 20 64 65 6c 65 74 69 6e 67 20 74 68  fore deleting th
3fa0: 65 6d 20 2a 2f 0a 20 20 20 20 69 66 28 20 70 47  em */.    if( pG
3fb0: 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 5d 20 29  roup->bOpen[i] )
3fc0: 7b 0a 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e  {.      pSubOpen
3fd0: 20 3d 20 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c   = pGroup->pReal
3fe0: 5b 69 5d 3b 0a 20 20 20 20 20 20 72 63 32 20 3d  [i];.      rc2 =
3ff0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
4000: 6f 64 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75 62  ods->xClose(pSub
4010: 4f 70 65 6e 29 3b 0a 20 20 20 20 20 20 69 66 28  Open);.      if(
4020: 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20   rc2!=SQLITE_OK 
4030: 29 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f  ) rc = SQLITE_IO
4040: 45 52 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20  ERR_TRUNCATE;.  
4050: 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 4f 70 65      pGroup->bOpe
4060: 6e 5b 69 5d 20 3d 20 30 3b 0a 20 20 20 20 7d 0a  n[i] = 0;.    }.
4070: 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f 4d 55  #ifdef SQLITE_MU
4080: 4c 54 49 50 4c 45 58 5f 45 58 54 5f 4f 56 57 52  LTIPLEX_EXT_OVWR
4090: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70  .    sqlite3_snp
40a0: 72 69 6e 74 66 28 53 51 4c 49 54 45 5f 4d 55 4c  rintf(SQLITE_MUL
40b0: 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a 2b 31 2c  TIPLEX_EXT_SZ+1,
40c0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d   gMultiplex.zNam
40d0: 65 2b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2d  e+pGroup->nName-
40e0: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
40f0: 5f 45 58 54 5f 53 5a 2c 20 53 51 4c 49 54 45 5f  _EXT_SZ, SQLITE_
4100: 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d  MULTIPLEX_EXT_FM
4110: 54 2c 20 69 29 3b 0a 23 65 6c 73 65 0a 20 20 20  T, i);.#else.   
4120: 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74   sqlite3_snprint
4130: 66 28 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  f(SQLITE_MULTIPL
4140: 45 58 5f 45 58 54 5f 53 5a 2b 31 2c 20 67 4d 75  EX_EXT_SZ+1, gMu
4150: 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2b 70 47  ltiplex.zName+pG
4160: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2c 20 53 51 4c  roup->nName, SQL
4170: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58  ITE_MULTIPLEX_EX
4180: 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6e 64 69  T_FMT, i);.#endi
4190: 66 0a 20 20 20 20 72 63 32 20 3d 20 70 4f 72 69  f.    rc2 = pOri
41a0: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
41b0: 72 69 67 56 66 73 2c 20 67 4d 75 6c 74 69 70 6c  rigVfs, gMultipl
41c0: 65 78 2e 7a 4e 61 6d 65 2c 20 30 29 3b 0a 20 20  ex.zName, 0);.  
41d0: 20 20 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54    if( rc2!=SQLIT
41e0: 45 5f 4f 4b 20 29 20 72 63 20 3d 20 53 51 4c 49  E_OK ) rc = SQLI
41f0: 54 45 5f 49 4f 45 52 52 5f 54 52 55 4e 43 41 54  TE_IOERR_TRUNCAT
4200: 45 3b 0a 20 20 7d 0a 20 20 70 53 75 62 4f 70 65  E;.  }.  pSubOpe
4210: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
4220: 4f 70 65 6e 28 70 2c 20 28 69 6e 74 29 28 73 69  Open(p, (int)(si
4230: 7a 65 2f 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 43  ze/gMultiplex.nC
4240: 68 75 6e 6b 53 69 7a 65 29 2c 20 26 72 63 32 2c  hunkSize), &rc2,
4250: 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53   NULL);.  if( pS
4260: 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 63  ubOpen ){.    rc
4270: 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  2 = pSubOpen->pM
4280: 65 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74  ethods->xTruncat
4290: 65 28 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65  e(pSubOpen, size
42a0: 25 67 4d 75 6c 74 69 70 6c 65 78 2e 6e 43 68 75  %gMultiplex.nChu
42b0: 6e 6b 53 69 7a 65 29 3b 0a 20 20 20 20 69 66 28  nkSize);.    if(
42c0: 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20   rc2!=SQLITE_OK 
42d0: 29 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 7d 65  ) rc = rc2;.  }e
42e0: 6c 73 65 7b 0a 20 20 20 20 72 63 20 3d 20 53 51  lse{.    rc = SQ
42f0: 4c 49 54 45 5f 49 4f 45 52 52 5f 54 52 55 4e 43  LITE_IOERR_TRUNC
4300: 41 54 45 3b 0a 20 20 7d 0a 20 20 6d 75 6c 74 69  ATE;.  }.  multi
4310: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
4320: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
4330: 50 61 73 73 20 78 53 79 6e 63 20 72 65 71 75 65  Pass xSync reque
4340: 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74  sts through to t
4350: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
4360: 77 69 74 68 6f 75 74 20 63 68 61 6e 67 65 0a 2a  without change.*
4370: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
4380: 74 69 70 6c 65 78 53 79 6e 63 28 73 71 6c 69 74  tiplexSync(sqlit
4390: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
43a0: 69 6e 74 20 66 6c 61 67 73 29 7b 0a 20 20 6d 75  int flags){.  mu
43b0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
43c0: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
43d0: 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70  )pConn;.  multip
43e0: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
43f0: 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20   = p->pGroup;.  
4400: 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f  int rc = SQLITE_
4410: 4f 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d  OK;.  int i;.  m
4420: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
4430: 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 67 4d  .  for(i=0; i<gM
4440: 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75  ultiplex.nMaxChu
4450: 6e 6b 73 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 2f  nks; i++){.    /
4460: 2a 20 69 66 20 77 65 20 64 6f 6e 27 74 20 68 61  * if we don't ha
4470: 76 65 20 69 74 20 6f 70 65 6e 2c 20 77 65 20 64  ve it open, we d
4480: 6f 6e 27 74 20 6e 65 65 64 20 74 6f 20 73 79 6e  on't need to syn
4490: 63 20 69 74 20 2a 2f 0a 20 20 20 20 69 66 28 20  c it */.    if( 
44a0: 70 47 72 6f 75 70 2d 3e 62 4f 70 65 6e 5b 69 5d  pGroup->bOpen[i]
44b0: 20 29 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65   ){.      sqlite
44c0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
44d0: 20 3d 20 70 47 72 6f 75 70 2d 3e 70 52 65 61 6c   = pGroup->pReal
44e0: 5b 69 5d 3b 0a 20 20 20 20 20 20 69 6e 74 20 72  [i];.      int r
44f0: 63 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  c2 = pSubOpen->p
4500: 4d 65 74 68 6f 64 73 2d 3e 78 53 79 6e 63 28 70  Methods->xSync(p
4510: 53 75 62 4f 70 65 6e 2c 20 66 6c 61 67 73 29 3b  SubOpen, flags);
4520: 0a 20 20 20 20 20 20 69 66 28 20 72 63 32 21 3d  .      if( rc2!=
4530: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d  SQLITE_OK ) rc =
4540: 20 72 63 32 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a   rc2;.    }.  }.
4550: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
4560: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
4570: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c  .}../* Pass xFil
4580: 65 53 69 7a 65 20 72 65 71 75 65 73 74 73 20 74  eSize requests t
4590: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
45a0: 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 20 41  iginal VFS..** A
45b0: 67 67 72 65 67 61 74 65 20 74 68 65 20 73 69 7a  ggregate the siz
45c0: 65 20 6f 66 20 61 6c 6c 20 74 68 65 20 63 68 75  e of all the chu
45d0: 6e 6b 73 20 62 65 66 6f 72 65 20 72 65 74 75 72  nks before retur
45e0: 6e 69 6e 67 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ning..*/.static 
45f0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c  int multiplexFil
4600: 65 53 69 7a 65 28 73 71 6c 69 74 65 33 5f 66 69  eSize(sqlite3_fi
4610: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71 6c 69 74  le *pConn, sqlit
4620: 65 33 5f 69 6e 74 36 34 20 2a 70 53 69 7a 65 29  e3_int64 *pSize)
4630: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
4640: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
4650: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
4660: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
4670: 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f  pGroup = p->pGro
4680: 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  up;.  int rc = S
4690: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
46a0: 72 63 32 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  rc2;.  int i;.  
46b0: 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29  multiplexEnter()
46c0: 3b 0a 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a  ;.  *pSize = 0;.
46d0: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 67 4d 75    for(i=0; i<gMu
46e0: 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e  ltiplex.nMaxChun
46f0: 6b 73 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 73 71  ks; i++){.    sq
4700: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
4710: 4f 70 65 6e 20 3d 20 4e 55 4c 4c 3b 0a 20 20 20  Open = NULL;.   
4720: 20 2f 2a 20 69 66 20 6e 6f 74 20 6f 70 65 6e 65   /* if not opene
4730: 64 20 61 6c 72 65 61 64 79 2c 20 63 68 65 63 6b  d already, check
4740: 20 74 6f 20 73 65 65 20 69 66 20 74 68 65 20 63   to see if the c
4750: 68 75 6e 6b 20 65 78 69 73 74 73 20 2a 2f 0a 20  hunk exists */. 
4760: 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 62     if( pGroup->b
4770: 4f 70 65 6e 5b 69 5d 20 29 7b 0a 20 20 20 20 20  Open[i] ){.     
4780: 20 70 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f   pSubOpen = pGro
4790: 75 70 2d 3e 70 52 65 61 6c 5b 69 5d 3b 0a 20 20  up->pReal[i];.  
47a0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 73    }else{.      s
47b0: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69  qlite3_vfs *pOri
47c0: 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65  gVfs = gMultiple
47d0: 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a  x.pOrigVfs;   /*
47e0: 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 20   Real VFS */.   
47f0: 20 20 20 69 6e 74 20 65 78 69 73 74 73 20 3d 20     int exists = 
4800: 30 3b 0a 20 20 20 20 20 20 6d 65 6d 63 70 79 28  0;.      memcpy(
4810: 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65  gMultiplex.zName
4820: 2c 20 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c  , pGroup->zName,
4830: 20 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 2b 31   pGroup->nName+1
4840: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 69 20 29  );.      if( i )
4850: 7b 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f  {.#ifdef SQLITE_
4860: 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54 5f 4f 56  MULTIPLEX_EXT_OV
4870: 57 52 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74  WR.        sqlit
4880: 65 33 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c 49  e3_snprintf(SQLI
4890: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
48a0: 5f 53 5a 2b 31 2c 20 67 4d 75 6c 74 69 70 6c 65  _SZ+1, gMultiple
48b0: 78 2e 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e  x.zName+pGroup->
48c0: 6e 4e 61 6d 65 2d 53 51 4c 49 54 45 5f 4d 55 4c  nName-SQLITE_MUL
48d0: 54 49 50 4c 45 58 5f 45 58 54 5f 53 5a 2c 20 53  TIPLEX_EXT_SZ, S
48e0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
48f0: 45 58 54 5f 46 4d 54 2c 20 69 29 3b 0a 23 65 6c  EXT_FMT, i);.#el
4900: 73 65 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74  se.        sqlit
4910: 65 33 5f 73 6e 70 72 69 6e 74 66 28 53 51 4c 49  e3_snprintf(SQLI
4920: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 45 58 54  TE_MULTIPLEX_EXT
4930: 5f 53 5a 2b 31 2c 20 67 4d 75 6c 74 69 70 6c 65  _SZ+1, gMultiple
4940: 78 2e 7a 4e 61 6d 65 2b 70 47 72 6f 75 70 2d 3e  x.zName+pGroup->
4950: 6e 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4d 55  nName, SQLITE_MU
4960: 4c 54 49 50 4c 45 58 5f 45 58 54 5f 46 4d 54 2c  LTIPLEX_EXT_FMT,
4970: 20 69 29 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20   i);.#endif.    
4980: 20 20 7d 0a 20 20 20 20 20 20 72 63 32 20 3d 20    }.      rc2 = 
4990: 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73  pOrigVfs->xAcces
49a0: 73 28 70 4f 72 69 67 56 66 73 2c 20 67 4d 75 6c  s(pOrigVfs, gMul
49b0: 74 69 70 6c 65 78 2e 7a 4e 61 6d 65 2c 20 53 51  tiplex.zName, SQ
49c0: 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49 53  LITE_ACCESS_EXIS
49d0: 54 53 2c 20 26 65 78 69 73 74 73 29 3b 0a 20 20  TS, &exists);.  
49e0: 20 20 20 20 69 66 28 20 72 63 32 3d 3d 53 51 4c      if( rc2==SQL
49f0: 49 54 45 5f 4f 4b 20 26 26 20 65 78 69 73 74 73  ITE_OK && exists
4a00: 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 69 66  ){.        /* if
4a10: 20 69 74 20 65 78 69 73 74 73 2c 20 6f 70 65 6e   it exists, open
4a20: 20 69 74 20 2a 2f 0a 20 20 20 20 20 20 20 20 70   it */.        p
4a30: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
4a40: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c 20 69 2c  lexSubOpen(p, i,
4a50: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20   &rc, NULL);.   
4a60: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
4a70: 20 20 2f 2a 20 73 74 6f 70 20 61 74 20 66 69 72    /* stop at fir
4a80: 73 74 20 22 67 61 70 22 20 2a 2f 0a 20 20 20 20  st "gap" */.    
4a90: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
4aa0: 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28   }.    }.    if(
4ab0: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
4ac0: 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34     sqlite3_int64
4ad0: 20 73 7a 3b 0a 20 20 20 20 20 20 72 63 32 20 3d   sz;.      rc2 =
4ae0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
4af0: 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70  ods->xFileSize(p
4b00: 53 75 62 4f 70 65 6e 2c 20 26 73 7a 29 3b 0a 20  SubOpen, &sz);. 
4b10: 20 20 20 20 20 69 66 28 20 72 63 32 21 3d 53 51       if( rc2!=SQ
4b20: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
4b30: 20 20 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20     rc = rc2;.   
4b40: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
4b50: 20 20 69 66 28 20 73 7a 3e 67 4d 75 6c 74 69 70    if( sz>gMultip
4b60: 6c 65 78 2e 6e 43 68 75 6e 6b 53 69 7a 65 20 29  lex.nChunkSize )
4b70: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
4b80: 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 46 53   SQLITE_IOERR_FS
4b90: 54 41 54 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  TAT;.        }. 
4ba0: 20 20 20 20 20 20 20 2a 70 53 69 7a 65 20 2b 3d         *pSize +=
4bb0: 20 73 7a 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20   sz;.      }.   
4bc0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 62 72   }else{.      br
4bd0: 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20  eak;.    }.  }. 
4be0: 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28   multiplexLeave(
4bf0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
4c00: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 4c 6f 63 6b  }../* Pass xLock
4c10: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
4c20: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
4c30: 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e  l VFS unchanged.
4c40: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
4c50: 75 6c 74 69 70 6c 65 78 4c 6f 63 6b 28 73 71 6c  ultiplexLock(sql
4c60: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
4c70: 2c 20 69 6e 74 20 6c 6f 63 6b 29 7b 0a 20 20 6d  , int lock){.  m
4c80: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
4c90: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
4ca0: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
4cb0: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
4cc0: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
4cd0: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
4ce0: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b  , 0, &rc, NULL);
4cf0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
4d00: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
4d10: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
4d20: 2d 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e  ->xLock(pSubOpen
4d30: 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72  , lock);.  }.  r
4d40: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53  eturn SQLITE_BUS
4d50: 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55  Y;.}../* Pass xU
4d60: 6e 6c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  nlock requests t
4d70: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
4d80: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
4d90: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
4da0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c  int multiplexUnl
4db0: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
4dc0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63   *pConn, int loc
4dd0: 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  k){.  multiplexC
4de0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
4df0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
4e00: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
4e10: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
4e20: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
4e30: 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c  bOpen(p, 0, &rc,
4e40: 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53   NULL);.  if( pS
4e50: 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65  ubOpen ){.    re
4e60: 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70  turn pSubOpen->p
4e70: 4d 65 74 68 6f 64 73 2d 3e 78 55 6e 6c 6f 63 6b  Methods->xUnlock
4e80: 28 70 53 75 62 4f 70 65 6e 2c 20 6c 6f 63 6b 29  (pSubOpen, lock)
4e90: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53  ;.  }.  return S
4ea0: 51 4c 49 54 45 5f 49 4f 45 52 52 5f 55 4e 4c 4f  QLITE_IOERR_UNLO
4eb0: 43 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78  CK;.}../* Pass x
4ec0: 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63  CheckReservedLoc
4ed0: 6b 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  k requests throu
4ee0: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
4ef0: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
4f00: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
4f10: 6d 75 6c 74 69 70 6c 65 78 43 68 65 63 6b 52 65  multiplexCheckRe
4f20: 73 65 72 76 65 64 4c 6f 63 6b 28 73 71 6c 69 74  servedLock(sqlit
4f30: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
4f40: 69 6e 74 20 2a 70 52 65 73 4f 75 74 29 7b 0a 20  int *pResOut){. 
4f50: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
4f60: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
4f70: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
4f80: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
4f90: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
4fa0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
4fb0: 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  (p, 0, &rc, NULL
4fc0: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
4fd0: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
4fe0: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
4ff0: 64 73 2d 3e 78 43 68 65 63 6b 52 65 73 65 72 76  ds->xCheckReserv
5000: 65 64 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c  edLock(pSubOpen,
5010: 20 70 52 65 73 4f 75 74 29 3b 0a 20 20 7d 0a 20   pResOut);.  }. 
5020: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49   return SQLITE_I
5030: 4f 45 52 52 5f 43 48 45 43 4b 52 45 53 45 52 56  OERR_CHECKRESERV
5040: 45 44 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61  EDLOCK;.}../* Pa
5050: 73 73 20 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 20  ss xFileControl 
5060: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
5070: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
5080: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
5090: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
50a0: 6c 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e 74 72  ltiplexFileContr
50b0: 6f 6c 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  ol(sqlite3_file 
50c0: 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6f 70 2c 20  *pConn, int op, 
50d0: 76 6f 69 64 20 2a 70 41 72 67 29 7b 0a 20 20 6d  void *pArg){.  m
50e0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
50f0: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
5100: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
5110: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
5120: 65 20 2a 70 53 75 62 4f 70 65 6e 3b 0a 20 20 69  e *pSubOpen;.  i
5130: 66 20 28 20 6f 70 3d 3d 53 51 4c 49 54 45 5f 46  f ( op==SQLITE_F
5140: 43 4e 54 4c 5f 53 49 5a 45 5f 48 49 4e 54 20 7c  CNTL_SIZE_HINT |
5150: 7c 20 6f 70 3d 3d 53 51 4c 49 54 45 5f 46 43 4e  | op==SQLITE_FCN
5160: 54 4c 5f 43 48 55 4e 4b 5f 53 49 5a 45 20 29 20  TL_CHUNK_SIZE ) 
5170: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
5180: 3b 0a 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d  ;.  pSubOpen = m
5190: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
51a0: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29  p, 0, &rc, NULL)
51b0: 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e  ;.  if( pSubOpen
51c0: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70   ){.    return p
51d0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
51e0: 73 2d 3e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28  s->xFileControl(
51f0: 70 53 75 62 4f 70 65 6e 2c 20 6f 70 2c 20 70 41  pSubOpen, op, pA
5200: 72 67 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  rg);.  }.  retur
5210: 6e 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a  n SQLITE_ERROR;.
5220: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 65 63 74  }../* Pass xSect
5230: 6f 72 53 69 7a 65 20 72 65 71 75 65 73 74 73 20  orSize requests 
5240: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
5250: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
5260: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
5270: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 65   int multiplexSe
5280: 63 74 6f 72 53 69 7a 65 28 73 71 6c 69 74 65 33  ctorSize(sqlite3
5290: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20  _file *pConn){. 
52a0: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
52b0: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
52c0: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
52d0: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
52e0: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
52f0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
5300: 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  (p, 0, &rc, NULL
5310: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
5320: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
5330: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
5340: 64 73 2d 3e 78 53 65 63 74 6f 72 53 69 7a 65 28  ds->xSectorSize(
5350: 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20  pSubOpen);.  }. 
5360: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 44   return SQLITE_D
5370: 45 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f 53 49  EFAULT_SECTOR_SI
5380: 5a 45 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78  ZE;.}../* Pass x
5390: 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69  DeviceCharacteri
53a0: 73 74 69 63 73 20 72 65 71 75 65 73 74 73 20 74  stics requests t
53b0: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
53c0: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
53d0: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
53e0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 76  int multiplexDev
53f0: 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69  iceCharacteristi
5400: 63 73 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  cs(sqlite3_file 
5410: 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69  *pConn){.  multi
5420: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
5430: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
5440: 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  onn;.  int rc;. 
5450: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
5460: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
5470: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2c 20 30 2c  lexSubOpen(p, 0,
5480: 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69   &rc, NULL);.  i
5490: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
54a0: 20 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70     return pSubOp
54b0: 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 44  en->pMethods->xD
54c0: 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69 73  eviceCharacteris
54d0: 74 69 63 73 28 70 53 75 62 4f 70 65 6e 29 3b 0a  tics(pSubOpen);.
54e0: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a    }.  return 0;.
54f0: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 4d  }../* Pass xShmM
5500: 61 70 20 72 65 71 75 65 73 74 73 20 74 68 72 6f  ap requests thro
5510: 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69  ugh to the origi
5520: 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65  nal VFS unchange
5530: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
5540: 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70   multiplexShmMap
5550: 28 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  (.  sqlite3_file
5560: 20 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20 20 20   *pConn,        
5570: 20 20 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6f 70      /* Handle op
5580: 65 6e 20 6f 6e 20 64 61 74 61 62 61 73 65 20 66  en on database f
5590: 69 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 69 52 65  ile */.  int iRe
55a0: 67 69 6f 6e 2c 20 20 20 20 20 20 20 20 20 20 20  gion,           
55b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 67 69           /* Regi
55c0: 6f 6e 20 74 6f 20 72 65 74 72 69 65 76 65 20 2a  on to retrieve *
55d0: 2f 0a 20 20 69 6e 74 20 73 7a 52 65 67 69 6f 6e  /.  int szRegion
55e0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
55f0: 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 72      /* Size of r
5600: 65 67 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74 20  egions */.  int 
5610: 62 45 78 74 65 6e 64 2c 20 20 20 20 20 20 20 20  bExtend,        
5620: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54              /* T
5630: 72 75 65 20 74 6f 20 65 78 74 65 6e 64 20 66 69  rue to extend fi
5640: 6c 65 20 69 66 20 6e 65 63 65 73 73 61 72 79 20  le if necessary 
5650: 2a 2f 0a 20 20 76 6f 69 64 20 76 6f 6c 61 74 69  */.  void volati
5660: 6c 65 20 2a 2a 70 70 20 20 20 20 20 20 20 20 20  le **pp         
5670: 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 4d 61 70       /* OUT: Map
5680: 70 65 64 20 6d 65 6d 6f 72 79 20 2a 2f 0a 29 7b  ped memory */.){
5690: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
56a0: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
56b0: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69  Conn*)pConn;.  i
56c0: 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33  nt rc;.  sqlite3
56d0: 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20  _file *pSubOpen 
56e0: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
56f0: 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  en(p, 0, &rc, NU
5700: 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f  LL);.  if( pSubO
5710: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
5720: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
5730: 68 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28 70 53  hods->xShmMap(pS
5740: 75 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f 6e 2c  ubOpen, iRegion,
5750: 20 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78 74 65   szRegion, bExte
5760: 6e 64 2c 20 70 70 29 3b 0a 20 20 7d 0a 20 20 72  nd, pp);.  }.  r
5770: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45  eturn SQLITE_IOE
5780: 52 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78  RR;.}../* Pass x
5790: 53 68 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74 73  ShmLock requests
57a0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
57b0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
57c0: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
57d0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53  c int multiplexS
57e0: 68 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74 65  hmLock(.  sqlite
57f0: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20  3_file *pConn,  
5800: 20 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73 65       /* Database
5810: 20 66 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68   file holding th
5820: 65 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 20  e shared memory 
5830: 2a 2f 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20 20  */.  int ofst,  
5840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5850: 2f 2a 20 46 69 72 73 74 20 6c 6f 63 6b 20 74 6f  /* First lock to
5860: 20 61 63 71 75 69 72 65 20 6f 72 20 72 65 6c 65   acquire or rele
5870: 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c 20  ase */.  int n, 
5880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5890: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
58a0: 20 6c 6f 63 6b 73 20 74 6f 20 61 63 71 75 69 72   locks to acquir
58b0: 65 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f 0a  e or release */.
58c0: 20 20 69 6e 74 20 66 6c 61 67 73 20 20 20 20 20    int flags     
58d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
58e0: 57 68 61 74 20 74 6f 20 64 6f 20 77 69 74 68 20  What to do with 
58f0: 74 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a 20  the lock */.){. 
5900: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
5910: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
5920: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
5930: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
5940: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
5950: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
5960: 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  (p, 0, &rc, NULL
5970: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
5980: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
5990: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
59a0: 64 73 2d 3e 78 53 68 6d 4c 6f 63 6b 28 70 53 75  ds->xShmLock(pSu
59b0: 62 4f 70 65 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20  bOpen, ofst, n, 
59c0: 66 6c 61 67 73 29 3b 0a 20 20 7d 0a 20 20 72 65  flags);.  }.  re
59d0: 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59  turn SQLITE_BUSY
59e0: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68  ;.}../* Pass xSh
59f0: 6d 42 61 72 72 69 65 72 20 72 65 71 75 65 73 74  mBarrier request
5a00: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
5a10: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
5a20: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
5a30: 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65  ic void multiple
5a40: 78 53 68 6d 42 61 72 72 69 65 72 28 73 71 6c 69  xShmBarrier(sqli
5a50: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29  te3_file *pConn)
5a60: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
5a70: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
5a80: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
5a90: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
5aa0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
5ab0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
5ac0: 70 65 6e 28 70 2c 20 30 2c 20 26 72 63 2c 20 4e  pen(p, 0, &rc, N
5ad0: 55 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62  ULL);.  if( pSub
5ae0: 4f 70 65 6e 20 29 7b 0a 20 20 20 20 70 53 75 62  Open ){.    pSub
5af0: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
5b00: 78 53 68 6d 42 61 72 72 69 65 72 28 70 53 75 62  xShmBarrier(pSub
5b10: 4f 70 65 6e 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a  Open);.  }.}../*
5b20: 20 50 61 73 73 20 78 53 68 6d 55 6e 6d 61 70 20   Pass xShmUnmap 
5b30: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
5b40: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
5b50: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
5b60: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
5b70: 6c 74 69 70 6c 65 78 53 68 6d 55 6e 6d 61 70 28  ltiplexShmUnmap(
5b80: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43  sqlite3_file *pC
5b90: 6f 6e 6e 2c 20 69 6e 74 20 64 65 6c 65 74 65 46  onn, int deleteF
5ba0: 6c 61 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  lag){.  multiple
5bb0: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
5bc0: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
5bd0: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
5be0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
5bf0: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
5c00: 53 75 62 4f 70 65 6e 28 70 2c 20 30 2c 20 26 72  SubOpen(p, 0, &r
5c10: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20  c, NULL);.  if( 
5c20: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
5c30: 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d  return pSubOpen-
5c40: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 55  >pMethods->xShmU
5c50: 6e 6d 61 70 28 70 53 75 62 4f 70 65 6e 2c 20 64  nmap(pSubOpen, d
5c60: 65 6c 65 74 65 46 6c 61 67 29 3b 0a 20 20 7d 0a  eleteFlag);.  }.
5c70: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
5c80: 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  OK;.}../********
5c90: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
5ca0: 2a 2a 20 50 75 62 6c 69 63 20 49 6e 74 65 72 66  ** Public Interf
5cb0: 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  aces ***********
5cc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
5cd0: 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 49 6e 69 74 69 61  **/./*.** Initia
5ce0: 6c 69 7a 65 20 74 68 65 20 6d 75 6c 74 69 70 6c  lize the multipl
5cf0: 65 78 20 56 46 53 20 73 68 69 6d 2e 20 20 55 73  ex VFS shim.  Us
5d00: 65 20 74 68 65 20 56 46 53 20 6e 61 6d 65 64 20  e the VFS named 
5d10: 7a 4f 72 69 67 56 66 73 4e 61 6d 65 0a 2a 2a 20  zOrigVfsName.** 
5d20: 61 73 20 74 68 65 20 56 46 53 20 74 68 61 74 20  as the VFS that 
5d30: 64 6f 65 73 20 74 68 65 20 61 63 74 75 61 6c 20  does the actual 
5d40: 77 6f 72 6b 2e 20 20 55 73 65 20 74 68 65 20 64  work.  Use the d
5d50: 65 66 61 75 6c 74 20 69 66 0a 2a 2a 20 7a 4f 72  efault if.** zOr
5d60: 69 67 56 66 73 4e 61 6d 65 3d 3d 4e 55 4c 4c 2e  igVfsName==NULL.
5d70: 20 20 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75 6c    .**.** The mul
5d80: 74 69 70 6c 65 78 20 56 46 53 20 73 68 69 6d 20  tiplex VFS shim 
5d90: 69 73 20 6e 61 6d 65 64 20 22 6d 75 6c 74 69 70  is named "multip
5da0: 6c 65 78 22 2e 20 20 49 74 20 77 69 6c 6c 20 62  lex".  It will b
5db0: 65 63 6f 6d 65 20 74 68 65 20 64 65 66 61 75 6c  ecome the defaul
5dc0: 74 0a 2a 2a 20 56 46 53 20 69 66 20 6d 61 6b 65  t.** VFS if make
5dd0: 44 65 66 61 75 6c 74 20 69 73 20 6e 6f 6e 2d 7a  Default is non-z
5de0: 65 72 6f 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20  ero..**.** THIS 
5df0: 52 4f 55 54 49 4e 45 20 49 53 20 4e 4f 54 20 54  ROUTINE IS NOT T
5e00: 48 52 45 41 44 53 41 46 45 2e 20 20 43 61 6c 6c  HREADSAFE.  Call
5e10: 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20 65 78   this routine ex
5e20: 61 63 74 6c 79 20 6f 6e 63 65 0a 2a 2a 20 64 75  actly once.** du
5e30: 72 69 6e 67 20 73 74 61 72 74 2d 75 70 2e 0a 2a  ring start-up..*
5e40: 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75  /.int sqlite3_mu
5e50: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
5e60: 7a 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  ze(const char *z
5e70: 4f 72 69 67 56 66 73 4e 61 6d 65 2c 20 69 6e 74  OrigVfsName, int
5e80: 20 6d 61 6b 65 44 65 66 61 75 6c 74 29 7b 0a 20   makeDefault){. 
5e90: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f   sqlite3_vfs *pO
5ea0: 72 69 67 56 66 73 3b 0a 20 20 69 66 28 20 67 4d  rigVfs;.  if( gM
5eb0: 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69  ultiplex.isIniti
5ec0: 61 6c 69 7a 65 64 20 29 20 72 65 74 75 72 6e 20  alized ) return 
5ed0: 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20  SQLITE_MISUSE;. 
5ee0: 20 70 4f 72 69 67 56 66 73 20 3d 20 73 71 6c 69   pOrigVfs = sqli
5ef0: 74 65 33 5f 76 66 73 5f 66 69 6e 64 28 7a 4f 72  te3_vfs_find(zOr
5f00: 69 67 56 66 73 4e 61 6d 65 29 3b 0a 20 20 69 66  igVfsName);.  if
5f10: 28 20 70 4f 72 69 67 56 66 73 3d 3d 30 20 29 20  ( pOrigVfs==0 ) 
5f20: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 45 52  return SQLITE_ER
5f30: 52 4f 52 3b 0a 20 20 61 73 73 65 72 74 28 20 70  ROR;.  assert( p
5f40: 4f 72 69 67 56 66 73 21 3d 26 67 4d 75 6c 74 69  OrigVfs!=&gMulti
5f50: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 20 29 3b  plex.sThisVfs );
5f60: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d  .  gMultiplex.pM
5f70: 75 74 65 78 20 3d 20 73 71 6c 69 74 65 33 5f 6d  utex = sqlite3_m
5f80: 75 74 65 78 5f 61 6c 6c 6f 63 28 53 51 4c 49 54  utex_alloc(SQLIT
5f90: 45 5f 4d 55 54 45 58 5f 46 41 53 54 29 3b 0a 20  E_MUTEX_FAST);. 
5fa0: 20 69 66 28 20 21 67 4d 75 6c 74 69 70 6c 65 78   if( !gMultiplex
5fb0: 2e 70 4d 75 74 65 78 20 29 7b 0a 20 20 20 20 72  .pMutex ){.    r
5fc0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d  eturn SQLITE_NOM
5fd0: 45 4d 3b 0a 20 20 7d 0a 20 20 67 4d 75 6c 74 69  EM;.  }.  gMulti
5fe0: 70 6c 65 78 2e 7a 4e 61 6d 65 20 3d 20 73 71 6c  plex.zName = sql
5ff0: 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 70 4f 72 69  ite3_malloc(pOri
6000: 67 56 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65  gVfs->mxPathname
6010: 29 3b 0a 20 20 69 66 28 20 21 67 4d 75 6c 74 69  );.  if( !gMulti
6020: 70 6c 65 78 2e 7a 4e 61 6d 65 20 29 7b 0a 20 20  plex.zName ){.  
6030: 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f    sqlite3_mutex_
6040: 66 72 65 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e  free(gMultiplex.
6050: 70 4d 75 74 65 78 29 3b 0a 20 20 20 20 72 65 74  pMutex);.    ret
6060: 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d  urn SQLITE_NOMEM
6070: 3b 0a 20 20 7d 0a 20 20 67 4d 75 6c 74 69 70 6c  ;.  }.  gMultipl
6080: 65 78 2e 6e 43 68 75 6e 6b 53 69 7a 65 20 3d 20  ex.nChunkSize = 
6090: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
60a0: 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b 0a 20 20 67  _CHUNK_SIZE;.  g
60b0: 4d 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68  Multiplex.nMaxCh
60c0: 75 6e 6b 73 20 3d 20 53 51 4c 49 54 45 5f 4d 55  unks = SQLITE_MU
60d0: 4c 54 49 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e  LTIPLEX_MAX_CHUN
60e0: 4b 53 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  KS;.  gMultiplex
60f0: 2e 70 47 72 6f 75 70 73 20 3d 20 4e 55 4c 4c 3b  .pGroups = NULL;
6100: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73  .  gMultiplex.is
6110: 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 31 3b  Initialized = 1;
6120: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f  .  gMultiplex.pO
6130: 72 69 67 56 66 73 20 3d 20 70 4f 72 69 67 56 66  rigVfs = pOrigVf
6140: 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  s;.  gMultiplex.
6150: 73 54 68 69 73 56 66 73 20 3d 20 2a 70 4f 72 69  sThisVfs = *pOri
6160: 67 56 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  gVfs;.  gMultipl
6170: 65 78 2e 73 54 68 69 73 56 66 73 2e 73 7a 4f 73  ex.sThisVfs.szOs
6180: 46 69 6c 65 20 2b 3d 20 73 69 7a 65 6f 66 28 6d  File += sizeof(m
6190: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a 20  ultiplexConn);. 
61a0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
61b0: 73 56 66 73 2e 7a 4e 61 6d 65 20 3d 20 22 6d 75  sVfs.zName = "mu
61c0: 6c 74 69 70 6c 65 78 22 3b 0a 20 20 67 4d 75 6c  ltiplex";.  gMul
61d0: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e  tiplex.sThisVfs.
61e0: 78 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  xOpen = multiple
61f0: 78 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70  xOpen;.  gMultip
6200: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 65  lex.sThisVfs.xDe
6210: 6c 65 74 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  lete = multiplex
6220: 44 65 6c 65 74 65 3b 0a 20 20 67 4d 75 6c 74 69  Delete;.  gMulti
6230: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 41  plex.sThisVfs.xA
6240: 63 63 65 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65  ccess = multiple
6250: 78 41 63 63 65 73 73 3b 0a 20 20 67 4d 75 6c 74  xAccess;.  gMult
6260: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
6270: 46 75 6c 6c 50 61 74 68 6e 61 6d 65 20 3d 20 6d  FullPathname = m
6280: 75 6c 74 69 70 6c 65 78 46 75 6c 6c 50 61 74 68  ultiplexFullPath
6290: 6e 61 6d 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  name;.  gMultipl
62a0: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 4f  ex.sThisVfs.xDlO
62b0: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44  pen = multiplexD
62c0: 6c 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70  lOpen;.  gMultip
62d0: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c  lex.sThisVfs.xDl
62e0: 45 72 72 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65  Error = multiple
62f0: 78 44 6c 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c  xDlError;.  gMul
6300: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e  tiplex.sThisVfs.
6310: 78 44 6c 53 79 6d 20 3d 20 6d 75 6c 74 69 70 6c  xDlSym = multipl
6320: 65 78 44 6c 53 79 6d 3b 0a 20 20 67 4d 75 6c 74  exDlSym;.  gMult
6330: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
6340: 44 6c 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70  DlClose = multip
6350: 6c 65 78 44 6c 43 6c 6f 73 65 3b 0a 20 20 67 4d  lexDlClose;.  gM
6360: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
6370: 73 2e 78 52 61 6e 64 6f 6d 6e 65 73 73 20 3d 20  s.xRandomness = 
6380: 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e  multiplexRandomn
6390: 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ess;.  gMultiple
63a0: 78 2e 73 54 68 69 73 56 66 73 2e 78 53 6c 65 65  x.sThisVfs.xSlee
63b0: 70 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65  p = multiplexSle
63c0: 65 70 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ep;.  gMultiplex
63d0: 2e 73 54 68 69 73 56 66 73 2e 78 43 75 72 72 65  .sThisVfs.xCurre
63e0: 6e 74 54 69 6d 65 20 3d 20 6d 75 6c 74 69 70 6c  ntTime = multipl
63f0: 65 78 43 75 72 72 65 6e 74 54 69 6d 65 3b 0a 20  exCurrentTime;. 
6400: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
6410: 73 56 66 73 2e 78 47 65 74 4c 61 73 74 45 72 72  sVfs.xGetLastErr
6420: 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 47 65  or = multiplexGe
6430: 74 4c 61 73 74 45 72 72 6f 72 3b 0a 20 20 67 4d  tLastError;.  gM
6440: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
6450: 73 2e 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e  s.xCurrentTimeIn
6460: 74 36 34 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43  t64 = multiplexC
6470: 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 3b  urrentTimeInt64;
6480: 0a 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ..  gMultiplex.s
6490: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 69 56 65 72  IoMethodsV1.iVer
64a0: 73 69 6f 6e 20 3d 20 31 3b 0a 20 20 67 4d 75 6c  sion = 1;.  gMul
64b0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
64c0: 73 56 31 2e 78 43 6c 6f 73 65 20 3d 20 6d 75 6c  sV1.xClose = mul
64d0: 74 69 70 6c 65 78 43 6c 6f 73 65 3b 0a 20 20 67  tiplexClose;.  g
64e0: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
64f0: 68 6f 64 73 56 31 2e 78 52 65 61 64 20 3d 20 6d  hodsV1.xRead = m
6500: 75 6c 74 69 70 6c 65 78 52 65 61 64 3b 0a 20 20  ultiplexRead;.  
6510: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
6520: 74 68 6f 64 73 56 31 2e 78 57 72 69 74 65 20 3d  thodsV1.xWrite =
6530: 20 6d 75 6c 74 69 70 6c 65 78 57 72 69 74 65 3b   multiplexWrite;
6540: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
6550: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 54 72 75 6e  oMethodsV1.xTrun
6560: 63 61 74 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  cate = multiplex
6570: 54 72 75 6e 63 61 74 65 3b 0a 20 20 67 4d 75 6c  Truncate;.  gMul
6580: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
6590: 73 56 31 2e 78 53 79 6e 63 20 3d 20 6d 75 6c 74  sV1.xSync = mult
65a0: 69 70 6c 65 78 53 79 6e 63 3b 0a 20 20 67 4d 75  iplexSync;.  gMu
65b0: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
65c0: 64 73 56 31 2e 78 46 69 6c 65 53 69 7a 65 20 3d  dsV1.xFileSize =
65d0: 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 53 69   multiplexFileSi
65e0: 7a 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ze;.  gMultiplex
65f0: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 4c  .sIoMethodsV1.xL
6600: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4c  ock = multiplexL
6610: 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ock;.  gMultiple
6620: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
6630: 55 6e 6c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c  Unlock = multipl
6640: 65 78 55 6e 6c 6f 63 6b 3b 0a 20 20 67 4d 75 6c  exUnlock;.  gMul
6650: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
6660: 73 56 31 2e 78 43 68 65 63 6b 52 65 73 65 72 76  sV1.xCheckReserv
6670: 65 64 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c  edLock = multipl
6680: 65 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c  exCheckReservedL
6690: 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ock;.  gMultiple
66a0: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
66b0: 46 69 6c 65 43 6f 6e 74 72 6f 6c 20 3d 20 6d 75  FileControl = mu
66c0: 6c 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e 74 72  ltiplexFileContr
66d0: 6f 6c 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ol;.  gMultiplex
66e0: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53  .sIoMethodsV1.xS
66f0: 65 63 74 6f 72 53 69 7a 65 20 3d 20 6d 75 6c 74  ectorSize = mult
6700: 69 70 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 3b  iplexSectorSize;
6710: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
6720: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 44 65 76 69  oMethodsV1.xDevi
6730: 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63  ceCharacteristic
6740: 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 65 76  s = multiplexDev
6750: 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69  iceCharacteristi
6760: 63 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  cs;.  gMultiplex
6770: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 20 3d 20  .sIoMethodsV2 = 
6780: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
6790: 74 68 6f 64 73 56 31 3b 0a 20 20 67 4d 75 6c 74  thodsV1;.  gMult
67a0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
67b0: 56 32 2e 69 56 65 72 73 69 6f 6e 20 3d 20 32 3b  V2.iVersion = 2;
67c0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
67d0: 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 4d  oMethodsV2.xShmM
67e0: 61 70 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68  ap = multiplexSh
67f0: 6d 4d 61 70 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  mMap;.  gMultipl
6800: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e  ex.sIoMethodsV2.
6810: 78 53 68 6d 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69  xShmLock = multi
6820: 70 6c 65 78 53 68 6d 4c 6f 63 6b 3b 0a 20 20 67  plexShmLock;.  g
6830: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
6840: 68 6f 64 73 56 32 2e 78 53 68 6d 42 61 72 72 69  hodsV2.xShmBarri
6850: 65 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68  er = multiplexSh
6860: 6d 42 61 72 72 69 65 72 3b 0a 20 20 67 4d 75 6c  mBarrier;.  gMul
6870: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
6880: 73 56 32 2e 78 53 68 6d 55 6e 6d 61 70 20 3d 20  sV2.xShmUnmap = 
6890: 6d 75 6c 74 69 70 6c 65 78 53 68 6d 55 6e 6d 61  multiplexShmUnma
68a0: 70 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73  p;.  sqlite3_vfs
68b0: 5f 72 65 67 69 73 74 65 72 28 26 67 4d 75 6c 74  _register(&gMult
68c0: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2c 20  iplex.sThisVfs, 
68d0: 6d 61 6b 65 44 65 66 61 75 6c 74 29 3b 0a 20 20  makeDefault);.  
68e0: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
68f0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 68 75 74 64  ;.}../*.** Shutd
6900: 6f 77 6e 20 74 68 65 20 6d 75 6c 74 69 70 6c 65  own the multiple
6910: 78 20 73 79 73 74 65 6d 2e 0a 2a 2a 0a 2a 2a 20  x system..**.** 
6920: 41 6c 6c 20 53 51 4c 69 74 65 20 64 61 74 61 62  All SQLite datab
6930: 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20  ase connections 
6940: 6d 75 73 74 20 62 65 20 63 6c 6f 73 65 64 20 62  must be closed b
6950: 65 66 6f 72 65 20 63 61 6c 6c 69 6e 67 20 74 68  efore calling th
6960: 69 73 0a 2a 2a 20 72 6f 75 74 69 6e 65 2e 0a 2a  is.** routine..*
6970: 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49 4e  *.** THIS ROUTIN
6980: 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44 53  E IS NOT THREADS
6990: 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73 20  AFE.  Call this 
69a0: 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79 20  routine exactly 
69b0: 6f 6e 63 65 20 77 68 69 6c 65 0a 2a 2a 20 73 68  once while.** sh
69c0: 75 74 74 69 6e 67 20 64 6f 77 6e 20 69 6e 20 6f  utting down in o
69d0: 72 64 65 72 20 74 6f 20 66 72 65 65 20 61 6c 6c  rder to free all
69e0: 20 72 65 6d 61 69 6e 69 6e 67 20 6d 75 6c 74 69   remaining multi
69f0: 70 6c 65 78 20 67 72 6f 75 70 73 2e 0a 2a 2f 0a  plex groups..*/.
6a00: 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  int sqlite3_mult
6a10: 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 76  iplex_shutdown(v
6a20: 6f 69 64 29 7b 0a 20 20 69 66 28 20 67 4d 75 6c  oid){.  if( gMul
6a30: 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c  tiplex.isInitial
6a40: 69 7a 65 64 3d 3d 30 20 29 20 72 65 74 75 72 6e  ized==0 ) return
6a50: 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a   SQLITE_MISUSE;.
6a60: 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78    if( gMultiplex
6a70: 2e 70 47 72 6f 75 70 73 20 29 20 72 65 74 75 72  .pGroups ) retur
6a80: 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b  n SQLITE_MISUSE;
6a90: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73  .  gMultiplex.is
6aa0: 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 30 3b  Initialized = 0;
6ab0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  .  sqlite3_free(
6ac0: 67 4d 75 6c 74 69 70 6c 65 78 2e 7a 4e 61 6d 65  gMultiplex.zName
6ad0: 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74  );.  sqlite3_mut
6ae0: 65 78 5f 66 72 65 65 28 67 4d 75 6c 74 69 70 6c  ex_free(gMultipl
6af0: 65 78 2e 70 4d 75 74 65 78 29 3b 0a 20 20 73 71  ex.pMutex);.  sq
6b00: 6c 69 74 65 33 5f 76 66 73 5f 75 6e 72 65 67 69  lite3_vfs_unregi
6b10: 73 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78  ster(&gMultiplex
6b20: 2e 73 54 68 69 73 56 66 73 29 3b 0a 20 20 6d 65  .sThisVfs);.  me
6b30: 6d 73 65 74 28 26 67 4d 75 6c 74 69 70 6c 65 78  mset(&gMultiplex
6b40: 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 4d 75 6c  , 0, sizeof(gMul
6b50: 74 69 70 6c 65 78 29 29 3b 0a 20 20 72 65 74 75  tiplex));.  retu
6b60: 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a  rn SQLITE_OK;.}.
6b70: 0a 2f 2a 0a 2a 2a 20 41 64 6a 75 73 74 20 63 68  ./*.** Adjust ch
6b80: 75 6e 6b 69 6e 67 20 70 61 72 61 6d 73 2e 20 20  unking params.  
6b90: 56 46 53 20 73 68 6f 75 6c 64 20 62 65 20 69 6e  VFS should be in
6ba0: 69 74 69 61 6c 69 7a 65 64 20 66 69 72 73 74 2e  itialized first.
6bb0: 0a 2a 2a 20 4e 6f 20 66 69 6c 65 73 20 73 68 6f  .** No files sho
6bc0: 75 6c 64 20 62 65 20 6f 70 65 6e 2e 20 20 52 65  uld be open.  Re
6bd0: 2d 69 6e 74 69 61 6c 69 7a 69 6e 67 20 77 69 6c  -intializing wil
6be0: 6c 20 72 65 73 65 74 20 74 68 65 73 65 0a 2a 2a  l reset these.**
6bf0: 20 74 6f 20 74 68 65 20 64 65 66 61 75 6c 74 2e   to the default.
6c00: 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f  .*/.int sqlite3_
6c10: 6d 75 6c 74 69 70 6c 65 78 5f 73 65 74 28 0a 20  multiplex_set(. 
6c20: 20 69 6e 74 20 6e 43 68 75 6e 6b 53 69 7a 65 2c   int nChunkSize,
6c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c40: 20 2f 2a 20 4d 61 78 20 63 68 75 6e 6b 20 73 69   /* Max chunk si
6c50: 7a 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 4d 61 78  ze */.  int nMax
6c60: 43 68 75 6e 6b 73 20 20 20 20 20 20 20 20 20 20  Chunks          
6c70: 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 78 20 6e          /* Max n
6c80: 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73 20  umber of chunks 
6c90: 2a 2f 0a 29 7b 0a 20 20 69 66 28 20 21 67 4d 75  */.){.  if( !gMu
6ca0: 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61  ltiplex.isInitia
6cb0: 6c 69 7a 65 64 20 29 20 72 65 74 75 72 6e 20 53  lized ) return S
6cc0: 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20  QLITE_MISUSE;.  
6cd0: 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  if( gMultiplex.p
6ce0: 47 72 6f 75 70 73 20 29 20 72 65 74 75 72 6e 20  Groups ) return 
6cf0: 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20  SQLITE_MISUSE;. 
6d00: 20 69 66 28 20 6e 43 68 75 6e 6b 53 69 7a 65 3c   if( nChunkSize<
6d10: 33 32 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49  32 ) return SQLI
6d20: 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 69 66 28  TE_MISUSE;.  if(
6d30: 20 6e 4d 61 78 43 68 75 6e 6b 73 3c 31 20 29 20   nMaxChunks<1 ) 
6d40: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49  return SQLITE_MI
6d50: 53 55 53 45 3b 0a 20 20 69 66 28 20 6e 4d 61 78  SUSE;.  if( nMax
6d60: 43 68 75 6e 6b 73 3e 39 39 20 29 20 72 65 74 75  Chunks>99 ) retu
6d70: 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45  rn SQLITE_MISUSE
6d80: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74  ;.  multiplexEnt
6d90: 65 72 28 29 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  er();.  gMultipl
6da0: 65 78 2e 6e 43 68 75 6e 6b 53 69 7a 65 20 3d 20  ex.nChunkSize = 
6db0: 6e 43 68 75 6e 6b 53 69 7a 65 3b 0a 20 20 67 4d  nChunkSize;.  gM
6dc0: 75 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75  ultiplex.nMaxChu
6dd0: 6e 6b 73 20 3d 20 6e 4d 61 78 43 68 75 6e 6b 73  nks = nMaxChunks
6de0: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  ;.  multiplexLea
6df0: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 53  ve();.  return S
6e00: 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a  QLITE_OK;.}../**
6e10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
6e20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 54 65 73 74  *********** Test
6e30: 20 43 6f 64 65 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a   Code **********
6e40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
6e50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 23 69 66 64 65  *********/.#ifde
6e60: 66 20 53 51 4c 49 54 45 5f 54 45 53 54 0a 23 69  f SQLITE_TEST.#i
6e70: 6e 63 6c 75 64 65 20 3c 74 63 6c 2e 68 3e 0a 0a  nclude <tcl.h>..
6e80: 65 78 74 65 72 6e 20 63 6f 6e 73 74 20 63 68 61  extern const cha
6e90: 72 20 2a 73 71 6c 69 74 65 33 54 65 73 74 45 72  r *sqlite3TestEr
6ea0: 72 6f 72 4e 61 6d 65 28 69 6e 74 29 3b 0a 0a 0a  rorName(int);...
6eb0: 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71  /*.** tclcmd: sq
6ec0: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
6ed0: 69 6e 69 74 69 61 6c 69 7a 65 20 4e 41 4d 45 20  initialize NAME 
6ee0: 4d 41 4b 45 44 45 46 41 55 4c 54 0a 2a 2f 0a 73  MAKEDEFAULT.*/.s
6ef0: 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d  tatic int test_m
6f00: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
6f10: 69 7a 65 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c  ize(.  void * cl
6f20: 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f  ientData,.  Tcl_
6f30: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
6f40: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
6f50: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
6f60: 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 63  v[].){.  const c
6f70: 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20  har *zName;     
6f80: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
6f90: 20 6f 66 20 6e 65 77 20 6d 75 6c 74 69 70 6c 65   of new multiple
6fa0: 78 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6d  x VFS */.  int m
6fb0: 61 6b 65 44 65 66 61 75 6c 74 3b 20 20 20 20 20  akeDefault;     
6fc0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
6fd0: 75 65 20 74 6f 20 6d 61 6b 65 20 74 68 65 20 6e  ue to make the n
6fe0: 65 77 20 56 46 53 20 74 68 65 20 64 65 66 61 75  ew VFS the defau
6ff0: 6c 74 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20  lt */.  int rc; 
7000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7010: 20 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65          /* Value
7020: 20 72 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c   returned by mul
7030: 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a  tiplex_initializ
7040: 65 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45 44  e() */..  UNUSED
7050: 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e  _PARAMETER(clien
7060: 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 50 72  tData);..  /* Pr
7070: 6f 63 65 73 73 20 61 72 67 75 6d 65 6e 74 73 20  ocess arguments 
7080: 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 33  */.  if( objc!=3
7090: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
70a0: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
70b0: 20 31 2c 20 6f 62 6a 76 2c 20 22 4e 41 4d 45 20   1, objv, "NAME 
70c0: 4d 41 4b 45 44 45 46 41 55 4c 54 22 29 3b 0a 20  MAKEDEFAULT");. 
70d0: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
70e0: 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e 61 6d 65  ROR;.  }.  zName
70f0: 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67   = Tcl_GetString
7100: 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20 69 66 28  (objv[1]);.  if(
7110: 20 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61 6e 46   Tcl_GetBooleanF
7120: 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f  romObj(interp, o
7130: 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65 44 65 66  bjv[2], &makeDef
7140: 61 75 6c 74 29 20 29 20 72 65 74 75 72 6e 20 54  ault) ) return T
7150: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 69 66 28 20  CL_ERROR;.  if( 
7160: 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30 27 20 29  zName[0]=='\0' )
7170: 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a 20 20 2f   zName = 0;..  /
7180: 2a 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d  * Call sqlite3_m
7190: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
71a0: 69 7a 65 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20  ize() */.  rc = 
71b0: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
71c0: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 7a 4e 61  x_initialize(zNa
71d0: 6d 65 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29  me, makeDefault)
71e0: 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c  ;.  Tcl_SetResul
71f0: 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20  t(interp, (char 
7200: 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45 72 72  *)sqlite3TestErr
7210: 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f  orName(rc), TCL_
7220: 53 54 41 54 49 43 29 3b 0a 0a 20 20 72 65 74 75  STATIC);..  retu
7230: 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn TCL_OK;.}../*
7240: 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71 6c 69  .** tclcmd: sqli
7250: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
7260: 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74 61 74 69 63  utdown.*/.static
7270: 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69 70   int test_multip
7280: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 0a 20 20  lex_shutdown(.  
7290: 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74  void * clientDat
72a0: 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20  a,.  Tcl_Interp 
72b0: 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f  *interp,.  int o
72c0: 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a  bjc,.  Tcl_Obj *
72d0: 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a  CONST objv[].){.
72e0: 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20    int rc;       
72f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7300: 20 20 2f 2a 20 56 61 6c 75 65 20 72 65 74 75 72    /* Value retur
7310: 6e 65 64 20 62 79 20 6d 75 6c 74 69 70 6c 65 78  ned by multiplex
7320: 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a 2f 0a 0a  _shutdown() */..
7330: 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54    UNUSED_PARAMET
7340: 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b 0a  ER(clientData);.
7350: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 31 20 29  .  if( objc!=1 )
7360: 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e  {.    Tcl_WrongN
7370: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31  umArgs(interp, 1
7380: 2c 20 6f 62 6a 76 2c 20 22 22 29 3b 0a 20 20 20  , objv, "");.   
7390: 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f   return TCL_ERRO
73a0: 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 61 6c  R;.  }..  /* Cal
73b0: 6c 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  l sqlite3_multip
73c0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a  lex_shutdown() *
73d0: 2f 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33  /.  rc = sqlite3
73e0: 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64  _multiplex_shutd
73f0: 6f 77 6e 28 29 3b 0a 20 20 54 63 6c 5f 53 65 74  own();.  Tcl_Set
7400: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28  Result(interp, (
7410: 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65  char *)sqlite3Te
7420: 73 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c  stErrorName(rc),
7430: 20 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20   TCL_STATIC);.. 
7440: 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a   return TCL_OK;.
7450: 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a  }../*.** tclcmd:
7460: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
7470: 65 78 5f 73 65 74 20 43 48 55 4e 4b 5f 53 49 5a  ex_set CHUNK_SIZ
7480: 45 20 4d 41 58 5f 43 48 55 4e 4b 53 0a 2a 2f 0a  E MAX_CHUNKS.*/.
7490: 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f  static int test_
74a0: 6d 75 6c 74 69 70 6c 65 78 5f 73 65 74 28 0a 20  multiplex_set(. 
74b0: 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61   void * clientDa
74c0: 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70  ta,.  Tcl_Interp
74d0: 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20   *interp,.  int 
74e0: 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20  objc,.  Tcl_Obj 
74f0: 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b  *CONST objv[].){
7500: 0a 20 20 69 6e 74 20 6e 43 68 75 6e 6b 53 69 7a  .  int nChunkSiz
7510: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
7520: 20 20 20 2f 2a 20 4d 61 78 20 63 68 75 6e 6b 20     /* Max chunk 
7530: 73 69 7a 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 4d  size */.  int nM
7540: 61 78 43 68 75 6e 6b 73 3b 20 20 20 20 20 20 20  axChunks;       
7550: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 78            /* Max
7560: 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b   number of chunk
7570: 73 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20 20  s */.  int rc;  
7580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7590: 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20         /* Value 
75a0: 72 65 74 75 72 6e 65 64 20 62 79 20 73 71 6c 69  returned by sqli
75b0: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 65  te3_multiplex_se
75c0: 74 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45 44  t() */..  UNUSED
75d0: 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e  _PARAMETER(clien
75e0: 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 50 72  tData);..  /* Pr
75f0: 6f 63 65 73 73 20 61 72 67 75 6d 65 6e 74 73 20  ocess arguments 
7600: 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 33  */.  if( objc!=3
7610: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
7620: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
7630: 20 31 2c 20 6f 62 6a 76 2c 20 22 43 48 55 4e 4b   1, objv, "CHUNK
7640: 5f 53 49 5a 45 20 4d 41 58 5f 43 48 55 4e 4b 53  _SIZE MAX_CHUNKS
7650: 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54  ");.    return T
7660: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20  CL_ERROR;.  }.  
7670: 69 66 28 20 54 63 6c 5f 47 65 74 49 6e 74 46 72  if( Tcl_GetIntFr
7680: 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f 62  omObj(interp, ob
7690: 6a 76 5b 31 5d 2c 20 26 6e 43 68 75 6e 6b 53 69  jv[1], &nChunkSi
76a0: 7a 65 29 20 29 20 72 65 74 75 72 6e 20 54 43 4c  ze) ) return TCL
76b0: 5f 45 52 52 4f 52 3b 0a 20 20 69 66 28 20 54 63  _ERROR;.  if( Tc
76c0: 6c 5f 47 65 74 49 6e 74 46 72 6f 6d 4f 62 6a 28  l_GetIntFromObj(
76d0: 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 32 5d 2c  interp, objv[2],
76e0: 20 26 6e 4d 61 78 43 68 75 6e 6b 73 29 20 29 20   &nMaxChunks) ) 
76f0: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
7700: 3b 0a 0a 20 20 2f 2a 20 49 6e 76 6f 6b 65 20 73  ;..  /* Invoke s
7710: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
7720: 5f 73 65 74 28 29 20 2a 2f 0a 20 20 72 63 20 3d  _set() */.  rc =
7730: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
7740: 65 78 5f 73 65 74 28 6e 43 68 75 6e 6b 53 69 7a  ex_set(nChunkSiz
7750: 65 2c 20 6e 4d 61 78 43 68 75 6e 6b 73 29 3b 0a  e, nMaxChunks);.
7760: 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c 74  .  Tcl_SetResult
7770: 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20 2a  (interp, (char *
7780: 29 73 71 6c 69 74 65 33 54 65 73 74 45 72 72 6f  )sqlite3TestErro
7790: 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f 53  rName(rc), TCL_S
77a0: 54 41 54 49 43 29 3b 0a 20 20 72 65 74 75 72 6e  TATIC);.  return
77b0: 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a   TCL_OK;.}../*.*
77c0: 2a 20 74 63 6c 63 6d 64 3a 20 20 73 71 6c 69 74  * tclcmd:  sqlit
77d0: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d  e3_multiplex_dum
77e0: 70 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  p.*/.static int 
77f0: 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 64  test_multiplex_d
7800: 75 6d 70 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c  ump(.  void * cl
7810: 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f  ientData,.  Tcl_
7820: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
7830: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
7840: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
7850: 76 5b 5d 0a 29 7b 0a 20 20 54 63 6c 5f 4f 62 6a  v[].){.  Tcl_Obj
7860: 20 2a 70 52 65 73 75 6c 74 3b 0a 20 20 54 63 6c   *pResult;.  Tcl
7870: 5f 4f 62 6a 20 2a 70 47 72 6f 75 70 54 65 72 6d  _Obj *pGroupTerm
7880: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  ;.  multiplexGro
7890: 75 70 20 2a 70 47 72 6f 75 70 3b 0a 20 20 69 6e  up *pGroup;.  in
78a0: 74 20 69 3b 0a 20 20 69 6e 74 20 6e 43 68 75 6e  t i;.  int nChun
78b0: 6b 73 20 3d 20 30 3b 0a 0a 20 20 55 4e 55 53 45  ks = 0;..  UNUSE
78c0: 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65  D_PARAMETER(clie
78d0: 6e 74 44 61 74 61 29 3b 0a 20 20 55 4e 55 53 45  ntData);.  UNUSE
78e0: 44 5f 50 41 52 41 4d 45 54 45 52 28 6f 62 6a 63  D_PARAMETER(objc
78f0: 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  );.  UNUSED_PARA
7900: 4d 45 54 45 52 28 6f 62 6a 76 29 3b 0a 0a 20 20  METER(objv);..  
7910: 70 52 65 73 75 6c 74 20 3d 20 54 63 6c 5f 4e 65  pResult = Tcl_Ne
7920: 77 4f 62 6a 28 29 3b 0a 20 20 6d 75 6c 74 69 70  wObj();.  multip
7930: 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 66 6f  lexEnter();.  fo
7940: 72 28 70 47 72 6f 75 70 3d 67 4d 75 6c 74 69 70  r(pGroup=gMultip
7950: 6c 65 78 2e 70 47 72 6f 75 70 73 3b 20 70 47 72  lex.pGroups; pGr
7960: 6f 75 70 3b 20 70 47 72 6f 75 70 3d 70 47 72 6f  oup; pGroup=pGro
7970: 75 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20  up->pNext){.    
7980: 70 47 72 6f 75 70 54 65 72 6d 20 3d 20 54 63 6c  pGroupTerm = Tcl
7990: 5f 4e 65 77 4f 62 6a 28 29 3b 0a 0a 20 20 20 20  _NewObj();..    
79a0: 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 5b 70 47  pGroup->zName[pG
79b0: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 5d 20 3d 20 27  roup->nName] = '
79c0: 5c 30 27 3b 0a 20 20 20 20 54 63 6c 5f 4c 69 73  \0';.    Tcl_Lis
79d0: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
79e0: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
79f0: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
7a00: 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f 62 6a  Tcl_NewStringObj
7a10: 28 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20  (pGroup->zName, 
7a20: 2d 31 29 29 3b 0a 20 20 20 20 54 63 6c 5f 4c 69  -1));.    Tcl_Li
7a30: 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65  stObjAppendEleme
7a40: 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75  nt(interp, pGrou
7a50: 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20  pTerm,.         
7a60: 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70   Tcl_NewIntObj(p
7a70: 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 29 29 3b 0a  Group->nName));.
7a80: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
7a90: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
7aa0: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
7ab0: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
7ac0: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
7ad0: 3e 66 6c 61 67 73 29 29 3b 0a 0a 20 20 20 20 2f  >flags));..    /
7ae0: 2a 20 63 6f 75 6e 74 20 6e 75 6d 62 65 72 20 6f  * count number o
7af0: 66 20 63 68 75 6e 6b 73 20 77 69 74 68 20 6f 70  f chunks with op
7b00: 65 6e 20 68 61 6e 64 6c 65 73 20 2a 2f 0a 20 20  en handles */.  
7b10: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 67 4d 75    for(i=0; i<gMu
7b20: 6c 74 69 70 6c 65 78 2e 6e 4d 61 78 43 68 75 6e  ltiplex.nMaxChun
7b30: 6b 73 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20  ks; i++){.      
7b40: 69 66 28 20 70 47 72 6f 75 70 2d 3e 62 4f 70 65  if( pGroup->bOpe
7b50: 6e 5b 69 5d 20 29 20 6e 43 68 75 6e 6b 73 2b 2b  n[i] ) nChunks++
7b60: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 54 63 6c 5f  ;.    }.    Tcl_
7b70: 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65  ListObjAppendEle
7b80: 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72  ment(interp, pGr
7b90: 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20  oupTerm,.       
7ba0: 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a     Tcl_NewIntObj
7bb0: 28 6e 43 68 75 6e 6b 73 29 29 3b 0a 0a 20 20 20  (nChunks));..   
7bc0: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65   Tcl_ListObjAppe
7bd0: 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70  ndElement(interp
7be0: 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20  , pGroupTerm,.  
7bf0: 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49          Tcl_NewI
7c00: 6e 74 4f 62 6a 28 67 4d 75 6c 74 69 70 6c 65 78  ntObj(gMultiplex
7c10: 2e 6e 43 68 75 6e 6b 53 69 7a 65 29 29 3b 0a 20  .nChunkSize));. 
7c20: 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70     Tcl_ListObjAp
7c30: 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65  pendElement(inte
7c40: 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a  rp, pGroupTerm,.
7c50: 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65            Tcl_Ne
7c60: 77 49 6e 74 4f 62 6a 28 67 4d 75 6c 74 69 70 6c  wIntObj(gMultipl
7c70: 65 78 2e 6e 4d 61 78 43 68 75 6e 6b 73 29 29 3b  ex.nMaxChunks));
7c80: 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62  ..    Tcl_ListOb
7c90: 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69  jAppendElement(i
7ca0: 6e 74 65 72 70 2c 20 70 52 65 73 75 6c 74 2c 20  nterp, pResult, 
7cb0: 70 47 72 6f 75 70 54 65 72 6d 29 3b 0a 20 20 7d  pGroupTerm);.  }
7cc0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76  .  multiplexLeav
7cd0: 65 28 29 3b 0a 20 20 54 63 6c 5f 53 65 74 4f 62  e();.  Tcl_SetOb
7ce0: 6a 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20  jResult(interp, 
7cf0: 70 52 65 73 75 6c 74 29 3b 0a 20 20 72 65 74 75  pResult);.  retu
7d00: 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn TCL_OK;.}../*
7d10: 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74 69 6e 65  .** This routine
7d20: 20 72 65 67 69 73 74 65 72 73 20 74 68 65 20 63   registers the c
7d30: 75 73 74 6f 6d 20 54 43 4c 20 63 6f 6d 6d 61 6e  ustom TCL comman
7d40: 64 73 20 64 65 66 69 6e 65 64 20 69 6e 20 74 68  ds defined in th
7d50: 69 73 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 20 20 54  is.** module.  T
7d60: 68 69 73 20 73 68 6f 75 6c 64 20 62 65 20 74 68  his should be th
7d70: 65 20 6f 6e 6c 79 20 70 72 6f 63 65 64 75 72 65  e only procedure
7d80: 20 76 69 73 69 62 6c 65 20 66 72 6f 6d 20 6f 75   visible from ou
7d90: 74 73 69 64 65 0a 2a 2a 20 6f 66 20 74 68 69 73  tside.** of this
7da0: 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 69 6e 74 20   module..*/.int 
7db0: 53 71 6c 69 74 65 6d 75 6c 74 69 70 6c 65 78 5f  Sqlitemultiplex_
7dc0: 49 6e 69 74 28 54 63 6c 5f 49 6e 74 65 72 70 20  Init(Tcl_Interp 
7dd0: 2a 69 6e 74 65 72 70 29 7b 0a 20 20 73 74 61 74  *interp){.  stat
7de0: 69 63 20 73 74 72 75 63 74 20 7b 0a 20 20 20 20  ic struct {.    
7df0: 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20   char *zName;.  
7e00: 20 20 20 54 63 6c 5f 4f 62 6a 43 6d 64 50 72 6f     Tcl_ObjCmdPro
7e10: 63 20 2a 78 50 72 6f 63 3b 0a 20 20 7d 20 61 43  c *xProc;.  } aC
7e20: 6d 64 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22  md[] = {.    { "
7e30: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
7e40: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 22 2c 20 74  x_initialize", t
7e50: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e  est_multiplex_in
7e60: 69 74 69 61 6c 69 7a 65 20 7d 2c 0a 20 20 20 20  itialize },.    
7e70: 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69  { "sqlite3_multi
7e80: 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 22 2c 20  plex_shutdown", 
7e90: 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73  test_multiplex_s
7ea0: 68 75 74 64 6f 77 6e 20 7d 2c 0a 20 20 20 20 7b  hutdown },.    {
7eb0: 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70   "sqlite3_multip
7ec0: 6c 65 78 5f 73 65 74 22 2c 20 74 65 73 74 5f 6d  lex_set", test_m
7ed0: 75 6c 74 69 70 6c 65 78 5f 73 65 74 20 7d 2c 0a  ultiplex_set },.
7ee0: 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d      { "sqlite3_m
7ef0: 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 22 2c 20  ultiplex_dump", 
7f00: 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 64  test_multiplex_d
7f10: 75 6d 70 20 7d 2c 0a 20 20 7d 3b 0a 20 20 69 6e  ump },.  };.  in
7f20: 74 20 69 3b 0a 0a 20 20 66 6f 72 28 69 3d 30 3b  t i;..  for(i=0;
7f30: 20 69 3c 73 69 7a 65 6f 66 28 61 43 6d 64 29 2f   i<sizeof(aCmd)/
7f40: 73 69 7a 65 6f 66 28 61 43 6d 64 5b 30 5d 29 3b  sizeof(aCmd[0]);
7f50: 20 69 2b 2b 29 7b 0a 20 20 20 20 54 63 6c 5f 43   i++){.    Tcl_C
7f60: 72 65 61 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28  reateObjCommand(
7f70: 69 6e 74 65 72 70 2c 20 61 43 6d 64 5b 69 5d 2e  interp, aCmd[i].
7f80: 7a 4e 61 6d 65 2c 20 61 43 6d 64 5b 69 5d 2e 78  zName, aCmd[i].x
7f90: 50 72 6f 63 2c 20 30 2c 20 30 29 3b 0a 20 20 7d  Proc, 0, 0);.  }
7fa0: 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f  ..  return TCL_O
7fb0: 4b 3b 0a 7d 0a 23 65 6e 64 69 66 0a              K;.}.#endif.