/ Hex Artifact Content
Login

Artifact 3147c64c34721f088d5ab20f85dabd5d7732c007:


0000: 2f 2a 0a 2a 2a 20 32 30 30 35 20 44 65 63 65 6d  /*.** 2005 Decem
0010: 62 65 72 20 31 34 0a 2a 2a 0a 2a 2a 20 54 68 65  ber 14.**.** The
0020: 20 61 75 74 68 6f 72 20 64 69 73 63 6c 61 69 6d   author disclaim
0030: 73 20 63 6f 70 79 72 69 67 68 74 20 74 6f 20 74  s copyright to t
0040: 68 69 73 20 73 6f 75 72 63 65 20 63 6f 64 65 2e  his source code.
0050: 20 20 49 6e 20 70 6c 61 63 65 20 6f 66 0a 2a 2a    In place of.**
0060: 20 61 20 6c 65 67 61 6c 20 6e 6f 74 69 63 65 2c   a legal notice,
0070: 20 68 65 72 65 20 69 73 20 61 20 62 6c 65 73 73   here is a bless
0080: 69 6e 67 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 4d 61  ing:.**.**    Ma
0090: 79 20 79 6f 75 20 64 6f 20 67 6f 6f 64 20 61 6e  y you do good an
00a0: 64 20 6e 6f 74 20 65 76 69 6c 2e 0a 2a 2a 20 20  d not evil..**  
00b0: 20 20 4d 61 79 20 79 6f 75 20 66 69 6e 64 20 66    May you find f
00c0: 6f 72 67 69 76 65 6e 65 73 73 20 66 6f 72 20 79  orgiveness for y
00d0: 6f 75 72 73 65 6c 66 20 61 6e 64 20 66 6f 72 67  ourself and forg
00e0: 69 76 65 20 6f 74 68 65 72 73 2e 0a 2a 2a 20 20  ive others..**  
00f0: 20 20 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20    May you share 
0100: 66 72 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61  freely, never ta
0110: 6b 69 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79  king more than y
0120: 6f 75 20 67 69 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a  ou 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 2a 0a 2a 2a 0a 2a 2a 20 54 68 69 73  *****.**.** This
0180: 20 66 69 6c 65 20 63 6f 6e 74 61 69 6e 73 20 61   file contains a
0190: 6e 20 65 78 61 6d 70 6c 65 20 69 6d 70 6c 65 6d  n example implem
01a0: 65 6e 74 61 74 69 6f 6e 20 6f 66 20 61 6e 20 61  entation of an a
01b0: 73 79 6e 63 68 72 6f 6e 6f 75 73 20 49 4f 20 0a  synchronous IO .
01c0: 2a 2a 20 62 61 63 6b 65 6e 64 20 66 6f 72 20 53  ** backend for S
01d0: 51 4c 69 74 65 2e 0a 2a 2a 0a 2a 2a 20 57 48 41  QLite..**.** WHA
01e0: 54 20 49 53 20 41 53 59 4e 43 48 52 4f 4e 4f 55  T IS ASYNCHRONOU
01f0: 53 20 49 2f 4f 3f 0a 2a 2a 0a 2a 2a 20 57 69 74  S I/O?.**.** Wit
0200: 68 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20 49  h asynchronous I
0210: 2f 4f 2c 20 77 72 69 74 65 20 72 65 71 75 65 73  /O, write reques
0220: 74 73 20 61 72 65 20 68 61 6e 64 6c 65 64 20 62  ts are handled b
0230: 79 20 61 20 73 65 70 61 72 61 74 65 20 74 68 72  y a separate thr
0240: 65 61 64 0a 2a 2a 20 72 75 6e 6e 69 6e 67 20 69  ead.** running i
0250: 6e 20 74 68 65 20 62 61 63 6b 67 72 6f 75 6e 64  n the background
0260: 2e 20 20 54 68 69 73 20 6d 65 61 6e 73 20 74 68  .  This means th
0270: 61 74 20 74 68 65 20 74 68 72 65 61 64 20 74 68  at the thread th
0280: 61 74 20 69 6e 69 74 69 61 74 65 73 0a 2a 2a 20  at initiates.** 
0290: 61 20 64 61 74 61 62 61 73 65 20 77 72 69 74 65  a database write
02a0: 20 64 6f 65 73 20 6e 6f 74 20 68 61 76 65 20 74   does not have t
02b0: 6f 20 77 61 69 74 20 66 6f 72 20 28 73 6f 6d 65  o wait for (some
02c0: 74 69 6d 65 73 20 73 6c 6f 77 29 20 64 69 73 6b  times slow) disk
02d0: 20 49 2f 4f 0a 2a 2a 20 74 6f 20 6f 63 63 75 72   I/O.** to occur
02e0: 2e 20 20 54 68 65 20 77 72 69 74 65 20 73 65 65  .  The write see
02f0: 6d 73 20 74 6f 20 68 61 70 70 65 6e 20 76 65 72  ms to happen ver
0300: 79 20 71 75 69 63 6b 6c 79 2c 20 74 68 6f 75 67  y quickly, thoug
0310: 68 20 69 6e 20 72 65 61 6c 69 74 79 0a 2a 2a 20  h in reality.** 
0320: 69 74 20 69 73 20 68 61 70 70 65 6e 69 6e 67 20  it is happening 
0330: 61 74 20 69 74 73 20 75 73 75 61 6c 20 73 6c 6f  at its usual slo
0340: 77 20 70 61 63 65 20 69 6e 20 74 68 65 20 62 61  w pace in the ba
0350: 63 6b 67 72 6f 75 6e 64 2e 0a 2a 2a 0a 2a 2a 20  ckground..**.** 
0360: 41 73 79 6e 63 68 72 6f 6e 6f 75 73 20 49 2f 4f  Asynchronous I/O
0370: 20 61 70 70 65 61 72 73 20 74 6f 20 67 69 76 65   appears to give
0380: 20 62 65 74 74 65 72 20 72 65 73 70 6f 6e 73 69   better responsi
0390: 76 65 6e 65 73 73 2c 20 62 75 74 20 61 74 20 61  veness, but at a
03a0: 20 70 72 69 63 65 2e 0a 2a 2a 20 59 6f 75 20 6c   price..** You l
03b0: 6f 73 65 20 74 68 65 20 44 75 72 61 62 6c 65 20  ose the Durable 
03c0: 70 72 6f 70 65 72 74 79 2e 20 20 57 69 74 68 20  property.  With 
03d0: 74 68 65 20 64 65 66 61 75 6c 74 20 49 2f 4f 20  the default I/O 
03e0: 62 61 63 6b 65 6e 64 20 6f 66 20 53 51 4c 69 74  backend of SQLit
03f0: 65 2c 0a 2a 2a 20 6f 6e 63 65 20 61 20 77 72 69  e,.** once a wri
0400: 74 65 20 63 6f 6d 70 6c 65 74 65 73 2c 20 79 6f  te completes, yo
0410: 75 20 6b 6e 6f 77 20 74 68 61 74 20 74 68 65 20  u know that the 
0420: 69 6e 66 6f 72 6d 61 74 69 6f 6e 20 79 6f 75 20  information you 
0430: 77 72 6f 74 65 20 69 73 0a 2a 2a 20 73 61 66 65  wrote is.** safe
0440: 6c 79 20 6f 6e 20 64 69 73 6b 2e 20 20 57 69 74  ly on disk.  Wit
0450: 68 20 74 68 65 20 61 73 79 6e 63 68 72 6f 6e 6f  h the asynchrono
0460: 75 73 20 49 2f 4f 2c 20 74 68 69 73 20 69 73 20  us I/O, this is 
0470: 6e 6f 74 20 74 68 65 20 63 61 73 65 2e 20 20 49  not the case.  I
0480: 66 0a 2a 2a 20 79 6f 75 72 20 70 72 6f 67 72 61  f.** your progra
0490: 6d 20 63 72 61 73 68 65 73 20 6f 72 20 69 66 20  m crashes or if 
04a0: 61 20 70 6f 77 65 72 20 6c 6f 73 65 20 6f 63 63  a power lose occ
04b0: 75 72 73 20 61 66 74 65 72 20 74 68 65 20 64 61  urs after the da
04c0: 74 61 62 61 73 65 0a 2a 2a 20 77 72 69 74 65 20  tabase.** write 
04d0: 62 75 74 20 62 65 66 6f 72 65 20 74 68 65 20 61  but before the a
04e0: 73 79 6e 63 68 72 6f 6e 6f 75 73 20 77 72 69 74  synchronous writ
04f0: 65 20 74 68 72 65 61 64 20 68 61 73 20 63 6f 6d  e thread has com
0500: 70 6c 65 74 65 64 2c 20 74 68 65 6e 20 74 68 65  pleted, then the
0510: 0a 2a 2a 20 64 61 74 61 62 61 73 65 20 63 68 61  .** database cha
0520: 6e 67 65 20 6d 69 67 68 74 20 6e 65 76 65 72 20  nge might never 
0530: 6d 61 6b 65 20 69 74 20 74 6f 20 64 69 73 6b 20  make it to disk 
0540: 61 6e 64 20 74 68 65 20 6e 65 78 74 20 75 73 65  and the next use
0550: 72 20 6f 66 20 74 68 65 0a 2a 2a 20 64 61 74 61  r of the.** data
0560: 62 61 73 65 20 6d 69 67 68 74 20 6e 6f 74 20 73  base might not s
0570: 65 65 20 79 6f 75 72 20 63 68 61 6e 67 65 2e 0a  ee your change..
0580: 2a 2a 0a 2a 2a 20 59 6f 75 20 6c 6f 73 65 20 44  **.** You lose D
0590: 75 72 61 62 69 6c 69 74 79 20 77 69 74 68 20 61  urability with a
05a0: 73 79 6e 63 68 72 6f 6e 6f 75 73 20 49 2f 4f 2c  synchronous I/O,
05b0: 20 62 75 74 20 79 6f 75 20 73 74 69 6c 6c 20 72   but you still r
05c0: 65 74 61 69 6e 20 74 68 65 0a 2a 2a 20 6f 74 68  etain the.** oth
05d0: 65 72 20 70 61 72 74 73 20 6f 66 20 41 43 49 44  er parts of ACID
05e0: 3a 20 20 41 74 6f 6d 69 63 2c 20 20 43 6f 6e 73  :  Atomic,  Cons
05f0: 69 73 74 65 6e 74 2c 20 61 6e 64 20 49 73 6f 6c  istent, and Isol
0600: 61 74 65 64 2e 20 20 4d 61 6e 79 0a 2a 2a 20 61  ated.  Many.** a
0610: 70 70 6c 69 61 74 69 6f 6e 73 20 67 65 74 20 61  ppliations get a
0620: 6c 6f 6e 67 20 66 69 6e 65 20 77 69 74 68 6f 75  long fine withou
0630: 74 20 74 68 65 20 44 75 72 61 62 6c 69 74 79 2e  t the Durablity.
0640: 0a 2a 2a 0a 2a 2a 20 48 4f 57 20 49 54 20 57 4f  .**.** HOW IT WO
0650: 52 4b 53 0a 2a 2a 0a 2a 2a 20 41 73 79 6e 63 68  RKS.**.** Asynch
0660: 72 6f 6e 6f 75 73 20 49 2f 4f 20 77 6f 72 6b 73  ronous I/O works
0670: 20 62 79 20 63 72 65 61 74 69 6e 67 20 61 20 73   by creating a s
0680: 70 65 63 69 61 6c 20 53 51 4c 69 74 65 20 22 76  pecial SQLite "v
0690: 66 73 22 20 73 74 72 75 63 74 75 72 65 0a 2a 2a  fs" structure.**
06a0: 20 61 6e 64 20 72 65 67 69 73 74 65 72 69 6e 67   and registering
06b0: 20 69 74 20 77 69 74 68 20 73 71 6c 69 74 65 33   it with sqlite3
06c0: 5f 76 66 73 5f 72 65 67 69 73 74 65 72 28 29 2e  _vfs_register().
06d0: 20 57 68 65 6e 20 66 69 6c 65 73 20 6f 70 65 6e   When files open
06e0: 65 64 20 76 69 61 20 0a 2a 2a 20 74 68 69 73 20  ed via .** this 
06f0: 76 66 73 20 61 72 65 20 77 72 69 74 74 65 6e 20  vfs are written 
0700: 74 6f 20 28 75 73 69 6e 67 20 73 71 6c 69 74 65  to (using sqlite
0710: 33 4f 73 57 72 69 74 65 28 29 29 2c 20 74 68 65  3OsWrite()), the
0720: 20 64 61 74 61 20 69 73 20 6e 6f 74 20 0a 2a 2a   data is not .**
0730: 20 77 72 69 74 74 65 6e 20 64 69 72 65 63 74 6c   written directl
0740: 79 20 74 6f 20 64 69 73 6b 2c 20 62 75 74 20 69  y to disk, but i
0750: 73 20 70 6c 61 63 65 64 20 69 6e 20 74 68 65 20  s placed in the 
0760: 22 77 72 69 74 65 2d 71 75 65 75 65 22 20 74 6f  "write-queue" to
0770: 20 62 65 0a 2a 2a 20 68 61 6e 64 6c 65 64 20 62   be.** handled b
0780: 79 20 74 68 65 20 62 61 63 6b 67 72 6f 75 6e 64  y the background
0790: 20 74 68 72 65 61 64 2e 0a 2a 2a 0a 2a 2a 20 57   thread..**.** W
07a0: 68 65 6e 20 66 69 6c 65 73 20 6f 70 65 6e 65 64  hen files opened
07b0: 20 77 69 74 68 20 74 68 65 20 61 73 79 6e 63 68   with the asynch
07c0: 72 6f 6e 6f 75 73 20 76 66 73 20 61 72 65 20 72  ronous vfs are r
07d0: 65 61 64 20 66 72 6f 6d 20 0a 2a 2a 20 28 75 73  ead from .** (us
07e0: 69 6e 67 20 73 71 6c 69 74 65 33 4f 73 52 65 61  ing sqlite3OsRea
07f0: 64 28 29 29 2c 20 74 68 65 20 64 61 74 61 20 69  d()), the data i
0800: 73 20 72 65 61 64 20 66 72 6f 6d 20 74 68 65 20  s read from the 
0810: 66 69 6c 65 20 6f 6e 20 0a 2a 2a 20 64 69 73 6b  file on .** disk
0820: 20 61 6e 64 20 74 68 65 20 77 72 69 74 65 2d 71   and the write-q
0830: 75 65 75 65 2c 20 73 6f 20 74 68 61 74 20 66 72  ueue, so that fr
0840: 6f 6d 20 74 68 65 20 70 6f 69 6e 74 20 6f 66 20  om the point of 
0850: 76 69 65 77 20 6f 66 0a 2a 2a 20 74 68 65 20 76  view of.** the v
0860: 66 73 20 72 65 61 64 65 72 20 74 68 65 20 4f 73  fs reader the Os
0870: 57 72 69 74 65 28 29 20 61 70 70 65 61 72 73 20  Write() appears 
0880: 74 6f 20 68 61 76 65 20 61 6c 72 65 61 64 79 20  to have already 
0890: 63 6f 6d 70 6c 65 74 65 64 2e 0a 2a 2a 0a 2a 2a  completed..**.**
08a0: 20 54 68 65 20 73 70 65 63 69 61 6c 20 76 66 73   The special vfs
08b0: 20 69 73 20 72 65 67 69 73 74 65 72 65 64 20 28   is registered (
08c0: 61 6e 64 20 75 6e 72 65 67 69 73 74 65 72 65 64  and unregistered
08d0: 29 20 62 79 20 63 61 6c 6c 73 20 74 6f 20 0a 2a  ) by calls to .*
08e0: 2a 20 66 75 6e 63 74 69 6f 6e 20 61 73 79 6e 63  * function async
08f0: 45 6e 61 62 6c 65 28 29 20 28 73 65 65 20 62 65  Enable() (see be
0900: 6c 6f 77 29 2e 0a 2a 2a 0a 2a 2a 20 4c 49 4d 49  low)..**.** LIMI
0910: 54 41 54 49 4f 4e 53 0a 2a 2a 0a 2a 2a 20 54 68  TATIONS.**.** Th
0920: 69 73 20 64 65 6d 6f 6e 73 74 72 61 74 69 6f 6e  is demonstration
0930: 20 63 6f 64 65 20 69 73 20 64 65 6c 69 62 65 72   code is deliber
0940: 61 74 65 6c 79 20 6b 65 70 74 20 73 69 6d 70 6c  ately kept simpl
0950: 65 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 6b 65  e in order to ke
0960: 65 70 0a 2a 2a 20 74 68 65 20 6d 61 69 6e 20 69  ep.** the main i
0970: 64 65 61 73 20 63 6c 65 61 72 20 61 6e 64 20 65  deas clear and e
0980: 61 73 79 20 74 6f 20 75 6e 64 65 72 73 74 61 6e  asy to understan
0990: 64 2e 20 20 52 65 61 6c 20 61 70 70 6c 69 63 61  d.  Real applica
09a0: 74 69 6f 6e 73 20 74 68 61 74 0a 2a 2a 20 77 61  tions that.** wa
09b0: 6e 74 20 74 6f 20 64 6f 20 61 73 79 6e 63 68 72  nt to do asynchr
09c0: 6f 6e 6f 75 73 20 49 2f 4f 20 6d 69 67 68 74 20  onous I/O might 
09d0: 77 61 6e 74 20 74 6f 20 61 64 64 20 61 64 64 69  want to add addi
09e0: 74 69 6f 6e 61 6c 20 63 61 70 61 62 69 6c 69 74  tional capabilit
09f0: 69 65 73 2e 0a 2a 2a 20 46 6f 72 20 65 78 61 6d  ies..** For exam
0a00: 70 6c 65 2c 20 69 6e 20 74 68 69 73 20 64 65 6d  ple, in this dem
0a10: 6f 6e 73 74 72 61 74 69 6f 6e 20 69 66 20 77 72  onstration if wr
0a20: 69 74 65 73 20 61 72 65 20 68 61 70 70 65 6e 69  ites are happeni
0a30: 6e 67 20 61 74 20 61 20 73 74 65 61 64 79 0a 2a  ng at a steady.*
0a40: 2a 20 73 74 72 65 61 6d 20 74 68 61 74 20 65 78  * stream that ex
0a50: 63 65 65 64 73 20 74 68 65 20 49 2f 4f 20 63 61  ceeds the I/O ca
0a60: 70 61 62 69 6c 69 74 79 20 6f 66 20 74 68 65 20  pability of the 
0a70: 62 61 63 6b 67 72 6f 75 6e 64 20 77 72 69 74 65  background write
0a80: 72 20 74 68 72 65 61 64 2c 0a 2a 2a 20 74 68 65  r thread,.** the
0a90: 20 71 75 65 75 65 20 6f 66 20 70 65 6e 64 69 6e   queue of pendin
0aa0: 67 20 77 72 69 74 65 20 6f 70 65 72 61 74 69 6f  g write operatio
0ab0: 6e 73 20 77 69 6c 6c 20 67 72 6f 77 20 77 69 74  ns will grow wit
0ac0: 68 6f 75 74 20 62 6f 75 6e 64 20 75 6e 74 69 6c  hout bound until
0ad0: 20 77 65 0a 2a 2a 20 72 75 6e 20 6f 75 74 20 6f   we.** run out o
0ae0: 66 20 6d 65 6d 6f 72 79 2e 20 20 55 73 65 72 73  f memory.  Users
0af0: 20 6f 66 20 74 68 69 73 20 74 65 63 68 6e 69 71   of this techniq
0b00: 75 65 20 6d 61 79 20 77 61 6e 74 20 74 6f 20 6b  ue may want to k
0b10: 65 65 70 20 74 72 61 63 6b 20 6f 66 0a 2a 2a 20  eep track of.** 
0b20: 74 68 65 20 71 75 61 6e 74 69 74 79 20 6f 66 20  the quantity of 
0b30: 70 65 6e 64 69 6e 67 20 77 72 69 74 65 73 20 61  pending writes a
0b40: 6e 64 20 73 74 6f 70 20 61 63 63 65 70 74 69 6e  nd stop acceptin
0b50: 67 20 6e 65 77 20 77 72 69 74 65 20 72 65 71 75  g new write requ
0b60: 65 73 74 73 0a 2a 2a 20 77 68 65 6e 20 74 68 65  ests.** when the
0b70: 20 62 75 66 66 65 72 20 67 65 74 73 20 74 6f 20   buffer gets to 
0b80: 62 65 20 74 6f 6f 20 62 69 67 2e 0a 2a 2a 0a 2a  be too big..**.*
0b90: 2a 20 4c 4f 43 4b 49 4e 47 20 2b 20 43 4f 4e 43  * LOCKING + CONC
0ba0: 55 52 52 45 4e 43 59 0a 2a 2a 0a 2a 2a 20 4d 75  URRENCY.**.** Mu
0bb0: 6c 74 69 70 6c 65 20 63 6f 6e 6e 65 63 74 69 6f  ltiple connectio
0bc0: 6e 73 20 66 72 6f 6d 20 77 69 74 68 69 6e 20 61  ns from within a
0bd0: 20 73 69 6e 67 6c 65 20 70 72 6f 63 65 73 73 20   single process 
0be0: 74 68 61 74 20 75 73 65 20 74 68 69 73 0a 2a 2a  that use this.**
0bf0: 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20   implementation 
0c00: 6f 66 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20  of asynchronous 
0c10: 49 4f 20 6d 61 79 20 61 63 63 65 73 73 20 61 20  IO may access a 
0c20: 73 69 6e 67 6c 65 20 64 61 74 61 62 61 73 65 0a  single database.
0c30: 2a 2a 20 66 69 6c 65 20 63 6f 6e 63 75 72 72 65  ** file concurre
0c40: 6e 74 6c 79 2e 20 46 72 6f 6d 20 74 68 65 20 70  ntly. From the p
0c50: 6f 69 6e 74 20 6f 66 20 76 69 65 77 20 6f 66 20  oint of view of 
0c60: 74 68 65 20 75 73 65 72 2c 20 69 66 20 61 6c 6c  the user, if all
0c70: 0a 2a 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20  .** connections 
0c80: 61 72 65 20 66 72 6f 6d 20 77 69 74 68 69 6e 20  are from within 
0c90: 61 20 73 69 6e 67 6c 65 20 70 72 6f 63 65 73 73  a single process
0ca0: 2c 20 74 68 65 72 65 20 69 73 20 6e 6f 20 64 69  , there is no di
0cb0: 66 66 65 72 65 6e 63 65 0a 2a 2a 20 62 65 74 77  fference.** betw
0cc0: 65 65 6e 20 74 68 65 20 63 6f 6e 63 75 72 72 65  een the concurre
0cd0: 6e 63 79 20 6f 66 66 65 72 65 64 20 62 79 20 22  ncy offered by "
0ce0: 6e 6f 72 6d 61 6c 22 20 53 51 4c 69 74 65 20 61  normal" SQLite a
0cf0: 6e 64 20 53 51 4c 69 74 65 0a 2a 2a 20 75 73 69  nd SQLite.** usi
0d00: 6e 67 20 74 68 65 20 61 73 79 6e 63 68 72 6f 6e  ng the asynchron
0d10: 6f 75 73 20 62 61 63 6b 65 6e 64 2e 0a 2a 2a 0a  ous backend..**.
0d20: 2a 2a 20 49 66 20 63 6f 6e 6e 65 63 74 69 6f 6e  ** If connection
0d30: 73 20 66 72 6f 6d 20 77 69 74 68 69 6e 20 6d 75  s from within mu
0d40: 6c 74 69 70 6c 65 20 64 61 74 61 62 61 73 65 20  ltiple database 
0d50: 66 69 6c 65 73 20 6d 61 79 20 61 63 63 65 73 73  files may access
0d60: 20 74 68 65 0a 2a 2a 20 64 61 74 61 62 61 73 65   the.** database
0d70: 20 66 69 6c 65 2c 20 74 68 65 20 45 4e 41 42 4c   file, the ENABL
0d80: 45 5f 46 49 4c 45 5f 4c 4f 43 4b 49 4e 47 20 73  E_FILE_LOCKING s
0d90: 79 6d 62 6f 6c 20 28 73 65 65 20 62 65 6c 6f 77  ymbol (see below
0da0: 29 20 6d 75 73 74 20 62 65 0a 2a 2a 20 64 65 66  ) must be.** def
0db0: 69 6e 65 64 2e 20 49 66 20 69 74 20 69 73 20 6e  ined. If it is n
0dc0: 6f 74 20 64 65 66 69 6e 65 64 2c 20 74 68 65 6e  ot defined, then
0dd0: 20 6e 6f 20 6c 6f 63 6b 73 20 61 72 65 20 65 73   no locks are es
0de0: 74 61 62 6c 69 73 68 65 64 20 6f 6e 20 0a 2a 2a  tablished on .**
0df0: 20 74 68 65 20 64 61 74 61 62 61 73 65 20 66 69   the database fi
0e00: 6c 65 2e 20 49 6e 20 74 68 69 73 20 63 61 73 65  le. In this case
0e10: 2c 20 69 66 20 6d 75 6c 74 69 70 6c 65 20 70 72  , if multiple pr
0e20: 6f 63 65 73 73 65 73 20 61 63 63 65 73 73 20 0a  ocesses access .
0e30: 2a 2a 20 74 68 65 20 64 61 74 61 62 61 73 65 20  ** the database 
0e40: 66 69 6c 65 2c 20 63 6f 72 72 75 70 74 69 6f 6e  file, corruption
0e50: 20 77 69 6c 6c 20 71 75 69 63 6b 6c 79 20 72 65   will quickly re
0e60: 73 75 6c 74 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 45  sult..**.** If E
0e70: 4e 41 42 4c 45 5f 46 49 4c 45 5f 4c 4f 43 4b 49  NABLE_FILE_LOCKI
0e80: 4e 47 20 69 73 20 64 65 66 69 6e 65 64 20 28 74  NG is defined (t
0e90: 68 65 20 64 65 66 61 75 6c 74 29 2c 20 74 68 65  he default), the
0ea0: 6e 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 0a 2a  n connections .*
0eb0: 2a 20 66 72 6f 6d 20 77 69 74 68 69 6e 20 6d 75  * from within mu
0ec0: 6c 74 69 70 6c 65 20 70 72 6f 63 65 73 73 65 73  ltiple processes
0ed0: 20 6d 61 79 20 61 63 63 65 73 73 20 61 20 73 69   may access a si
0ee0: 6e 67 6c 65 20 64 61 74 61 62 61 73 65 20 66 69  ngle database fi
0ef0: 6c 65 20 0a 2a 2a 20 77 69 74 68 6f 75 74 20 72  le .** without r
0f00: 69 73 6b 69 6e 67 20 63 6f 72 72 75 70 74 69 6f  isking corruptio
0f10: 6e 2e 20 48 6f 77 65 76 65 72 20 63 6f 6e 63 75  n. However concu
0f20: 72 72 65 6e 63 79 20 69 73 20 72 65 64 75 63 65  rrency is reduce
0f30: 64 20 61 73 0a 2a 2a 20 66 6f 6c 6c 6f 77 73 3a  d as.** follows:
0f40: 0a 2a 2a 0a 2a 2a 20 20 20 2a 20 57 68 65 6e 20  .**.**   * When 
0f50: 61 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 75 73 69  a connection usi
0f60: 6e 67 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20  ng asynchronous 
0f70: 49 4f 20 62 65 67 69 6e 73 20 61 20 64 61 74 61  IO begins a data
0f80: 62 61 73 65 0a 2a 2a 20 20 20 20 20 74 72 61 6e  base.**     tran
0f90: 73 61 63 74 69 6f 6e 2c 20 74 68 65 20 64 61 74  saction, the dat
0fa0: 61 62 61 73 65 20 69 73 20 6c 6f 63 6b 65 64 20  abase is locked 
0fb0: 69 6d 6d 65 64 69 61 74 65 6c 79 2e 20 48 6f 77  immediately. How
0fc0: 65 76 65 72 20 74 68 65 0a 2a 2a 20 20 20 20 20  ever the.**     
0fd0: 6c 6f 63 6b 20 69 73 20 6e 6f 74 20 72 65 6c 65  lock is not rele
0fe0: 61 73 65 64 20 75 6e 74 69 6c 20 61 66 74 65 72  ased until after
0ff0: 20 61 6c 6c 20 72 65 6c 65 76 61 6e 74 20 6f 70   all relevant op
1000: 65 72 61 74 69 6f 6e 73 0a 2a 2a 20 20 20 20 20  erations.**     
1010: 69 6e 20 74 68 65 20 77 72 69 74 65 2d 71 75 65  in the write-que
1020: 75 65 20 68 61 76 65 20 62 65 65 6e 20 66 6c 75  ue have been flu
1030: 73 68 65 64 20 74 6f 20 64 69 73 6b 2e 20 54 68  shed to disk. Th
1040: 69 73 20 6d 65 61 6e 73 0a 2a 2a 20 20 20 20 20  is means.**     
1050: 28 66 6f 72 20 65 78 61 6d 70 6c 65 29 20 74 68  (for example) th
1060: 61 74 20 74 68 65 20 64 61 74 61 62 61 73 65 20  at the database 
1070: 6d 61 79 20 72 65 6d 61 69 6e 20 6c 6f 63 6b 65  may remain locke
1080: 64 20 66 6f 72 20 73 6f 6d 65 20 0a 2a 2a 20 20  d for some .**  
1090: 20 20 20 74 69 6d 65 20 61 66 74 65 72 20 61 20     time after a 
10a0: 22 43 4f 4d 4d 49 54 22 20 6f 72 20 22 52 4f 4c  "COMMIT" or "ROL
10b0: 4c 42 41 43 4b 22 20 69 73 20 69 73 73 75 65 64  LBACK" is issued
10c0: 2e 0a 2a 2a 0a 2a 2a 20 20 20 2a 20 49 66 20 61  ..**.**   * If a
10d0: 6e 20 61 70 70 6c 69 63 61 74 69 6f 6e 20 75 73  n application us
10e0: 69 6e 67 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73  ing asynchronous
10f0: 20 49 4f 20 65 78 65 63 75 74 65 73 20 74 72 61   IO executes tra
1100: 6e 73 61 63 74 69 6f 6e 73 0a 2a 2a 20 20 20 20  nsactions.**    
1110: 20 69 6e 20 71 75 69 63 6b 20 73 75 63 63 65 73   in quick succes
1120: 73 69 6f 6e 2c 20 6f 74 68 65 72 20 64 61 74 61  sion, other data
1130: 62 61 73 65 20 75 73 65 72 73 20 6d 61 79 20 62  base users may b
1140: 65 20 65 66 66 65 63 74 69 76 65 6c 79 0a 2a 2a  e effectively.**
1150: 20 20 20 20 20 6c 6f 63 6b 65 64 20 6f 75 74 20       locked out 
1160: 6f 66 20 74 68 65 20 64 61 74 61 62 61 73 65 2e  of the database.
1170: 20 54 68 69 73 20 69 73 20 62 65 63 61 75 73 65   This is because
1180: 20 77 68 65 6e 20 61 20 42 45 47 49 4e 0a 2a 2a   when a BEGIN.**
1190: 20 20 20 20 20 69 73 20 65 78 65 63 75 74 65 64       is executed
11a0: 2c 20 61 20 64 61 74 61 62 61 73 65 20 6c 6f 63  , a database loc
11b0: 6b 20 69 73 20 65 73 74 61 62 6c 69 73 68 65 64  k is established
11c0: 20 69 6d 6d 65 64 69 61 74 65 6c 79 2e 20 42 75   immediately. Bu
11d0: 74 0a 2a 2a 20 20 20 20 20 77 68 65 6e 20 74 68  t.**     when th
11e0: 65 20 63 6f 72 72 65 73 70 6f 6e 64 69 6e 67 20  e corresponding 
11f0: 43 4f 4d 4d 49 54 20 6f 72 20 52 4f 4c 4c 42 41  COMMIT or ROLLBA
1200: 43 4b 20 6f 63 63 75 72 73 2c 20 74 68 65 20 6c  CK occurs, the l
1210: 6f 63 6b 0a 2a 2a 20 20 20 20 20 69 73 20 6e 6f  ock.**     is no
1220: 74 20 72 65 6c 65 61 73 65 64 20 75 6e 74 69 6c  t released until
1230: 20 74 68 65 20 72 65 6c 65 76 61 6e 74 20 70 61   the relevant pa
1240: 72 74 20 6f 66 20 74 68 65 20 77 72 69 74 65 2d  rt of the write-
1250: 71 75 65 75 65 20 0a 2a 2a 20 20 20 20 20 68 61  queue .**     ha
1260: 73 20 62 65 65 6e 20 66 6c 75 73 68 65 64 20 74  s been flushed t
1270: 68 72 6f 75 67 68 2e 20 41 73 20 61 20 72 65 73  hrough. As a res
1280: 75 6c 74 2c 20 69 66 20 61 20 43 4f 4d 4d 49 54  ult, if a COMMIT
1290: 20 69 73 20 66 6f 6c 6c 6f 77 65 64 0a 2a 2a 20   is followed.** 
12a0: 20 20 20 20 62 79 20 61 20 42 45 47 49 4e 20 62      by a BEGIN b
12b0: 65 66 6f 72 65 20 74 68 65 20 77 72 69 74 65 2d  efore the write-
12c0: 71 75 65 75 65 20 69 73 20 66 6c 75 73 68 65 64  queue is flushed
12d0: 20 74 68 72 6f 75 67 68 2c 20 74 68 65 20 64 61   through, the da
12e0: 74 61 62 61 73 65 20 0a 2a 2a 20 20 20 20 20 69  tabase .**     i
12f0: 73 20 6e 65 76 65 72 20 75 6e 6c 6f 63 6b 65 64  s never unlocked
1300: 2c 70 72 65 76 65 6e 74 69 6e 67 20 6f 74 68 65  ,preventing othe
1310: 72 20 70 72 6f 63 65 73 73 65 73 20 66 72 6f 6d  r processes from
1320: 20 61 63 63 65 73 73 69 6e 67 20 0a 2a 2a 20 20   accessing .**  
1330: 20 20 20 74 68 65 20 64 61 74 61 62 61 73 65 2e     the database.
1340: 0a 2a 2a 0a 2a 2a 20 44 65 66 69 6e 69 6e 67 20  .**.** Defining 
1350: 45 4e 41 42 4c 45 5f 46 49 4c 45 5f 4c 4f 43 4b  ENABLE_FILE_LOCK
1360: 49 4e 47 20 77 68 65 6e 20 75 73 69 6e 67 20 61  ING when using a
1370: 6e 20 4e 46 53 20 6f 72 20 6f 74 68 65 72 20 72  n NFS or other r
1380: 65 6d 6f 74 65 20 0a 2a 2a 20 66 69 6c 65 2d 73  emote .** file-s
1390: 79 73 74 65 6d 20 6d 61 79 20 73 6c 6f 77 20 74  ystem may slow t
13a0: 68 69 6e 67 73 20 64 6f 77 6e 2c 20 61 73 20 73  hings down, as s
13b0: 79 6e 63 68 72 6f 6e 6f 75 73 20 72 6f 75 6e 64  ynchronous round
13c0: 2d 74 72 69 70 73 20 74 6f 20 74 68 65 20 0a 2a  -trips to the .*
13d0: 2a 20 73 65 72 76 65 72 20 6d 61 79 20 62 65 20  * server may be 
13e0: 72 65 71 75 69 72 65 64 20 74 6f 20 65 73 74 61  required to esta
13f0: 62 6c 69 73 68 20 64 61 74 61 62 61 73 65 20 66  blish database f
1400: 69 6c 65 20 6c 6f 63 6b 73 2e 0a 2a 2f 0a 23 64  ile locks..*/.#d
1410: 65 66 69 6e 65 20 45 4e 41 42 4c 45 5f 46 49 4c  efine ENABLE_FIL
1420: 45 5f 4c 4f 43 4b 49 4e 47 0a 0a 23 69 66 6e 64  E_LOCKING..#ifnd
1430: 65 66 20 53 51 4c 49 54 45 5f 41 4d 41 4c 47 41  ef SQLITE_AMALGA
1440: 4d 41 54 49 4f 4e 0a 23 20 69 6e 63 6c 75 64 65  MATION.# include
1450: 20 22 73 71 6c 69 74 65 49 6e 74 2e 68 22 0a 23   "sqliteInt.h".#
1460: 65 6e 64 69 66 0a 23 69 6e 63 6c 75 64 65 20 3c  endif.#include <
1470: 74 63 6c 2e 68 3e 0a 0a 2f 2a 0a 2a 2a 20 54 68  tcl.h>../*.** Th
1480: 69 73 20 74 65 73 74 20 75 73 65 73 20 70 74 68  is test uses pth
1490: 72 65 61 64 73 20 61 6e 64 20 68 65 6e 63 65 20  reads and hence 
14a0: 6f 6e 6c 79 20 77 6f 72 6b 73 20 6f 6e 20 75 6e  only works on un
14b0: 69 78 20 61 6e 64 20 77 69 74 68 0a 2a 2a 20 61  ix and with.** a
14c0: 20 74 68 72 65 61 64 73 61 66 65 20 62 75 69 6c   threadsafe buil
14d0: 64 20 6f 66 20 53 51 4c 69 74 65 2e 0a 2a 2f 0a  d of SQLite..*/.
14e0: 23 69 66 20 4f 53 5f 55 4e 49 58 20 26 26 20 53  #if OS_UNIX && S
14f0: 51 4c 49 54 45 5f 54 48 52 45 41 44 53 41 46 45  QLITE_THREADSAFE
1500: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 64 65 6d  ../*.** This dem
1510: 6f 20 75 73 65 73 20 70 74 68 72 65 61 64 73 2e  o uses pthreads.
1520: 20 20 49 66 20 79 6f 75 20 64 6f 20 6e 6f 74 20    If you do not 
1530: 68 61 76 65 20 61 20 70 74 68 72 65 61 64 73 20  have a pthreads 
1540: 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 0a 2a  implementation.*
1550: 2a 20 66 6f 72 20 79 6f 75 72 20 6f 70 65 72 61  * for your opera
1560: 74 69 6e 67 20 73 79 73 74 65 6d 2c 20 79 6f 75  ting system, you
1570: 20 77 69 6c 6c 20 6e 65 65 64 20 74 6f 20 72 65   will need to re
1580: 63 6f 64 65 20 74 68 65 20 74 68 72 65 61 64 69  code the threadi
1590: 6e 67 20 0a 2a 2a 20 6c 6f 67 69 63 2e 0a 2a 2f  ng .** logic..*/
15a0: 0a 23 69 6e 63 6c 75 64 65 20 3c 70 74 68 72 65  .#include <pthre
15b0: 61 64 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c  ad.h>.#include <
15c0: 73 63 68 65 64 2e 68 3e 0a 0a 2f 2a 20 55 73 65  sched.h>../* Use
15d0: 66 75 6c 20 6d 61 63 72 6f 73 20 75 73 65 64 20  ful macros used 
15e0: 69 6e 20 73 65 76 65 72 61 6c 20 70 6c 61 63 65  in several place
15f0: 73 20 2a 2f 0a 23 64 65 66 69 6e 65 20 4d 49 4e  s */.#define MIN
1600: 28 78 2c 79 29 20 28 28 78 29 3c 28 79 29 3f 28  (x,y) ((x)<(y)?(
1610: 78 29 3a 28 79 29 29 0a 23 64 65 66 69 6e 65 20  x):(y)).#define 
1620: 4d 41 58 28 78 2c 79 29 20 28 28 78 29 3e 28 79  MAX(x,y) ((x)>(y
1630: 29 3f 28 78 29 3a 28 79 29 29 0a 0a 2f 2a 20 46  )?(x):(y))../* F
1640: 6f 72 77 61 72 64 20 72 65 66 65 72 65 6e 63 65  orward reference
1650: 73 20 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72  s */.typedef str
1660: 75 63 74 20 41 73 79 6e 63 57 72 69 74 65 20 41  uct AsyncWrite A
1670: 73 79 6e 63 57 72 69 74 65 3b 0a 74 79 70 65 64  syncWrite;.typed
1680: 65 66 20 73 74 72 75 63 74 20 41 73 79 6e 63 46  ef struct AsyncF
1690: 69 6c 65 20 41 73 79 6e 63 46 69 6c 65 3b 0a 74  ile AsyncFile;.t
16a0: 79 70 65 64 65 66 20 73 74 72 75 63 74 20 41 73  ypedef struct As
16b0: 79 6e 63 46 69 6c 65 44 61 74 61 20 41 73 79 6e  yncFileData Asyn
16c0: 63 46 69 6c 65 44 61 74 61 3b 0a 74 79 70 65 64  cFileData;.typed
16d0: 65 66 20 73 74 72 75 63 74 20 41 73 79 6e 63 46  ef struct AsyncF
16e0: 69 6c 65 4c 6f 63 6b 20 41 73 79 6e 63 46 69 6c  ileLock AsyncFil
16f0: 65 4c 6f 63 6b 3b 0a 74 79 70 65 64 65 66 20 73  eLock;.typedef s
1700: 74 72 75 63 74 20 41 73 79 6e 63 4c 6f 63 6b 20  truct AsyncLock 
1710: 41 73 79 6e 63 4c 6f 63 6b 3b 0a 0a 2f 2a 20 45  AsyncLock;../* E
1720: 6e 61 62 6c 65 20 66 6f 72 20 64 65 62 75 67 67  nable for debugg
1730: 69 6e 67 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ing */.static in
1740: 74 20 73 71 6c 69 74 65 33 61 73 79 6e 63 5f 74  t sqlite3async_t
1750: 72 61 63 65 20 3d 20 30 3b 0a 23 20 64 65 66 69  race = 0;.# defi
1760: 6e 65 20 41 53 59 4e 43 5f 54 52 41 43 45 28 58  ne ASYNC_TRACE(X
1770: 29 20 69 66 28 20 73 71 6c 69 74 65 33 61 73 79  ) if( sqlite3asy
1780: 6e 63 5f 74 72 61 63 65 20 29 20 61 73 79 6e 63  nc_trace ) async
1790: 54 72 61 63 65 20 58 0a 73 74 61 74 69 63 20 76  Trace X.static v
17a0: 6f 69 64 20 61 73 79 6e 63 54 72 61 63 65 28 63  oid asyncTrace(c
17b0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 46 6f 72 6d  onst char *zForm
17c0: 61 74 2c 20 2e 2e 2e 29 7b 0a 20 20 63 68 61 72  at, ...){.  char
17d0: 20 2a 7a 3b 0a 20 20 76 61 5f 6c 69 73 74 20 61   *z;.  va_list a
17e0: 70 3b 0a 20 20 76 61 5f 73 74 61 72 74 28 61 70  p;.  va_start(ap
17f0: 2c 20 7a 46 6f 72 6d 61 74 29 3b 0a 20 20 7a 20  , zFormat);.  z 
1800: 3d 20 73 71 6c 69 74 65 33 5f 76 6d 70 72 69 6e  = sqlite3_vmprin
1810: 74 66 28 7a 46 6f 72 6d 61 74 2c 20 61 70 29 3b  tf(zFormat, ap);
1820: 0a 20 20 76 61 5f 65 6e 64 28 61 70 29 3b 0a 20  .  va_end(ap);. 
1830: 20 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c   fprintf(stderr,
1840: 20 22 5b 25 64 5d 20 25 73 22 2c 20 28 69 6e 74   "[%d] %s", (int
1850: 29 70 74 68 72 65 61 64 5f 73 65 6c 66 28 29 2c  )pthread_self(),
1860: 20 7a 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   z);.  sqlite3_f
1870: 72 65 65 28 7a 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ree(z);.}../*.**
1880: 20 54 48 52 45 41 44 20 53 41 46 45 54 59 20 4e   THREAD SAFETY N
1890: 4f 54 45 53 0a 2a 2a 0a 2a 2a 20 42 61 73 69 63  OTES.**.** Basic
18a0: 20 72 75 6c 65 73 3a 0a 2a 2a 0a 2a 2a 20 20 20   rules:.**.**   
18b0: 20 20 2a 20 42 6f 74 68 20 72 65 61 64 20 61 6e    * Both read an
18c0: 64 20 77 72 69 74 65 20 61 63 63 65 73 73 20 74  d write access t
18d0: 6f 20 74 68 65 20 67 6c 6f 62 61 6c 20 77 72 69  o the global wri
18e0: 74 65 2d 6f 70 20 71 75 65 75 65 20 6d 75 73 74  te-op queue must
18f0: 20 62 65 20 0a 2a 2a 20 20 20 20 20 20 20 70 72   be .**       pr
1900: 6f 74 65 63 74 65 64 20 62 79 20 74 68 65 20 61  otected by the a
1910: 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 2e  sync.queueMutex.
1920: 20 41 73 20 61 72 65 20 74 68 65 20 61 73 79 6e   As are the asyn
1930: 63 2e 69 6f 45 72 72 6f 72 20 61 6e 64 0a 2a 2a  c.ioError and.**
1940: 20 20 20 20 20 20 20 61 73 79 6e 63 2e 6e 46 69         async.nFi
1950: 6c 65 20 76 61 72 69 61 62 6c 65 73 2e 0a 2a 2a  le variables..**
1960: 0a 2a 2a 20 20 20 20 20 2a 20 54 68 65 20 61 73  .**     * The as
1970: 79 6e 63 2e 61 4c 6f 63 6b 20 68 61 73 68 2d 74  ync.aLock hash-t
1980: 61 62 6c 65 20 61 6e 64 20 61 6c 6c 20 41 73 79  able and all Asy
1990: 6e 63 4c 6f 63 6b 20 61 6e 64 20 41 73 79 6e 63  ncLock and Async
19a0: 46 69 6c 65 4c 6f 63 6b 0a 2a 2a 20 20 20 20 20  FileLock.**     
19b0: 20 20 73 74 72 75 63 74 75 72 65 73 20 6d 75 73    structures mus
19c0: 74 20 62 65 20 70 72 6f 74 65 63 74 65 64 20 62  t be protected b
19d0: 79 20 74 68 65 20 61 73 79 6e 63 2e 6c 6f 63 6b  y the async.lock
19e0: 4d 75 74 65 78 20 6d 75 74 65 78 2e 0a 2a 2a 0a  Mutex mutex..**.
19f0: 2a 2a 20 20 20 20 20 2a 20 54 68 65 20 66 69 6c  **     * The fil
1a00: 65 20 68 61 6e 64 6c 65 73 20 66 72 6f 6d 20 74  e handles from t
1a10: 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 73 79  he underlying sy
1a20: 73 74 65 6d 20 61 72 65 20 61 73 73 75 6d 65 64  stem are assumed
1a30: 20 6e 6f 74 20 74 6f 20 0a 2a 2a 20 20 20 20 20   not to .**     
1a40: 20 20 62 65 20 74 68 72 65 61 64 20 73 61 66 65    be thread safe
1a50: 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 20 2a 20 53 65  ..**.**     * Se
1a60: 65 20 74 68 65 20 6c 61 73 74 20 74 77 6f 20 70  e the last two p
1a70: 61 72 61 67 72 61 70 68 73 20 75 6e 64 65 72 20  aragraphs under 
1a80: 22 54 68 65 20 57 72 69 74 65 72 20 54 68 72 65  "The Writer Thre
1a90: 61 64 22 20 66 6f 72 0a 2a 2a 20 20 20 20 20 20  ad" for.**      
1aa0: 20 61 6e 20 61 73 73 75 6d 70 74 69 6f 6e 20 74   an assumption t
1ab0: 6f 20 64 6f 20 77 69 74 68 20 66 69 6c 65 2d 68  o do with file-h
1ac0: 61 6e 64 6c 65 20 73 79 6e 63 68 72 6f 6e 69 7a  andle synchroniz
1ad0: 61 74 69 6f 6e 20 62 79 20 74 68 65 20 4f 73 2e  ation by the Os.
1ae0: 0a 2a 2a 0a 2a 2a 20 44 65 61 64 6c 6f 63 6b 20  .**.** Deadlock 
1af0: 70 72 65 76 65 6e 74 69 6f 6e 3a 0a 2a 2a 0a 2a  prevention:.**.*
1b00: 2a 20 20 20 20 20 54 68 65 72 65 20 61 72 65 20  *     There are 
1b10: 74 68 72 65 65 20 6d 75 74 65 78 20 75 73 65 64  three mutex used
1b20: 20 62 79 20 74 68 65 20 73 79 73 74 65 6d 3a 20   by the system: 
1b30: 74 68 65 20 22 77 72 69 74 65 72 22 20 6d 75 74  the "writer" mut
1b40: 65 78 2c 20 0a 2a 2a 20 20 20 20 20 74 68 65 20  ex, .**     the 
1b50: 22 71 75 65 75 65 22 20 6d 75 74 65 78 20 61 6e  "queue" mutex an
1b60: 64 20 74 68 65 20 22 6c 6f 63 6b 22 20 6d 75 74  d the "lock" mut
1b70: 65 78 2e 20 52 75 6c 65 73 20 61 72 65 3a 0a 2a  ex. Rules are:.*
1b80: 2a 0a 2a 2a 20 20 20 20 20 2a 20 49 74 20 69 73  *.**     * It is
1b90: 20 69 6c 6c 65 67 61 6c 20 74 6f 20 62 6c 6f 63   illegal to bloc
1ba0: 6b 20 6f 6e 20 74 68 65 20 77 72 69 74 65 72 20  k on the writer 
1bb0: 6d 75 74 65 78 20 77 68 65 6e 20 61 6e 79 20 6f  mutex when any o
1bc0: 74 68 65 72 20 6d 75 74 65 78 0a 2a 2a 20 20 20  ther mutex.**   
1bd0: 20 20 20 20 61 72 65 20 68 65 6c 64 2c 20 61 6e      are held, an
1be0: 64 20 0a 2a 2a 0a 2a 2a 20 20 20 20 20 2a 20 49  d .**.**     * I
1bf0: 74 20 69 73 20 69 6c 6c 65 67 61 6c 20 74 6f 20  t is illegal to 
1c00: 62 6c 6f 63 6b 20 6f 6e 20 74 68 65 20 71 75 65  block on the que
1c10: 75 65 20 6d 75 74 65 78 20 77 68 65 6e 20 74 68  ue mutex when th
1c20: 65 20 6c 6f 63 6b 20 6d 75 74 65 78 0a 2a 2a 20  e lock mutex.** 
1c30: 20 20 20 20 20 20 69 73 20 68 65 6c 64 2e 0a 2a        is held..*
1c40: 2a 0a 2a 2a 20 20 20 20 20 69 2e 65 2e 20 6d 75  *.**     i.e. mu
1c50: 74 65 78 27 73 20 6d 75 73 74 20 62 65 20 67 72  tex's must be gr
1c60: 61 62 62 65 64 20 69 6e 20 74 68 65 20 6f 72 64  abbed in the ord
1c70: 65 72 20 22 77 72 69 74 65 72 22 2c 20 22 71 75  er "writer", "qu
1c80: 65 75 65 22 2c 20 22 6c 6f 63 6b 22 2e 0a 2a 2a  eue", "lock"..**
1c90: 0a 2a 2a 20 46 69 6c 65 20 73 79 73 74 65 6d 20  .** File system 
1ca0: 6f 70 65 72 61 74 69 6f 6e 73 20 28 69 6e 76 6f  operations (invo
1cb0: 6b 65 64 20 62 79 20 53 51 4c 69 74 65 20 74 68  ked by SQLite th
1cc0: 72 65 61 64 29 3a 0a 2a 2a 0a 2a 2a 20 20 20 20  read):.**.**    
1cd0: 20 78 4f 70 65 6e 0a 2a 2a 20 20 20 20 20 78 44   xOpen.**     xD
1ce0: 65 6c 65 74 65 0a 2a 2a 20 20 20 20 20 78 46 69  elete.**     xFi
1cf0: 6c 65 45 78 69 73 74 73 0a 2a 2a 0a 2a 2a 20 46  leExists.**.** F
1d00: 69 6c 65 20 68 61 6e 64 6c 65 20 6f 70 65 72 61  ile handle opera
1d10: 74 69 6f 6e 73 20 28 69 6e 76 6f 6b 65 64 20 62  tions (invoked b
1d20: 79 20 53 51 4c 69 74 65 20 74 68 72 65 61 64 29  y SQLite thread)
1d30: 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20 20 20 20 20  :.**.**         
1d40: 61 73 79 6e 63 57 72 69 74 65 2c 20 61 73 79 6e  asyncWrite, asyn
1d50: 63 43 6c 6f 73 65 2c 20 61 73 79 6e 63 54 72 75  cClose, asyncTru
1d60: 6e 63 61 74 65 2c 20 61 73 79 6e 63 53 79 6e 63  ncate, asyncSync
1d70: 20 0a 2a 2a 20 20 20 20 0a 2a 2a 20 20 20 20 20   .**    .**     
1d80: 54 68 65 20 6f 70 65 72 61 74 69 6f 6e 73 20 61  The operations a
1d90: 62 6f 76 65 20 61 64 64 20 61 6e 20 65 6e 74 72  bove add an entr
1da0: 79 20 74 6f 20 74 68 65 20 67 6c 6f 62 61 6c 20  y to the global 
1db0: 77 72 69 74 65 2d 6f 70 20 6c 69 73 74 2e 20 54  write-op list. T
1dc0: 68 65 79 0a 2a 2a 20 20 20 20 20 70 72 65 70 61  hey.**     prepa
1dd0: 72 65 20 74 68 65 20 65 6e 74 72 79 2c 20 61 63  re the entry, ac
1de0: 71 75 69 72 65 20 74 68 65 20 61 73 79 6e 63 2e  quire the async.
1df0: 71 75 65 75 65 4d 75 74 65 78 20 6d 6f 6d 65 6e  queueMutex momen
1e00: 74 61 72 69 6c 79 20 77 68 69 6c 65 0a 2a 2a 20  tarily while.** 
1e10: 20 20 20 20 6c 69 73 74 20 70 6f 69 6e 74 65 72      list pointer
1e20: 73 20 61 72 65 20 20 6d 61 6e 69 70 75 6c 61 74  s are  manipulat
1e30: 65 64 20 74 6f 20 69 6e 73 65 72 74 20 74 68 65  ed to insert the
1e40: 20 6e 65 77 20 65 6e 74 72 79 2c 20 74 68 65 6e   new entry, then
1e50: 20 72 65 6c 65 61 73 65 0a 2a 2a 20 20 20 20 20   release.**     
1e60: 74 68 65 20 6d 75 74 65 78 20 61 6e 64 20 73 69  the mutex and si
1e70: 67 6e 61 6c 20 74 68 65 20 77 72 69 74 65 72 20  gnal the writer 
1e80: 74 68 72 65 61 64 20 74 6f 20 77 61 6b 65 20 75  thread to wake u
1e90: 70 20 69 6e 20 63 61 73 65 20 69 74 20 68 61 70  p in case it hap
1ea0: 70 65 6e 73 0a 2a 2a 20 20 20 20 20 74 6f 20 62  pens.**     to b
1eb0: 65 20 61 73 6c 65 65 70 2e 0a 2a 2a 0a 2a 2a 20  e asleep..**.** 
1ec0: 20 20 20 0a 2a 2a 20 20 20 20 20 20 20 20 20 61     .**         a
1ed0: 73 79 6e 63 52 65 61 64 2c 20 61 73 79 6e 63 46  syncRead, asyncF
1ee0: 69 6c 65 53 69 7a 65 2e 0a 2a 2a 0a 2a 2a 20 20  ileSize..**.**  
1ef0: 20 20 20 52 65 61 64 20 6f 70 65 72 61 74 69 6f     Read operatio
1f00: 6e 73 2e 20 42 6f 74 68 20 6f 66 20 74 68 65 73  ns. Both of thes
1f10: 65 20 72 65 61 64 20 66 72 6f 6d 20 62 6f 74 68  e read from both
1f20: 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20   the underlying 
1f30: 66 69 6c 65 0a 2a 2a 20 20 20 20 20 66 69 72 73  file.**     firs
1f40: 74 20 74 68 65 6e 20 61 64 6a 75 73 74 20 74 68  t then adjust th
1f50: 65 69 72 20 72 65 73 75 6c 74 20 62 61 73 65 64  eir result based
1f60: 20 6f 6e 20 70 65 6e 64 69 6e 67 20 77 72 69 74   on pending writ
1f70: 65 73 20 69 6e 20 74 68 65 20 0a 2a 2a 20 20 20  es in the .**   
1f80: 20 20 77 72 69 74 65 2d 6f 70 20 71 75 65 75 65    write-op queue
1f90: 2e 20 20 20 53 6f 20 61 73 79 6e 63 2e 71 75 65  .   So async.que
1fa0: 75 65 4d 75 74 65 78 20 69 73 20 68 65 6c 64 20  ueMutex is held 
1fb0: 66 6f 72 20 74 68 65 20 64 75 72 61 74 69 6f 6e  for the duration
1fc0: 0a 2a 2a 20 20 20 20 20 6f 66 20 74 68 65 73 65  .**     of these
1fd0: 20 6f 70 65 72 61 74 69 6f 6e 73 20 74 6f 20 70   operations to p
1fe0: 72 65 76 65 6e 74 20 6f 74 68 65 72 20 74 68 72  revent other thr
1ff0: 65 61 64 73 20 66 72 6f 6d 20 63 68 61 6e 67 69  eads from changi
2000: 6e 67 20 74 68 65 0a 2a 2a 20 20 20 20 20 71 75  ng the.**     qu
2010: 65 75 65 20 69 6e 20 6d 69 64 20 6f 70 65 72 61  eue in mid opera
2020: 74 69 6f 6e 2e 0a 2a 2a 20 20 20 20 0a 2a 2a 0a  tion..**    .**.
2030: 2a 2a 20 20 20 20 20 20 20 20 20 61 73 79 6e 63  **         async
2040: 4c 6f 63 6b 2c 20 61 73 79 6e 63 55 6e 6c 6f 63  Lock, asyncUnloc
2050: 6b 2c 20 61 73 79 6e 63 43 68 65 63 6b 52 65 73  k, asyncCheckRes
2060: 65 72 76 65 64 4c 6f 63 6b 0a 2a 2a 20 20 20 20  ervedLock.**    
2070: 0a 2a 2a 20 20 20 20 20 54 68 65 73 65 20 70 72  .**     These pr
2080: 69 6d 69 74 69 76 65 73 20 69 6d 70 6c 65 6d 65  imitives impleme
2090: 6e 74 20 69 6e 2d 70 72 6f 63 65 73 73 20 6c 6f  nt in-process lo
20a0: 63 6b 69 6e 67 20 75 73 69 6e 67 20 61 20 68 61  cking using a ha
20b0: 73 68 20 74 61 62 6c 65 0a 2a 2a 20 20 20 20 20  sh table.**     
20c0: 6f 6e 20 74 68 65 20 66 69 6c 65 20 6e 61 6d 65  on the file name
20d0: 2e 20 20 46 69 6c 65 73 20 61 72 65 20 6c 6f 63  .  Files are loc
20e0: 6b 65 64 20 63 6f 72 72 65 63 74 6c 79 20 66 6f  ked correctly fo
20f0: 72 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 63 6f  r connections co
2100: 6d 69 6e 67 0a 2a 2a 20 20 20 20 20 66 72 6f 6d  ming.**     from
2110: 20 74 68 65 20 73 61 6d 65 20 70 72 6f 63 65 73   the same proces
2120: 73 2e 20 20 42 75 74 20 6f 74 68 65 72 20 70 72  s.  But other pr
2130: 6f 63 65 73 73 65 73 20 63 61 6e 6e 6f 74 20 73  ocesses cannot s
2140: 65 65 20 74 68 65 73 65 20 6c 6f 63 6b 73 0a 2a  ee these locks.*
2150: 2a 20 20 20 20 20 61 6e 64 20 77 69 6c 6c 20 74  *     and will t
2160: 68 65 72 65 66 6f 72 65 20 6e 6f 74 20 68 6f 6e  herefore not hon
2170: 6f 72 20 74 68 65 6d 2e 0a 2a 2a 0a 2a 2a 0a 2a  or them..**.**.*
2180: 2a 20 54 68 65 20 77 72 69 74 65 72 20 74 68 72  * The writer thr
2190: 65 61 64 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20 54  ead:.**.**     T
21a0: 68 65 20 61 73 79 6e 63 2e 77 72 69 74 65 72 4d  he async.writerM
21b0: 75 74 65 78 20 69 73 20 75 73 65 64 20 74 6f 20  utex is used to 
21c0: 6d 61 6b 65 20 73 75 72 65 20 6f 6e 6c 79 20 74  make sure only t
21d0: 68 65 72 65 20 69 73 20 6f 6e 6c 79 0a 2a 2a 20  here is only.** 
21e0: 20 20 20 20 61 20 73 69 6e 67 6c 65 20 77 72 69      a single wri
21f0: 74 65 72 20 74 68 72 65 61 64 20 72 75 6e 6e 69  ter thread runni
2200: 6e 67 20 61 74 20 61 20 74 69 6d 65 2e 0a 2a 2a  ng at a time..**
2210: 0a 2a 2a 20 20 20 20 20 49 6e 73 69 64 65 20 74  .**     Inside t
2220: 68 65 20 77 72 69 74 65 72 20 74 68 72 65 61 64  he writer thread
2230: 20 69 73 20 61 20 6c 6f 6f 70 20 74 68 61 74 20   is a loop that 
2240: 77 6f 72 6b 73 20 6c 69 6b 65 20 74 68 69 73 3a  works like this:
2250: 0a 2a 2a 0a 2a 2a 20 20 20 20 20 20 20 20 20 57  .**.**         W
2260: 48 49 4c 45 20 28 77 72 69 74 65 2d 6f 70 20 6c  HILE (write-op l
2270: 69 73 74 20 69 73 20 6e 6f 74 20 65 6d 70 74 79  ist is not empty
2280: 29 0a 2a 2a 20 20 20 20 20 20 20 20 20 20 20 20  ).**            
2290: 20 44 6f 20 49 4f 20 6f 70 65 72 61 74 69 6f 6e   Do IO operation
22a0: 20 61 74 20 68 65 61 64 20 6f 66 20 77 72 69 74   at head of writ
22b0: 65 2d 6f 70 20 6c 69 73 74 0a 2a 2a 20 20 20 20  e-op list.**    
22c0: 20 20 20 20 20 20 20 20 20 52 65 6d 6f 76 65 20           Remove 
22d0: 65 6e 74 72 79 20 66 72 6f 6d 20 68 65 61 64 20  entry from head 
22e0: 6f 66 20 77 72 69 74 65 2d 6f 70 20 6c 69 73 74  of write-op list
22f0: 0a 2a 2a 20 20 20 20 20 20 20 20 20 45 4e 44 20  .**         END 
2300: 57 48 49 4c 45 0a 2a 2a 0a 2a 2a 20 20 20 20 20  WHILE.**.**     
2310: 54 68 65 20 61 73 79 6e 63 2e 71 75 65 75 65 4d  The async.queueM
2320: 75 74 65 78 20 69 73 20 61 6c 77 61 79 73 20 68  utex is always h
2330: 65 6c 64 20 64 75 72 69 6e 67 20 74 68 65 20 3c  eld during the <
2340: 77 72 69 74 65 2d 6f 70 20 6c 69 73 74 20 69 73  write-op list is
2350: 20 0a 2a 2a 20 20 20 20 20 6e 6f 74 20 65 6d 70   .**     not emp
2360: 74 79 3e 20 74 65 73 74 2c 20 61 6e 64 20 77 68  ty> test, and wh
2370: 65 6e 20 74 68 65 20 65 6e 74 72 79 20 69 73 20  en the entry is 
2380: 72 65 6d 6f 76 65 64 20 66 72 6f 6d 20 74 68 65  removed from the
2390: 20 68 65 61 64 0a 2a 2a 20 20 20 20 20 6f 66 20   head.**     of 
23a0: 74 68 65 20 77 72 69 74 65 2d 6f 70 20 6c 69 73  the write-op lis
23b0: 74 2e 20 53 6f 6d 65 74 69 6d 65 73 20 69 74 20  t. Sometimes it 
23c0: 69 73 20 68 65 6c 64 20 66 6f 72 20 74 68 65 20  is held for the 
23d0: 69 6e 74 65 72 69 6d 0a 2a 2a 20 20 20 20 20 70  interim.**     p
23e0: 65 72 69 6f 64 20 28 77 68 69 6c 65 20 74 68 65  eriod (while the
23f0: 20 49 4f 20 69 73 20 70 65 72 66 6f 72 6d 65 64   IO is performed
2400: 29 2c 20 61 6e 64 20 73 6f 6d 65 74 69 6d 65 73  ), and sometimes
2410: 20 69 74 20 69 73 0a 2a 2a 20 20 20 20 20 72 65   it is.**     re
2420: 6c 69 6e 71 75 69 73 68 65 64 2e 20 49 74 20 69  linquished. It i
2430: 73 20 72 65 6c 69 6e 71 75 69 73 68 65 64 20 69  s relinquished i
2440: 66 20 28 61 29 20 74 68 65 20 49 4f 20 6f 70 20  f (a) the IO op 
2450: 69 73 20 61 6e 0a 2a 2a 20 20 20 20 20 41 53 59  is an.**     ASY
2460: 4e 43 5f 43 4c 4f 53 45 20 6f 72 20 28 62 29 20  NC_CLOSE or (b) 
2470: 77 68 65 6e 20 74 68 65 20 66 69 6c 65 20 68 61  when the file ha
2480: 6e 64 6c 65 20 77 61 73 20 6f 70 65 6e 65 64 2c  ndle was opened,
2490: 20 74 77 6f 20 6f 66 0a 2a 2a 20 20 20 20 20 74   two of.**     t
24a0: 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 73 79  he underlying sy
24b0: 73 74 65 6d 73 20 68 61 6e 64 6c 65 73 20 77 65  stems handles we
24c0: 72 65 20 6f 70 65 6e 65 64 20 6f 6e 20 74 68 65  re opened on the
24d0: 20 73 61 6d 65 0a 2a 2a 20 20 20 20 20 66 69 6c   same.**     fil
24e0: 65 2d 73 79 73 74 65 6d 20 65 6e 74 72 79 2e 0a  e-system entry..
24f0: 2a 2a 0a 2a 2a 20 20 20 20 20 49 66 20 63 6f 6e  **.**     If con
2500: 64 69 74 69 6f 6e 20 28 62 29 20 61 62 6f 76 65  dition (b) above
2510: 20 69 73 20 74 72 75 65 2c 20 74 68 65 6e 20 6f   is true, then o
2520: 6e 65 20 66 69 6c 65 2d 68 61 6e 64 6c 65 20 0a  ne file-handle .
2530: 2a 2a 20 20 20 20 20 28 41 73 79 6e 63 46 69 6c  **     (AsyncFil
2540: 65 2e 70 42 61 73 65 52 65 61 64 29 20 69 73 20  e.pBaseRead) is 
2550: 75 73 65 64 20 65 78 63 6c 75 73 69 76 65 6c 79  used exclusively
2560: 20 62 79 20 73 71 6c 69 74 65 20 74 68 72 65 61   by sqlite threa
2570: 64 73 20 74 6f 20 72 65 61 64 20 74 68 65 0a 2a  ds to read the.*
2580: 2a 20 20 20 20 20 66 69 6c 65 2c 20 74 68 65 20  *     file, the 
2590: 6f 74 68 65 72 20 28 41 73 79 6e 63 46 69 6c 65  other (AsyncFile
25a0: 2e 70 42 61 73 65 57 72 69 74 65 29 20 62 79 20  .pBaseWrite) by 
25b0: 73 71 6c 69 74 65 33 5f 61 73 79 6e 63 5f 66 6c  sqlite3_async_fl
25c0: 75 73 68 28 29 20 0a 2a 2a 20 20 20 20 20 74 68  ush() .**     th
25d0: 72 65 61 64 73 20 74 6f 20 70 65 72 66 6f 72 6d  reads to perform
25e0: 20 77 72 69 74 65 28 29 20 6f 70 65 72 61 74 69   write() operati
25f0: 6f 6e 73 2e 20 54 68 69 73 20 6d 65 61 6e 73 20  ons. This means 
2600: 74 68 61 74 20 72 65 61 64 20 0a 2a 2a 20 20 20  that read .**   
2610: 20 20 6f 70 65 72 61 74 69 6f 6e 73 20 61 72 65    operations are
2620: 20 6e 6f 74 20 62 6c 6f 63 6b 65 64 20 62 79 20   not blocked by 
2630: 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20 77 72 69  asynchronous wri
2640: 74 65 73 20 28 61 6c 74 68 6f 75 67 68 20 0a 2a  tes (although .*
2650: 2a 20 20 20 20 20 61 73 79 6e 63 68 72 6f 6e 6f  *     asynchrono
2660: 75 73 20 77 72 69 74 65 73 20 6d 61 79 20 73 74  us writes may st
2670: 69 6c 6c 20 62 65 20 62 6c 6f 63 6b 65 64 20 62  ill be blocked b
2680: 79 20 72 65 61 64 73 29 2e 0a 2a 2a 0a 2a 2a 20  y reads)..**.** 
2690: 20 20 20 20 54 68 69 73 20 61 73 73 75 6d 65 73      This assumes
26a0: 20 74 68 61 74 20 74 68 65 20 4f 53 20 6b 65 65   that the OS kee
26b0: 70 73 20 74 77 6f 20 68 61 6e 64 6c 65 73 20 6f  ps two handles o
26c0: 70 65 6e 20 6f 6e 20 74 68 65 20 73 61 6d 65 20  pen on the same 
26d0: 66 69 6c 65 0a 2a 2a 20 20 20 20 20 70 72 6f 70  file.**     prop
26e0: 65 72 6c 79 20 69 6e 20 73 79 6e 63 2e 20 54 68  erly in sync. Th
26f0: 61 74 20 69 73 2c 20 61 6e 79 20 72 65 61 64 20  at is, any read 
2700: 6f 70 65 72 61 74 69 6f 6e 20 74 68 61 74 20 73  operation that s
2710: 74 61 72 74 73 20 61 66 74 65 72 20 61 0a 2a 2a  tarts after a.**
2720: 20 20 20 20 20 77 72 69 74 65 20 6f 70 65 72 61       write opera
2730: 74 69 6f 6e 20 6f 6e 20 74 68 65 20 73 61 6d 65  tion on the same
2740: 20 66 69 6c 65 20 73 79 73 74 65 6d 20 65 6e 74   file system ent
2750: 72 79 20 68 61 73 20 63 6f 6d 70 6c 65 74 65 64  ry has completed
2760: 20 72 65 74 75 72 6e 73 0a 2a 2a 20 20 20 20 20   returns.**     
2770: 64 61 74 61 20 63 6f 6e 73 69 73 74 65 6e 74 20  data consistent 
2780: 77 69 74 68 20 74 68 65 20 77 72 69 74 65 2e 20  with the write. 
2790: 57 65 20 61 6c 73 6f 20 61 73 73 75 6d 65 20 74  We also assume t
27a0: 68 61 74 20 69 66 20 6f 6e 65 20 74 68 72 65 61  hat if one threa
27b0: 64 20 0a 2a 2a 20 20 20 20 20 72 65 61 64 73 20  d .**     reads 
27c0: 61 20 66 69 6c 65 20 77 68 69 6c 65 20 61 6e 6f  a file while ano
27d0: 74 68 65 72 20 69 73 20 77 72 69 74 69 6e 67 20  ther is writing 
27e0: 69 74 20 61 6c 6c 20 62 79 74 65 73 20 6f 74 68  it all bytes oth
27f0: 65 72 20 74 68 61 6e 20 74 68 65 0a 2a 2a 20 20  er than the.**  
2800: 20 20 20 6f 6e 65 73 20 61 63 74 75 61 6c 6c 79     ones actually
2810: 20 62 65 69 6e 67 20 77 72 69 74 74 65 6e 20 63   being written c
2820: 6f 6e 74 61 69 6e 20 76 61 6c 69 64 20 64 61 74  ontain valid dat
2830: 61 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 20 49 66 20  a..**.**     If 
2840: 74 68 65 20 61 62 6f 76 65 20 61 73 73 75 6d 70  the above assump
2850: 74 69 6f 6e 73 20 61 72 65 20 6e 6f 74 20 74 72  tions are not tr
2860: 75 65 2c 20 73 65 74 20 74 68 65 20 70 72 65 70  ue, set the prep
2870: 72 6f 63 65 73 73 6f 72 20 73 79 6d 62 6f 6c 0a  rocessor symbol.
2880: 2a 2a 20 20 20 20 20 53 51 4c 49 54 45 5f 41 53  **     SQLITE_AS
2890: 59 4e 43 5f 54 57 4f 5f 46 49 4c 45 48 41 4e 44  YNC_TWO_FILEHAND
28a0: 4c 45 53 20 74 6f 20 30 2e 0a 2a 2f 0a 0a 23 69  LES to 0..*/..#i
28b0: 66 6e 64 65 66 20 53 51 4c 49 54 45 5f 41 53 59  fndef SQLITE_ASY
28c0: 4e 43 5f 54 57 4f 5f 46 49 4c 45 48 41 4e 44 4c  NC_TWO_FILEHANDL
28d0: 45 53 0a 2f 2a 20 23 64 65 66 69 6e 65 20 53 51  ES./* #define SQ
28e0: 4c 49 54 45 5f 41 53 59 4e 43 5f 54 57 4f 5f 46  LITE_ASYNC_TWO_F
28f0: 49 4c 45 48 41 4e 44 4c 45 53 20 30 20 2a 2f 0a  ILEHANDLES 0 */.
2900: 23 64 65 66 69 6e 65 20 53 51 4c 49 54 45 5f 41  #define SQLITE_A
2910: 53 59 4e 43 5f 54 57 4f 5f 46 49 4c 45 48 41 4e  SYNC_TWO_FILEHAN
2920: 44 4c 45 53 20 31 0a 23 65 6e 64 69 66 0a 0a 2f  DLES 1.#endif../
2930: 2a 0a 2a 2a 20 53 74 61 74 65 20 69 6e 66 6f 72  *.** State infor
2940: 6d 61 74 69 6f 6e 20 69 73 20 68 65 6c 64 20 69  mation is held i
2950: 6e 20 74 68 65 20 73 74 61 74 69 63 20 76 61 72  n the static var
2960: 69 61 62 6c 65 20 22 61 73 79 6e 63 22 20 64 65  iable "async" de
2970: 66 69 6e 65 64 0a 2a 2a 20 61 73 20 74 68 65 20  fined.** as the 
2980: 66 6f 6c 6c 6f 77 69 6e 67 20 73 74 72 75 63 74  following struct
2990: 75 72 65 2e 0a 2a 2a 0a 2a 2a 20 42 6f 74 68 20  ure..**.** Both 
29a0: 61 73 79 6e 63 2e 69 6f 45 72 72 6f 72 20 61 6e  async.ioError an
29b0: 64 20 61 73 79 6e 63 2e 6e 46 69 6c 65 20 61 72  d async.nFile ar
29c0: 65 20 70 72 6f 74 65 63 74 65 64 20 62 79 20 61  e protected by a
29d0: 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 2e  sync.queueMutex.
29e0: 0a 2a 2f 0a 73 74 61 74 69 63 20 73 74 72 75 63  .*/.static struc
29f0: 74 20 54 65 73 74 41 73 79 6e 63 53 74 61 74 69  t TestAsyncStati
2a00: 63 44 61 74 61 20 7b 0a 20 20 70 74 68 72 65 61  cData {.  pthrea
2a10: 64 5f 6d 75 74 65 78 5f 74 20 6c 6f 63 6b 4d 75  d_mutex_t lockMu
2a20: 74 65 78 3b 20 20 20 2f 2a 20 46 6f 72 20 61 63  tex;   /* For ac
2a30: 63 65 73 73 20 74 6f 20 61 4c 6f 63 6b 20 68 61  cess to aLock ha
2a40: 73 68 20 74 61 62 6c 65 20 2a 2f 0a 20 20 70 74  sh table */.  pt
2a50: 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 71 75  hread_mutex_t qu
2a60: 65 75 65 4d 75 74 65 78 3b 20 20 2f 2a 20 4d 75  eueMutex;  /* Mu
2a70: 74 65 78 20 66 6f 72 20 61 63 63 65 73 73 20 74  tex for access t
2a80: 6f 20 77 72 69 74 65 20 6f 70 65 72 61 74 69 6f  o write operatio
2a90: 6e 20 71 75 65 75 65 20 2a 2f 0a 20 20 70 74 68  n queue */.  pth
2aa0: 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 77 72 69  read_mutex_t wri
2ab0: 74 65 72 4d 75 74 65 78 3b 20 2f 2a 20 50 72 65  terMutex; /* Pre
2ac0: 76 65 6e 74 73 20 6d 75 6c 74 69 70 6c 65 20 77  vents multiple w
2ad0: 72 69 74 65 72 20 74 68 72 65 61 64 73 20 2a 2f  riter threads */
2ae0: 0a 20 20 70 74 68 72 65 61 64 5f 63 6f 6e 64 5f  .  pthread_cond_
2af0: 74 20 71 75 65 75 65 53 69 67 6e 61 6c 3b 20 20  t queueSignal;  
2b00: 2f 2a 20 46 6f 72 20 77 61 6b 69 6e 67 20 75 70  /* For waking up
2b10: 20 73 6c 65 65 70 69 6e 67 20 77 72 69 74 65 72   sleeping writer
2b20: 20 74 68 72 65 61 64 20 2a 2f 0a 20 20 70 74 68   thread */.  pth
2b30: 72 65 61 64 5f 63 6f 6e 64 5f 74 20 65 6d 70 74  read_cond_t empt
2b40: 79 53 69 67 6e 61 6c 3b 20 20 2f 2a 20 4e 6f 74  ySignal;  /* Not
2b50: 69 66 79 20 77 68 65 6e 20 74 68 65 20 77 72 69  ify when the wri
2b60: 74 65 20 71 75 65 75 65 20 69 73 20 65 6d 70 74  te queue is empt
2b70: 79 20 2a 2f 0a 20 20 41 73 79 6e 63 57 72 69 74  y */.  AsyncWrit
2b80: 65 20 2a 70 51 75 65 75 65 46 69 72 73 74 3b 20  e *pQueueFirst; 
2b90: 20 20 20 20 2f 2a 20 4e 65 78 74 20 77 72 69 74      /* Next writ
2ba0: 65 20 6f 70 65 72 61 74 69 6f 6e 20 74 6f 20 62  e operation to b
2bb0: 65 20 70 72 6f 63 65 73 73 65 64 20 2a 2f 0a 20  e processed */. 
2bc0: 20 41 73 79 6e 63 57 72 69 74 65 20 2a 70 51 75   AsyncWrite *pQu
2bd0: 65 75 65 4c 61 73 74 3b 20 20 20 20 20 20 2f 2a  eueLast;      /*
2be0: 20 4c 61 73 74 20 77 72 69 74 65 20 6f 70 65 72   Last write oper
2bf0: 61 74 69 6f 6e 20 6f 6e 20 74 68 65 20 6c 69 73  ation on the lis
2c00: 74 20 2a 2f 0a 20 20 48 61 73 68 20 61 4c 6f 63  t */.  Hash aLoc
2c10: 6b 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  k;              
2c20: 20 20 20 20 2f 2a 20 46 69 6c 65 73 20 6c 6f 63      /* Files loc
2c30: 6b 65 64 20 2a 2f 0a 20 20 76 6f 6c 61 74 69 6c  ked */.  volatil
2c40: 65 20 69 6e 74 20 69 6f 44 65 6c 61 79 3b 20 20  e int ioDelay;  
2c50: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 45 78             /* Ex
2c60: 74 72 61 20 64 65 6c 61 79 20 62 65 74 77 65 65  tra delay betwee
2c70: 6e 20 77 72 69 74 65 20 6f 70 65 72 61 74 69 6f  n write operatio
2c80: 6e 73 20 2a 2f 0a 20 20 76 6f 6c 61 74 69 6c 65  ns */.  volatile
2c90: 20 69 6e 74 20 77 72 69 74 65 72 48 61 6c 74 57   int writerHaltW
2ca0: 68 65 6e 49 64 6c 65 3b 20 20 2f 2a 20 57 72 69  henIdle;  /* Wri
2cb0: 74 65 72 20 74 68 72 65 61 64 20 68 61 6c 74 73  ter thread halts
2cc0: 20 77 68 65 6e 20 71 75 65 75 65 20 65 6d 70 74   when queue empt
2cd0: 79 20 2a 2f 0a 20 20 76 6f 6c 61 74 69 6c 65 20  y */.  volatile 
2ce0: 69 6e 74 20 77 72 69 74 65 72 48 61 6c 74 4e 6f  int writerHaltNo
2cf0: 77 3b 20 20 20 20 20 20 20 2f 2a 20 57 72 69 74  w;       /* Writ
2d00: 65 72 20 74 68 72 65 61 64 20 68 61 6c 74 73 20  er thread halts 
2d10: 61 66 74 65 72 20 6e 65 78 74 20 6f 70 20 2a 2f  after next op */
2d20: 0a 20 20 69 6e 74 20 69 6f 45 72 72 6f 72 3b 20  .  int ioError; 
2d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d40: 2f 2a 20 54 72 75 65 20 69 66 20 61 6e 20 49 4f  /* True if an IO
2d50: 20 65 72 72 6f 72 20 68 61 73 20 6f 63 63 75 72   error has occur
2d60: 65 64 20 2a 2f 0a 20 20 69 6e 74 20 6e 46 69 6c  ed */.  int nFil
2d70: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
2d80: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
2d90: 66 20 6f 70 65 6e 20 66 69 6c 65 73 20 28 66 72  f open files (fr
2da0: 6f 6d 20 73 71 6c 69 74 65 20 70 6f 76 29 20 2a  om sqlite pov) *
2db0: 2f 0a 7d 20 61 73 79 6e 63 20 3d 20 7b 0a 20 20  /.} async = {.  
2dc0: 50 54 48 52 45 41 44 5f 4d 55 54 45 58 5f 49 4e  PTHREAD_MUTEX_IN
2dd0: 49 54 49 41 4c 49 5a 45 52 2c 0a 20 20 50 54 48  ITIALIZER,.  PTH
2de0: 52 45 41 44 5f 4d 55 54 45 58 5f 49 4e 49 54 49  READ_MUTEX_INITI
2df0: 41 4c 49 5a 45 52 2c 0a 20 20 50 54 48 52 45 41  ALIZER,.  PTHREA
2e00: 44 5f 4d 55 54 45 58 5f 49 4e 49 54 49 41 4c 49  D_MUTEX_INITIALI
2e10: 5a 45 52 2c 0a 20 20 50 54 48 52 45 41 44 5f 43  ZER,.  PTHREAD_C
2e20: 4f 4e 44 5f 49 4e 49 54 49 41 4c 49 5a 45 52 2c  OND_INITIALIZER,
2e30: 0a 20 20 50 54 48 52 45 41 44 5f 43 4f 4e 44 5f  .  PTHREAD_COND_
2e40: 49 4e 49 54 49 41 4c 49 5a 45 52 2c 0a 7d 3b 0a  INITIALIZER,.};.
2e50: 0a 2f 2a 20 50 6f 73 73 69 62 6c 65 20 76 61 6c  ./* Possible val
2e60: 75 65 73 20 6f 66 20 41 73 79 6e 63 57 72 69 74  ues of AsyncWrit
2e70: 65 2e 6f 70 20 2a 2f 0a 23 64 65 66 69 6e 65 20  e.op */.#define 
2e80: 41 53 59 4e 43 5f 4e 4f 4f 50 20 20 20 20 20 20  ASYNC_NOOP      
2e90: 20 20 20 20 30 0a 23 64 65 66 69 6e 65 20 41 53      0.#define AS
2ea0: 59 4e 43 5f 57 52 49 54 45 20 20 20 20 20 20 20  YNC_WRITE       
2eb0: 20 20 31 0a 23 64 65 66 69 6e 65 20 41 53 59 4e    1.#define ASYN
2ec0: 43 5f 53 59 4e 43 20 20 20 20 20 20 20 20 20 20  C_SYNC          
2ed0: 32 0a 23 64 65 66 69 6e 65 20 41 53 59 4e 43 5f  2.#define ASYNC_
2ee0: 54 52 55 4e 43 41 54 45 20 20 20 20 20 20 33 0a  TRUNCATE      3.
2ef0: 23 64 65 66 69 6e 65 20 41 53 59 4e 43 5f 43 4c  #define ASYNC_CL
2f00: 4f 53 45 20 20 20 20 20 20 20 20 20 34 0a 23 64  OSE         4.#d
2f10: 65 66 69 6e 65 20 41 53 59 4e 43 5f 44 45 4c 45  efine ASYNC_DELE
2f20: 54 45 20 20 20 20 20 20 20 20 35 0a 23 64 65 66  TE        5.#def
2f30: 69 6e 65 20 41 53 59 4e 43 5f 4f 50 45 4e 45 58  ine ASYNC_OPENEX
2f40: 43 4c 55 53 49 56 45 20 36 0a 23 64 65 66 69 6e  CLUSIVE 6.#defin
2f50: 65 20 41 53 59 4e 43 5f 55 4e 4c 4f 43 4b 20 20  e ASYNC_UNLOCK  
2f60: 20 20 20 20 20 20 37 0a 0a 2f 2a 20 4e 61 6d 65        7../* Name
2f70: 73 20 6f 66 20 6f 70 63 6f 64 65 73 2e 20 20 55  s of opcodes.  U
2f80: 73 65 64 20 66 6f 72 20 64 65 62 75 67 67 69 6e  sed for debuggin
2f90: 67 20 6f 6e 6c 79 2e 0a 2a 2a 20 4d 61 6b 65 20  g only..** Make 
2fa0: 73 75 72 65 20 74 68 65 73 65 20 73 74 61 79 20  sure these stay 
2fb0: 69 6e 20 73 79 6e 63 20 77 69 74 68 20 74 68 65  in sync with the
2fc0: 20 6d 61 63 72 6f 73 20 61 62 6f 76 65 21 0a 2a   macros above!.*
2fd0: 2f 0a 73 74 61 74 69 63 20 63 6f 6e 73 74 20 63  /.static const c
2fe0: 68 61 72 20 2a 61 7a 4f 70 63 6f 64 65 4e 61 6d  har *azOpcodeNam
2ff0: 65 5b 5d 20 3d 20 7b 0a 20 20 22 4e 4f 4f 50 22  e[] = {.  "NOOP"
3000: 2c 20 22 57 52 49 54 45 22 2c 20 22 53 59 4e 43  , "WRITE", "SYNC
3010: 22 2c 20 22 54 52 55 4e 43 41 54 45 22 2c 20 22  ", "TRUNCATE", "
3020: 43 4c 4f 53 45 22 2c 20 22 44 45 4c 45 54 45 22  CLOSE", "DELETE"
3030: 2c 20 22 4f 50 45 4e 45 58 22 2c 20 22 55 4e 4c  , "OPENEX", "UNL
3040: 4f 43 4b 22 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 45  OCK".};../*.** E
3050: 6e 74 72 69 65 73 20 6f 6e 20 74 68 65 20 77 72  ntries on the wr
3060: 69 74 65 2d 6f 70 20 71 75 65 75 65 20 61 72 65  ite-op queue are
3070: 20 69 6e 73 74 61 6e 63 65 73 20 6f 66 20 74 68   instances of th
3080: 65 20 41 73 79 6e 63 57 72 69 74 65 0a 2a 2a 20  e AsyncWrite.** 
3090: 73 74 72 75 63 74 75 72 65 2c 20 64 65 66 69 6e  structure, defin
30a0: 65 64 20 68 65 72 65 2e 0a 2a 2a 0a 2a 2a 20 54  ed here..**.** T
30b0: 68 65 20 69 6e 74 65 72 70 72 65 74 61 74 69 6f  he interpretatio
30c0: 6e 20 6f 66 20 74 68 65 20 69 4f 66 66 73 65 74  n of the iOffset
30d0: 20 61 6e 64 20 6e 42 79 74 65 20 76 61 72 69 61   and nByte varia
30e0: 62 6c 65 73 20 76 61 72 69 65 73 20 64 65 70 65  bles varies depe
30f0: 6e 64 69 6e 67 20 0a 2a 2a 20 6f 6e 20 74 68 65  nding .** on the
3100: 20 76 61 6c 75 65 20 6f 66 20 41 73 79 6e 63 57   value of AsyncW
3110: 72 69 74 65 2e 6f 70 3a 0a 2a 2a 0a 2a 2a 20 41  rite.op:.**.** A
3120: 53 59 4e 43 5f 4e 4f 4f 50 3a 0a 2a 2a 20 20 20  SYNC_NOOP:.**   
3130: 20 20 4e 6f 20 76 61 6c 75 65 73 20 75 73 65 64    No values used
3140: 2e 0a 2a 2a 0a 2a 2a 20 41 53 59 4e 43 5f 57 52  ..**.** ASYNC_WR
3150: 49 54 45 3a 0a 2a 2a 20 20 20 20 20 69 4f 66 66  ITE:.**     iOff
3160: 73 65 74 20 2d 3e 20 4f 66 66 73 65 74 20 69 6e  set -> Offset in
3170: 20 66 69 6c 65 20 74 6f 20 77 72 69 74 65 20 74   file to write t
3180: 6f 2e 0a 2a 2a 20 20 20 20 20 6e 42 79 74 65 20  o..**     nByte 
3190: 20 20 2d 3e 20 4e 75 6d 62 65 72 20 6f 66 20 62    -> Number of b
31a0: 79 74 65 73 20 6f 66 20 64 61 74 61 20 74 6f 20  ytes of data to 
31b0: 77 72 69 74 65 20 28 70 6f 69 6e 74 65 64 20 74  write (pointed t
31c0: 6f 20 62 79 20 7a 42 75 66 29 2e 0a 2a 2a 0a 2a  o by zBuf)..**.*
31d0: 2a 20 41 53 59 4e 43 5f 53 59 4e 43 3a 0a 2a 2a  * ASYNC_SYNC:.**
31e0: 20 20 20 20 20 6e 42 79 74 65 20 20 20 2d 3e 20       nByte   -> 
31f0: 66 6c 61 67 73 20 74 6f 20 70 61 73 73 20 74 6f  flags to pass to
3200: 20 73 71 6c 69 74 65 33 4f 73 53 79 6e 63 28 29   sqlite3OsSync()
3210: 2e 0a 2a 2a 0a 2a 2a 20 41 53 59 4e 43 5f 54 52  ..**.** ASYNC_TR
3220: 55 4e 43 41 54 45 3a 0a 2a 2a 20 20 20 20 20 69  UNCATE:.**     i
3230: 4f 66 66 73 65 74 20 2d 3e 20 53 69 7a 65 20 74  Offset -> Size t
3240: 6f 20 74 72 75 6e 63 61 74 65 20 66 69 6c 65 20  o truncate file 
3250: 74 6f 2e 0a 2a 2a 20 20 20 20 20 6e 42 79 74 65  to..**     nByte
3260: 20 20 20 2d 3e 20 55 6e 75 73 65 64 2e 0a 2a 2a     -> Unused..**
3270: 0a 2a 2a 20 41 53 59 4e 43 5f 43 4c 4f 53 45 3a  .** ASYNC_CLOSE:
3280: 0a 2a 2a 20 20 20 20 20 69 4f 66 66 73 65 74 20  .**     iOffset 
3290: 2d 3e 20 55 6e 75 73 65 64 2e 0a 2a 2a 20 20 20  -> Unused..**   
32a0: 20 20 6e 42 79 74 65 20 20 20 2d 3e 20 55 6e 75    nByte   -> Unu
32b0: 73 65 64 2e 0a 2a 2a 0a 2a 2a 20 41 53 59 4e 43  sed..**.** ASYNC
32c0: 5f 44 45 4c 45 54 45 3a 0a 2a 2a 20 20 20 20 20  _DELETE:.**     
32d0: 69 4f 66 66 73 65 74 20 2d 3e 20 43 6f 6e 74 61  iOffset -> Conta
32e0: 69 6e 73 20 74 68 65 20 22 73 79 6e 63 44 69 72  ins the "syncDir
32f0: 22 20 66 6c 61 67 2e 0a 2a 2a 20 20 20 20 20 6e  " flag..**     n
3300: 42 79 74 65 20 20 20 2d 3e 20 4e 75 6d 62 65 72  Byte   -> Number
3310: 20 6f 66 20 62 79 74 65 73 20 6f 66 20 7a 42 75   of bytes of zBu
3320: 66 20 70 6f 69 6e 74 73 20 74 6f 20 28 66 69 6c  f points to (fil
3330: 65 20 6e 61 6d 65 29 2e 0a 2a 2a 0a 2a 2a 20 41  e name)..**.** A
3340: 53 59 4e 43 5f 4f 50 45 4e 45 58 43 4c 55 53 49  SYNC_OPENEXCLUSI
3350: 56 45 3a 0a 2a 2a 20 20 20 20 20 69 4f 66 66 73  VE:.**     iOffs
3360: 65 74 20 2d 3e 20 56 61 6c 75 65 20 6f 66 20 22  et -> Value of "
3370: 64 65 6c 66 6c 61 67 22 2e 0a 2a 2a 20 20 20 20  delflag"..**    
3380: 20 6e 42 79 74 65 20 20 20 2d 3e 20 4e 75 6d 62   nByte   -> Numb
3390: 65 72 20 6f 66 20 62 79 74 65 73 20 6f 66 20 7a  er of bytes of z
33a0: 42 75 66 20 70 6f 69 6e 74 73 20 74 6f 20 28 66  Buf points to (f
33b0: 69 6c 65 20 6e 61 6d 65 29 2e 0a 2a 2a 0a 2a 2a  ile name)..**.**
33c0: 20 41 53 59 4e 43 5f 55 4e 4c 4f 43 4b 3a 0a 2a   ASYNC_UNLOCK:.*
33d0: 2a 20 20 20 20 20 6e 42 79 74 65 20 20 20 2d 3e  *     nByte   ->
33e0: 20 41 72 67 75 6d 65 6e 74 20 74 6f 20 73 71 6c   Argument to sql
33f0: 69 74 65 33 4f 73 55 6e 6c 6f 63 6b 28 29 2e 0a  ite3OsUnlock()..
3400: 2a 2a 0a 2a 2a 0a 2a 2a 20 46 6f 72 20 61 6e 20  **.**.** For an 
3410: 41 53 59 4e 43 5f 57 52 49 54 45 20 6f 70 65 72  ASYNC_WRITE oper
3420: 61 74 69 6f 6e 2c 20 7a 42 75 66 20 70 6f 69 6e  ation, zBuf poin
3430: 74 73 20 74 6f 20 74 68 65 20 64 61 74 61 20 74  ts to the data t
3440: 6f 20 77 72 69 74 65 20 74 6f 20 74 68 65 20 66  o write to the f
3450: 69 6c 65 2e 20 0a 2a 2a 20 54 68 69 73 20 73 70  ile. .** This sp
3460: 61 63 65 20 69 73 20 73 71 6c 69 74 65 33 5f 6d  ace is sqlite3_m
3470: 61 6c 6c 6f 63 28 29 64 20 61 6c 6f 6e 67 20 77  alloc()d along w
3480: 69 74 68 20 74 68 65 20 41 73 79 6e 63 57 72 69  ith the AsyncWri
3490: 74 65 20 73 74 72 75 63 74 75 72 65 20 69 6e 20  te structure in 
34a0: 61 0a 2a 2a 20 73 69 6e 67 6c 65 20 62 6c 6f 62  a.** single blob
34b0: 2c 20 73 6f 20 69 73 20 64 65 6c 65 74 65 64 20  , so is deleted 
34c0: 77 68 65 6e 20 73 71 6c 69 74 65 33 5f 66 72 65  when sqlite3_fre
34d0: 65 28 29 20 69 73 20 63 61 6c 6c 65 64 20 6f 6e  e() is called on
34e0: 20 74 68 65 20 70 61 72 65 6e 74 20 0a 2a 2a 20   the parent .** 
34f0: 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74  structure..*/.st
3500: 72 75 63 74 20 41 73 79 6e 63 57 72 69 74 65 20  ruct AsyncWrite 
3510: 7b 0a 20 20 41 73 79 6e 63 46 69 6c 65 44 61 74  {.  AsyncFileDat
3520: 61 20 2a 70 46 69 6c 65 44 61 74 61 3b 20 20 20  a *pFileData;   
3530: 20 2f 2a 20 46 69 6c 65 20 74 6f 20 77 72 69 74   /* File to writ
3540: 65 20 64 61 74 61 20 74 6f 20 6f 72 20 73 79 6e  e data to or syn
3550: 63 20 2a 2f 0a 20 20 69 6e 74 20 6f 70 3b 20 20  c */.  int op;  
3560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3570: 20 20 20 20 2f 2a 20 4f 6e 65 20 6f 66 20 41 53      /* One of AS
3580: 59 4e 43 5f 78 78 78 20 65 74 63 2e 20 2a 2f 0a  YNC_xxx etc. */.
3590: 20 20 69 36 34 20 69 4f 66 66 73 65 74 3b 20 20    i64 iOffset;  
35a0: 20 20 20 20 20 20 2f 2a 20 53 65 65 20 61 62 6f        /* See abo
35b0: 76 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 42 79 74  ve */.  int nByt
35c0: 65 3b 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53  e;          /* S
35d0: 65 65 20 61 62 6f 76 65 20 2a 2f 0a 20 20 63 68  ee above */.  ch
35e0: 61 72 20 2a 7a 42 75 66 3b 20 20 20 20 20 20 20  ar *zBuf;       
35f0: 20 20 2f 2a 20 44 61 74 61 20 74 6f 20 77 72 69    /* Data to wri
3600: 74 65 20 74 6f 20 66 69 6c 65 20 28 6f 72 20 4e  te to file (or N
3610: 55 4c 4c 20 69 66 20 6f 70 21 3d 41 53 59 4e 43  ULL if op!=ASYNC
3620: 5f 57 52 49 54 45 29 20 2a 2f 0a 20 20 41 73 79  _WRITE) */.  Asy
3630: 6e 63 57 72 69 74 65 20 2a 70 4e 65 78 74 3b 20  ncWrite *pNext; 
3640: 20 2f 2a 20 4e 65 78 74 20 77 72 69 74 65 20 6f   /* Next write o
3650: 70 65 72 61 74 69 6f 6e 20 28 74 6f 20 61 6e 79  peration (to any
3660: 20 66 69 6c 65 29 20 2a 2f 0a 7d 3b 0a 0a 2f 2a   file) */.};../*
3670: 0a 2a 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20  .** An instance 
3680: 6f 66 20 74 68 69 73 20 73 74 72 75 63 74 75 72  of this structur
3690: 65 20 69 73 20 63 72 65 61 74 65 64 20 66 6f 72  e is created for
36a0: 20 65 61 63 68 20 64 69 73 74 69 6e 63 74 20 6f   each distinct o
36b0: 70 65 6e 20 66 69 6c 65 20 0a 2a 2a 20 28 69 2e  pen file .** (i.
36c0: 65 2e 20 69 66 20 74 77 6f 20 68 61 6e 64 6c 65  e. if two handle
36d0: 73 20 61 72 65 20 6f 70 65 6e 65 64 20 6f 6e 20  s are opened on 
36e0: 74 68 65 20 6f 6e 65 20 66 69 6c 65 2c 20 6f 6e  the one file, on
36f0: 6c 79 20 6f 6e 65 20 6f 66 20 74 68 65 73 65 0a  ly one of these.
3700: 2a 2a 20 73 74 72 75 63 74 75 72 65 73 20 69 73  ** structures is
3710: 20 61 6c 6c 6f 63 61 74 65 64 29 20 61 6e 64 20   allocated) and 
3720: 73 74 6f 72 65 64 20 69 6e 20 74 68 65 20 61 73  stored in the as
3730: 79 6e 63 2e 61 4c 6f 63 6b 20 68 61 73 68 20 74  ync.aLock hash t
3740: 61 62 6c 65 2e 20 54 68 65 0a 2a 2a 20 6b 65 79  able. The.** key
3750: 73 20 66 6f 72 20 61 73 79 6e 63 2e 61 4c 6f 63  s for async.aLoc
3760: 6b 20 61 72 65 20 74 68 65 20 66 75 6c 6c 20 70  k are the full p
3770: 61 74 68 6e 61 6d 65 73 20 6f 66 20 74 68 65 20  athnames of the 
3780: 6f 70 65 6e 65 64 20 66 69 6c 65 73 2e 0a 2a 2a  opened files..**
3790: 0a 2a 2a 20 41 73 79 6e 63 4c 6f 63 6b 2e 70 4c  .** AsyncLock.pL
37a0: 69 73 74 20 70 6f 69 6e 74 73 20 74 6f 20 74 68  ist points to th
37b0: 65 20 68 65 61 64 20 6f 66 20 61 20 6c 69 6e 6b  e head of a link
37c0: 65 64 20 6c 69 73 74 20 6f 66 20 41 73 79 6e 63  ed list of Async
37d0: 46 69 6c 65 4c 6f 63 6b 0a 2a 2a 20 73 74 72 75  FileLock.** stru
37e0: 63 74 75 72 65 73 2c 20 6f 6e 65 20 66 6f 72 20  ctures, one for 
37f0: 65 61 63 68 20 68 61 6e 64 6c 65 20 63 75 72 72  each handle curr
3800: 65 6e 74 6c 79 20 6f 70 65 6e 20 6f 6e 20 74 68  ently open on th
3810: 65 20 66 69 6c 65 2e 0a 2a 2a 0a 2a 2a 20 49 66  e file..**.** If
3820: 20 74 68 65 20 6f 70 65 6e 65 64 20 66 69 6c 65   the opened file
3830: 20 69 73 20 6e 6f 74 20 61 20 6d 61 69 6e 2d 64   is not a main-d
3840: 61 74 61 62 61 73 65 20 28 74 68 65 20 53 51 4c  atabase (the SQL
3850: 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 44 42  ITE_OPEN_MAIN_DB
3860: 20 69 73 0a 2a 2a 20 6e 6f 74 20 70 61 73 73 65   is.** not passe
3870: 64 20 74 6f 20 74 68 65 20 73 71 6c 69 74 65 33  d to the sqlite3
3880: 4f 73 4f 70 65 6e 28 29 20 63 61 6c 6c 29 2c 20  OsOpen() call), 
3890: 6f 72 20 69 66 20 45 4e 41 42 4c 45 5f 46 49 4c  or if ENABLE_FIL
38a0: 45 5f 4c 4f 43 4b 49 4e 47 20 69 73 20 0a 2a 2a  E_LOCKING is .**
38b0: 20 6e 6f 74 20 64 65 66 69 6e 65 64 20 61 74 20   not defined at 
38c0: 63 6f 6d 70 69 6c 65 20 74 69 6d 65 2c 20 76 61  compile time, va
38d0: 72 69 61 62 6c 65 73 20 41 73 79 6e 63 4c 6f 63  riables AsyncLoc
38e0: 6b 2e 70 46 69 6c 65 20 61 6e 64 20 0a 2a 2a 20  k.pFile and .** 
38f0: 41 73 79 6e 63 4c 6f 63 6b 2e 65 4c 6f 63 6b 20  AsyncLock.eLock 
3900: 61 72 65 20 6e 65 76 65 72 20 75 73 65 64 2e 20  are never used. 
3910: 4f 74 68 65 72 77 69 73 65 2c 20 70 46 69 6c 65  Otherwise, pFile
3920: 20 69 73 20 61 20 66 69 6c 65 20 68 61 6e 64 6c   is a file handl
3930: 65 0a 2a 2a 20 6f 70 65 6e 65 64 20 6f 6e 20 74  e.** opened on t
3940: 68 65 20 66 69 6c 65 20 69 6e 20 71 75 65 73 74  he file in quest
3950: 69 6f 6e 20 61 6e 64 20 75 73 65 64 20 74 6f 20  ion and used to 
3960: 6f 62 74 61 69 6e 20 74 68 65 20 66 69 6c 65 2d  obtain the file-
3970: 73 79 73 74 65 6d 20 0a 2a 2a 20 6c 6f 63 6b 73  system .** locks
3980: 20 72 65 71 75 69 72 65 64 20 62 79 20 64 61 74   required by dat
3990: 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e  abase connection
39a0: 73 20 77 69 74 68 69 6e 20 74 68 69 73 20 70 72  s within this pr
39b0: 6f 63 65 73 73 2e 0a 2a 2a 0a 2a 2a 20 53 65 65  ocess..**.** See
39c0: 20 63 6f 6d 6d 65 6e 74 73 20 61 62 6f 76 65 20   comments above 
39d0: 74 68 65 20 61 73 79 6e 63 4c 6f 63 6b 28 29 20  the asyncLock() 
39e0: 66 75 6e 63 74 69 6f 6e 20 66 6f 72 20 6d 6f 72  function for mor
39f0: 65 20 64 65 74 61 69 6c 73 20 6f 6e 20 0a 2a 2a  e details on .**
3a00: 20 74 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74   the implementat
3a10: 69 6f 6e 20 6f 66 20 64 61 74 61 62 61 73 65 20  ion of database 
3a20: 6c 6f 63 6b 69 6e 67 20 75 73 65 64 20 62 79 20  locking used by 
3a30: 74 68 69 73 20 62 61 63 6b 65 6e 64 2e 0a 2a 2f  this backend..*/
3a40: 0a 73 74 72 75 63 74 20 41 73 79 6e 63 4c 6f 63  .struct AsyncLoc
3a50: 6b 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  k {.  sqlite3_fi
3a60: 6c 65 20 2a 70 46 69 6c 65 3b 0a 20 20 69 6e 74  le *pFile;.  int
3a70: 20 65 4c 6f 63 6b 3b 0a 20 20 41 73 79 6e 63 46   eLock;.  AsyncF
3a80: 69 6c 65 4c 6f 63 6b 20 2a 70 4c 69 73 74 3b 0a  ileLock *pList;.
3a90: 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6e 20 69 6e 73  };../*.** An ins
3aa0: 74 61 6e 63 65 20 6f 66 20 74 68 65 20 66 6f 6c  tance of the fol
3ab0: 6c 6f 77 69 6e 67 20 73 74 72 75 63 74 75 72 65  lowing structure
3ac0: 20 69 73 20 61 6c 6c 6f 63 61 74 65 64 20 61 6c   is allocated al
3ad0: 6f 6e 67 20 77 69 74 68 20 65 61 63 68 0a 2a 2a  ong with each.**
3ae0: 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 20 73   AsyncFileData s
3af0: 74 72 75 63 74 75 72 65 20 28 73 65 65 20 41 73  tructure (see As
3b00: 79 6e 63 46 69 6c 65 44 61 74 61 2e 6c 6f 63 6b  yncFileData.lock
3b10: 29 2c 20 62 75 74 20 69 73 20 6f 6e 6c 79 20 75  ), but is only u
3b20: 73 65 64 20 69 66 20 74 68 65 0a 2a 2a 20 66 69  sed if the.** fi
3b30: 6c 65 20 77 61 73 20 6f 70 65 6e 65 64 20 77 69  le was opened wi
3b40: 74 68 20 74 68 65 20 53 51 4c 49 54 45 5f 4f 50  th the SQLITE_OP
3b50: 45 4e 5f 4d 41 49 4e 5f 44 42 2e 0a 2a 2f 0a 73  EN_MAIN_DB..*/.s
3b60: 74 72 75 63 74 20 41 73 79 6e 63 46 69 6c 65 4c  truct AsyncFileL
3b70: 6f 63 6b 20 7b 0a 20 20 69 6e 74 20 65 4c 6f 63  ock {.  int eLoc
3b80: 6b 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  k;              
3b90: 20 20 2f 2a 20 49 6e 74 65 72 6e 61 6c 6c 79 20    /* Internally 
3ba0: 76 69 73 69 62 6c 65 20 6c 6f 63 6b 20 73 74 61  visible lock sta
3bb0: 74 65 20 28 73 71 6c 69 74 65 20 70 6f 76 29 20  te (sqlite pov) 
3bc0: 2a 2f 0a 20 20 69 6e 74 20 65 41 73 79 6e 63 4c  */.  int eAsyncL
3bd0: 6f 63 6b 3b 20 20 20 20 20 20 20 20 20 20 20 2f  ock;           /
3be0: 2a 20 4c 6f 63 6b 2d 73 74 61 74 65 20 77 69 74  * Lock-state wit
3bf0: 68 20 77 72 69 74 65 2d 71 75 65 75 65 20 75 6e  h write-queue un
3c00: 6c 6f 63 6b 20 2a 2f 0a 20 20 41 73 79 6e 63 46  lock */.  AsyncF
3c10: 69 6c 65 4c 6f 63 6b 20 2a 70 4e 65 78 74 3b 0a  ileLock *pNext;.
3c20: 7d 3b 0a 0a 2f 2a 20 0a 2a 2a 20 54 68 65 20 41  };../* .** The A
3c30: 73 79 6e 63 46 69 6c 65 20 73 74 72 75 63 74 75  syncFile structu
3c40: 72 65 20 69 73 20 61 20 73 75 62 63 6c 61 73 73  re is a subclass
3c50: 20 6f 66 20 73 71 6c 69 74 65 33 5f 66 69 6c 65   of sqlite3_file
3c60: 20 75 73 65 64 20 66 6f 72 20 0a 2a 2a 20 61 73   used for .** as
3c70: 79 6e 63 68 72 6f 6e 6f 75 73 20 49 4f 2e 20 0a  ynchronous IO. .
3c80: 2a 2a 0a 2a 2a 20 41 6c 6c 20 6f 66 20 74 68 65  **.** All of the
3c90: 20 61 63 74 75 61 6c 20 64 61 74 61 20 66 6f 72   actual data for
3ca0: 20 74 68 65 20 73 74 72 75 63 74 75 72 65 20 69   the structure i
3cb0: 73 20 73 74 6f 72 65 64 20 69 6e 20 74 68 65 20  s stored in the 
3cc0: 73 74 72 75 63 74 75 72 65 0a 2a 2a 20 70 6f 69  structure.** poi
3cd0: 6e 74 65 64 20 74 6f 20 62 79 20 41 73 79 6e 63  nted to by Async
3ce0: 46 69 6c 65 2e 70 44 61 74 61 2c 20 77 68 69 63  File.pData, whic
3cf0: 68 20 69 73 20 61 6c 6c 6f 63 61 74 65 64 20 61  h is allocated a
3d00: 73 20 70 61 72 74 20 6f 66 20 74 68 65 0a 2a 2a  s part of the.**
3d10: 20 73 71 6c 69 74 65 33 4f 73 4f 70 65 6e 28 29   sqlite3OsOpen()
3d20: 20 75 73 69 6e 67 20 73 71 6c 69 74 65 33 5f 6d   using sqlite3_m
3d30: 61 6c 6c 6f 63 28 29 2e 20 54 68 65 20 72 65 61  alloc(). The rea
3d40: 73 6f 6e 20 66 6f 72 20 74 68 69 73 20 69 73 20  son for this is 
3d50: 74 68 61 74 20 74 68 65 0a 2a 2a 20 6c 69 66 65  that the.** life
3d60: 74 69 6d 65 20 6f 66 20 74 68 65 20 41 73 79 6e  time of the Asyn
3d70: 63 46 69 6c 65 20 73 74 72 75 63 74 75 72 65 20  cFile structure 
3d80: 69 73 20 65 6e 64 65 64 20 62 79 20 74 68 65 20  is ended by the 
3d90: 63 61 6c 6c 65 72 20 61 66 74 65 72 20 4f 73 43  caller after OsC
3da0: 6c 6f 73 65 28 29 0a 2a 2a 20 69 73 20 63 61 6c  lose().** is cal
3db0: 6c 65 64 2c 20 62 75 74 20 74 68 65 20 64 61 74  led, but the dat
3dc0: 61 20 69 6e 20 41 73 79 6e 63 46 69 6c 65 44 61  a in AsyncFileDa
3dd0: 74 61 20 6d 61 79 20 62 65 20 72 65 71 75 69 72  ta may be requir
3de0: 65 64 20 62 79 20 74 68 65 0a 2a 2a 20 77 72 69  ed by the.** wri
3df0: 74 65 72 20 74 68 72 65 61 64 20 61 66 74 65 72  ter thread after
3e00: 20 74 68 61 74 20 70 6f 69 6e 74 2e 0a 2a 2f 0a   that point..*/.
3e10: 73 74 72 75 63 74 20 41 73 79 6e 63 46 69 6c 65  struct AsyncFile
3e20: 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f 69 6f 5f   {.  sqlite3_io_
3e30: 6d 65 74 68 6f 64 73 20 2a 70 4d 65 74 68 6f 64  methods *pMethod
3e40: 3b 0a 20 20 41 73 79 6e 63 46 69 6c 65 44 61 74  ;.  AsyncFileDat
3e50: 61 20 2a 70 44 61 74 61 3b 0a 7d 3b 0a 73 74 72  a *pData;.};.str
3e60: 75 63 74 20 41 73 79 6e 63 46 69 6c 65 44 61 74  uct AsyncFileDat
3e70: 61 20 7b 0a 20 20 63 68 61 72 20 2a 7a 4e 61 6d  a {.  char *zNam
3e80: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
3e90: 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67 20 4f   /* Underlying O
3ea0: 53 20 66 69 6c 65 6e 61 6d 65 20 2d 20 75 73 65  S filename - use
3eb0: 64 20 66 6f 72 20 64 65 62 75 67 67 69 6e 67 20  d for debugging 
3ec0: 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 20  */.  int nName; 
3ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3ee0: 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 63 68 61  /* Number of cha
3ef0: 72 61 63 74 65 72 73 20 69 6e 20 7a 4e 61 6d 65  racters in zName
3f00: 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 66 69   */.  sqlite3_fi
3f10: 6c 65 20 2a 70 42 61 73 65 52 65 61 64 3b 20 20  le *pBaseRead;  
3f20: 20 2f 2a 20 52 65 61 64 20 68 61 6e 64 6c 65 20   /* Read handle 
3f30: 74 6f 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e  to the underlyin
3f40: 67 20 4f 73 20 66 69 6c 65 20 2a 2f 0a 20 20 73  g Os file */.  s
3f50: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 42 61  qlite3_file *pBa
3f60: 73 65 57 72 69 74 65 3b 20 20 2f 2a 20 57 72 69  seWrite;  /* Wri
3f70: 74 65 20 68 61 6e 64 6c 65 20 74 6f 20 74 68 65  te handle to the
3f80: 20 75 6e 64 65 72 6c 79 69 6e 67 20 4f 73 20 66   underlying Os f
3f90: 69 6c 65 20 2a 2f 0a 20 20 41 73 79 6e 63 46 69  ile */.  AsyncFi
3fa0: 6c 65 4c 6f 63 6b 20 6c 6f 63 6b 3b 0a 20 20 41  leLock lock;.  A
3fb0: 73 79 6e 63 57 72 69 74 65 20 63 6c 6f 73 65 3b  syncWrite close;
3fc0: 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 20 66  .};../*.** The f
3fd0: 6f 6c 6c 6f 77 69 6e 67 20 61 73 79 6e 63 5f 58  ollowing async_X
3fe0: 58 58 20 66 75 6e 63 74 69 6f 6e 73 20 61 72 65  XX functions are
3ff0: 20 64 65 62 75 67 67 69 6e 67 20 77 72 61 70 70   debugging wrapp
4000: 65 72 73 20 61 72 6f 75 6e 64 20 74 68 65 0a 2a  ers around the.*
4010: 2a 20 63 6f 72 72 65 73 70 6f 6e 64 69 6e 67 20  * corresponding 
4020: 70 74 68 72 65 61 64 5f 58 58 58 20 66 75 6e 63  pthread_XXX func
4030: 74 69 6f 6e 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20  tions:.**.**    
4040: 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c   pthread_mutex_l
4050: 6f 63 6b 28 29 3b 0a 2a 2a 20 20 20 20 20 70 74  ock();.**     pt
4060: 68 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f  hread_mutex_unlo
4070: 63 6b 28 29 3b 0a 2a 2a 20 20 20 20 20 70 74 68  ck();.**     pth
4080: 72 65 61 64 5f 6d 75 74 65 78 5f 74 72 79 6c 6f  read_mutex_trylo
4090: 63 6b 28 29 3b 0a 2a 2a 20 20 20 20 20 70 74 68  ck();.**     pth
40a0: 72 65 61 64 5f 63 6f 6e 64 5f 77 61 69 74 28 29  read_cond_wait()
40b0: 3b 0a 2a 2a 0a 2a 2a 20 49 74 20 69 73 20 69 6c  ;.**.** It is il
40c0: 6c 65 67 61 6c 20 74 6f 20 70 61 73 73 20 61 6e  legal to pass an
40d0: 79 20 6d 75 74 65 78 20 6f 74 68 65 72 20 74 68  y mutex other th
40e0: 61 6e 20 74 68 6f 73 65 20 73 74 6f 72 65 64 20  an those stored 
40f0: 69 6e 20 74 68 65 0a 2a 2a 20 66 6f 6c 6c 6f 77  in the.** follow
4100: 69 6e 67 20 67 6c 6f 62 61 6c 20 76 61 72 69 61  ing global varia
4110: 62 6c 65 73 20 6f 66 20 74 68 65 73 65 20 66 75  bles of these fu
4120: 6e 63 74 69 6f 6e 73 2e 0a 2a 2a 0a 2a 2a 20 20  nctions..**.**  
4130: 20 20 20 61 73 79 6e 63 2e 71 75 65 75 65 4d 75     async.queueMu
4140: 74 65 78 0a 2a 2a 20 20 20 20 20 61 73 79 6e 63  tex.**     async
4150: 2e 77 72 69 74 65 72 4d 75 74 65 78 0a 2a 2a 20  .writerMutex.** 
4160: 20 20 20 20 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75      async.lockMu
4170: 74 65 78 0a 2a 2a 0a 2a 2a 20 49 66 20 4e 44 45  tex.**.** If NDE
4180: 42 55 47 20 69 73 20 64 65 66 69 6e 65 64 2c 20  BUG is defined, 
4190: 74 68 65 73 65 20 77 72 61 70 70 65 72 73 20 64  these wrappers d
41a0: 6f 20 6e 6f 74 68 69 6e 67 20 65 78 63 65 70 74  o nothing except
41b0: 20 63 61 6c 6c 20 74 68 65 20 0a 2a 2a 20 63 6f   call the .** co
41c0: 72 72 65 73 70 6f 6e 64 69 6e 67 20 70 74 68 72  rresponding pthr
41d0: 65 61 64 73 20 66 75 6e 63 74 69 6f 6e 2e 20 49  eads function. I
41e0: 66 20 4e 44 45 42 55 47 20 69 73 20 6e 6f 74 20  f NDEBUG is not 
41f0: 64 65 66 69 6e 65 64 2c 20 74 68 65 6e 20 74 68  defined, then th
4200: 65 0a 2a 2a 20 66 6f 6c 6c 6f 77 69 6e 67 20 76  e.** following v
4210: 61 72 69 61 62 6c 65 73 20 61 72 65 20 75 73 65  ariables are use
4220: 64 20 74 6f 20 73 74 6f 72 65 20 74 68 65 20 74  d to store the t
4230: 68 72 65 61 64 2d 69 64 20 28 61 73 20 72 65 74  hread-id (as ret
4240: 75 72 6e 65 64 0a 2a 2a 20 62 79 20 70 74 68 72  urned.** by pthr
4250: 65 61 64 5f 73 65 6c 66 28 29 29 20 63 75 72 72  ead_self()) curr
4260: 65 6e 74 6c 79 20 68 6f 6c 64 69 6e 67 20 74 68  ently holding th
4270: 65 20 6d 75 74 65 78 2c 20 6f 72 20 30 20 6f 74  e mutex, or 0 ot
4280: 68 65 72 77 69 73 65 3a 0a 2a 2a 0a 2a 2a 20 20  herwise:.**.**  
4290: 20 20 20 61 73 79 6e 63 64 65 62 75 67 2e 71 75     asyncdebug.qu
42a0: 65 75 65 4d 75 74 65 78 48 6f 6c 64 65 72 0a 2a  eueMutexHolder.*
42b0: 2a 20 20 20 20 20 61 73 79 6e 63 64 65 62 75 67  *     asyncdebug
42c0: 2e 77 72 69 74 65 72 4d 75 74 65 78 48 6f 6c 64  .writerMutexHold
42d0: 65 72 0a 2a 2a 20 20 20 20 20 61 73 79 6e 63 64  er.**     asyncd
42e0: 65 62 75 67 2e 6c 6f 63 6b 4d 75 74 65 78 48 6f  ebug.lockMutexHo
42f0: 6c 64 65 72 0a 2a 2a 0a 2a 2a 20 54 68 65 73 65  lder.**.** These
4300: 20 76 61 72 69 61 62 6c 65 73 20 61 72 65 20 75   variables are u
4310: 73 65 64 20 62 79 20 73 6f 6d 65 20 61 73 73 65  sed by some asse
4320: 72 74 28 29 20 73 74 61 74 65 6d 65 6e 74 73 20  rt() statements 
4330: 74 68 61 74 20 76 65 72 69 66 79 0a 2a 2a 20 74  that verify.** t
4340: 68 65 20 73 74 61 74 65 6d 65 6e 74 73 20 6d 61  he statements ma
4350: 64 65 20 69 6e 20 74 68 65 20 22 44 65 61 64 6c  de in the "Deadl
4360: 6f 63 6b 20 50 72 65 76 65 6e 74 69 6f 6e 22 20  ock Prevention" 
4370: 6e 6f 74 65 73 20 65 61 72 6c 69 65 72 0a 2a 2a  notes earlier.**
4380: 20 69 6e 20 74 68 69 73 20 66 69 6c 65 2e 0a 2a   in this file..*
4390: 2f 0a 23 69 66 6e 64 65 66 20 4e 44 45 42 55 47  /.#ifndef NDEBUG
43a0: 0a 0a 73 74 61 74 69 63 20 73 74 72 75 63 74 20  ..static struct 
43b0: 54 65 73 74 41 73 79 6e 63 44 65 62 75 67 44 61  TestAsyncDebugDa
43c0: 74 61 20 7b 0a 20 20 70 74 68 72 65 61 64 5f 74  ta {.  pthread_t
43d0: 20 6c 6f 63 6b 4d 75 74 65 78 48 6f 6c 64 65 72   lockMutexHolder
43e0: 3b 0a 20 20 70 74 68 72 65 61 64 5f 74 20 71 75  ;.  pthread_t qu
43f0: 65 75 65 4d 75 74 65 78 48 6f 6c 64 65 72 3b 0a  eueMutexHolder;.
4400: 20 20 70 74 68 72 65 61 64 5f 74 20 77 72 69 74    pthread_t writ
4410: 65 72 4d 75 74 65 78 48 6f 6c 64 65 72 3b 0a 7d  erMutexHolder;.}
4420: 20 61 73 79 6e 63 64 65 62 75 67 20 3d 20 7b 30   asyncdebug = {0
4430: 2c 20 30 2c 20 30 7d 3b 0a 0a 2f 2a 0a 2a 2a 20  , 0, 0};../*.** 
4440: 57 72 61 70 70 65 72 20 61 72 6f 75 6e 64 20 70  Wrapper around p
4450: 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c 6f 63  thread_mutex_loc
4460: 6b 28 29 2e 20 43 68 65 63 6b 73 20 74 68 61 74  k(). Checks that
4470: 20 77 65 20 68 61 76 65 20 6e 6f 74 20 76 69 6f   we have not vio
4480: 6c 61 74 65 64 0a 2a 2a 20 74 68 65 20 61 6e 74  lated.** the ant
4490: 69 2d 64 65 61 64 6c 6f 63 6b 20 72 75 6c 65 73  i-deadlock rules
44a0: 20 28 73 65 65 20 22 44 65 61 64 6c 6f 63 6b 20   (see "Deadlock 
44b0: 70 72 65 76 65 6e 74 69 6f 6e 22 20 61 62 6f 76  prevention" abov
44c0: 65 29 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  e)..*/.static in
44d0: 74 20 61 73 79 6e 63 5f 6d 75 74 65 78 5f 6c 6f  t async_mutex_lo
44e0: 63 6b 28 70 74 68 72 65 61 64 5f 6d 75 74 65 78  ck(pthread_mutex
44f0: 5f 74 20 2a 70 4d 75 74 65 78 29 7b 0a 20 20 69  _t *pMutex){.  i
4500: 6e 74 20 69 49 64 78 3b 0a 20 20 69 6e 74 20 72  nt iIdx;.  int r
4510: 63 3b 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74  c;.  pthread_mut
4520: 65 78 5f 74 20 2a 61 4d 75 74 65 78 20 3d 20 28  ex_t *aMutex = (
4530: 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 20  pthread_mutex_t 
4540: 2a 29 28 26 61 73 79 6e 63 29 3b 0a 20 20 70 74  *)(&async);.  pt
4550: 68 72 65 61 64 5f 74 20 2a 61 48 6f 6c 64 65 72  hread_t *aHolder
4560: 20 3d 20 28 70 74 68 72 65 61 64 5f 74 20 2a 29   = (pthread_t *)
4570: 28 26 61 73 79 6e 63 64 65 62 75 67 29 3b 0a 0a  (&asyncdebug);..
4580: 20 20 2f 2a 20 54 68 65 20 63 6f 64 65 20 69 6e    /* The code in
4590: 20 74 68 69 73 20 27 69 66 6e 64 65 66 20 4e 44   this 'ifndef ND
45a0: 45 42 55 47 27 20 62 6c 6f 63 6b 20 64 65 70 65  EBUG' block depe
45b0: 6e 64 73 20 6f 6e 20 61 20 63 65 72 74 61 69 6e  nds on a certain
45c0: 20 61 6c 69 67 6e 6d 65 6e 74 0a 20 20 20 2a 20   alignment.   * 
45d0: 6f 66 20 74 68 65 20 76 61 72 69 61 62 6c 65 73  of the variables
45e0: 20 69 6e 20 54 65 73 74 41 73 79 6e 63 53 74 61   in TestAsyncSta
45f0: 74 69 63 44 61 74 61 20 61 6e 64 20 54 65 73 74  ticData and Test
4600: 41 73 79 6e 63 44 65 62 75 67 44 61 74 61 2e 20  AsyncDebugData. 
4610: 54 68 65 0a 20 20 20 2a 20 66 6f 6c 6c 6f 77 69  The.   * followi
4620: 6e 67 20 61 73 73 65 72 74 28 29 20 73 74 61 74  ng assert() stat
4630: 65 6d 65 6e 74 73 20 63 68 65 63 6b 20 74 68 61  ements check tha
4640: 74 20 74 68 69 73 20 68 61 73 20 6e 6f 74 20 62  t this has not b
4650: 65 65 6e 20 63 68 61 6e 67 65 64 2e 0a 20 20 20  een changed..   
4660: 2a 0a 20 20 20 2a 20 52 65 61 6c 6c 79 2c 20 74  *.   * Really, t
4670: 68 65 73 65 20 6f 6e 6c 79 20 6e 65 65 64 20 74  hese only need t
4680: 6f 20 62 65 20 72 75 6e 20 6f 6e 63 65 20 61 74  o be run once at
4690: 20 73 74 61 72 74 75 70 20 74 69 6d 65 2e 0a 20   startup time.. 
46a0: 20 20 2a 2f 0a 20 20 61 73 73 65 72 74 28 26 28    */.  assert(&(
46b0: 61 4d 75 74 65 78 5b 30 5d 29 3d 3d 26 61 73 79  aMutex[0])==&asy
46c0: 6e 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20  nc.lockMutex);. 
46d0: 20 61 73 73 65 72 74 28 26 28 61 4d 75 74 65 78   assert(&(aMutex
46e0: 5b 31 5d 29 3d 3d 26 61 73 79 6e 63 2e 71 75 65  [1])==&async.que
46f0: 75 65 4d 75 74 65 78 29 3b 0a 20 20 61 73 73 65  ueMutex);.  asse
4700: 72 74 28 26 28 61 4d 75 74 65 78 5b 32 5d 29 3d  rt(&(aMutex[2])=
4710: 3d 26 61 73 79 6e 63 2e 77 72 69 74 65 72 4d 75  =&async.writerMu
4720: 74 65 78 29 3b 0a 20 20 61 73 73 65 72 74 28 26  tex);.  assert(&
4730: 28 61 48 6f 6c 64 65 72 5b 30 5d 29 3d 3d 26 61  (aHolder[0])==&a
4740: 73 79 6e 63 64 65 62 75 67 2e 6c 6f 63 6b 4d 75  syncdebug.lockMu
4750: 74 65 78 48 6f 6c 64 65 72 29 3b 0a 20 20 61 73  texHolder);.  as
4760: 73 65 72 74 28 26 28 61 48 6f 6c 64 65 72 5b 31  sert(&(aHolder[1
4770: 5d 29 3d 3d 26 61 73 79 6e 63 64 65 62 75 67 2e  ])==&asyncdebug.
4780: 71 75 65 75 65 4d 75 74 65 78 48 6f 6c 64 65 72  queueMutexHolder
4790: 29 3b 0a 20 20 61 73 73 65 72 74 28 26 28 61 48  );.  assert(&(aH
47a0: 6f 6c 64 65 72 5b 32 5d 29 3d 3d 26 61 73 79 6e  older[2])==&asyn
47b0: 63 64 65 62 75 67 2e 77 72 69 74 65 72 4d 75 74  cdebug.writerMut
47c0: 65 78 48 6f 6c 64 65 72 29 3b 0a 0a 20 20 61 73  exHolder);..  as
47d0: 73 65 72 74 28 20 70 74 68 72 65 61 64 5f 73 65  sert( pthread_se
47e0: 6c 66 28 29 21 3d 30 20 29 3b 0a 0a 20 20 66 6f  lf()!=0 );..  fo
47f0: 72 28 69 49 64 78 3d 30 3b 20 69 49 64 78 3c 33  r(iIdx=0; iIdx<3
4800: 3b 20 69 49 64 78 2b 2b 29 7b 0a 20 20 20 20 69  ; iIdx++){.    i
4810: 66 28 20 70 4d 75 74 65 78 3d 3d 26 61 4d 75 74  f( pMutex==&aMut
4820: 65 78 5b 69 49 64 78 5d 20 29 20 62 72 65 61 6b  ex[iIdx] ) break
4830: 3b 0a 0a 20 20 20 20 2f 2a 20 54 68 69 73 20 69  ;..    /* This i
4840: 73 20 74 68 65 20 6b 65 79 20 61 73 73 65 72 74  s the key assert
4850: 28 29 2e 20 48 65 72 65 20 77 65 20 61 72 65 20  (). Here we are 
4860: 63 68 65 63 6b 69 6e 67 20 74 68 61 74 20 69 66  checking that if
4870: 20 74 68 65 20 63 61 6c 6c 65 72 0a 20 20 20 20   the caller.    
4880: 20 2a 20 69 73 20 74 72 79 69 6e 67 20 74 6f 20   * is trying to 
4890: 62 6c 6f 63 6b 20 6f 6e 20 61 73 79 6e 63 2e 77  block on async.w
48a0: 72 69 74 65 72 4d 75 74 65 78 2c 20 6e 65 69 74  riterMutex, neit
48b0: 68 65 72 20 6f 66 20 74 68 65 20 6f 74 68 65 72  her of the other
48c0: 20 74 77 6f 0a 20 20 20 20 20 2a 20 6d 75 74 65   two.     * mute
48d0: 78 20 61 72 65 20 68 65 6c 64 2e 20 49 66 20 74  x are held. If t
48e0: 68 65 20 63 61 6c 6c 65 72 20 69 73 20 74 72 79  he caller is try
48f0: 69 6e 67 20 74 6f 20 62 6c 6f 63 6b 20 6f 6e 20  ing to block on 
4900: 61 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78  async.queueMutex
4910: 2c 0a 20 20 20 20 20 2a 20 6c 6f 63 6b 4d 75 74  ,.     * lockMut
4920: 65 78 20 69 73 20 6e 6f 74 20 68 65 6c 64 2e 0a  ex is not held..
4930: 20 20 20 20 20 2a 2f 0a 20 20 20 20 61 73 73 65       */.    asse
4940: 72 74 28 21 70 74 68 72 65 61 64 5f 65 71 75 61  rt(!pthread_equa
4950: 6c 28 61 48 6f 6c 64 65 72 5b 69 49 64 78 5d 2c  l(aHolder[iIdx],
4960: 20 70 74 68 72 65 61 64 5f 73 65 6c 66 28 29 29   pthread_self())
4970: 29 3b 0a 20 20 7d 0a 20 20 61 73 73 65 72 74 28  );.  }.  assert(
4980: 69 49 64 78 3c 33 29 3b 0a 0a 20 20 72 63 20 3d  iIdx<3);..  rc =
4990: 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c   pthread_mutex_l
49a0: 6f 63 6b 28 70 4d 75 74 65 78 29 3b 0a 20 20 69  ock(pMutex);.  i
49b0: 66 28 20 72 63 3d 3d 30 20 29 7b 0a 20 20 20 20  f( rc==0 ){.    
49c0: 61 73 73 65 72 74 28 61 48 6f 6c 64 65 72 5b 69  assert(aHolder[i
49d0: 49 64 78 5d 3d 3d 30 29 3b 0a 20 20 20 20 61 48  Idx]==0);.    aH
49e0: 6f 6c 64 65 72 5b 69 49 64 78 5d 20 3d 20 70 74  older[iIdx] = pt
49f0: 68 72 65 61 64 5f 73 65 6c 66 28 29 3b 0a 20 20  hread_self();.  
4a00: 7d 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  }.  return rc;.}
4a10: 0a 0a 2f 2a 0a 2a 2a 20 57 72 61 70 70 65 72 20  ../*.** Wrapper 
4a20: 61 72 6f 75 6e 64 20 70 74 68 72 65 61 64 5f 6d  around pthread_m
4a30: 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 29 2e 0a 2a  utex_unlock()..*
4a40: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73 79  /.static int asy
4a50: 6e 63 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28  nc_mutex_unlock(
4a60: 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 20  pthread_mutex_t 
4a70: 2a 70 4d 75 74 65 78 29 7b 0a 20 20 69 6e 74 20  *pMutex){.  int 
4a80: 69 49 64 78 3b 0a 20 20 69 6e 74 20 72 63 3b 0a  iIdx;.  int rc;.
4a90: 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f    pthread_mutex_
4aa0: 74 20 2a 61 4d 75 74 65 78 20 3d 20 28 70 74 68  t *aMutex = (pth
4ab0: 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 2a 29 28  read_mutex_t *)(
4ac0: 26 61 73 79 6e 63 29 3b 0a 20 20 70 74 68 72 65  &async);.  pthre
4ad0: 61 64 5f 74 20 2a 61 48 6f 6c 64 65 72 20 3d 20  ad_t *aHolder = 
4ae0: 28 70 74 68 72 65 61 64 5f 74 20 2a 29 28 26 61  (pthread_t *)(&a
4af0: 73 79 6e 63 64 65 62 75 67 29 3b 0a 0a 20 20 66  syncdebug);..  f
4b00: 6f 72 28 69 49 64 78 3d 30 3b 20 69 49 64 78 3c  or(iIdx=0; iIdx<
4b10: 33 3b 20 69 49 64 78 2b 2b 29 7b 0a 20 20 20 20  3; iIdx++){.    
4b20: 69 66 28 20 70 4d 75 74 65 78 3d 3d 26 61 4d 75  if( pMutex==&aMu
4b30: 74 65 78 5b 69 49 64 78 5d 20 29 20 62 72 65 61  tex[iIdx] ) brea
4b40: 6b 3b 0a 20 20 7d 0a 20 20 61 73 73 65 72 74 28  k;.  }.  assert(
4b50: 69 49 64 78 3c 33 29 3b 0a 0a 20 20 61 73 73 65  iIdx<3);..  asse
4b60: 72 74 28 70 74 68 72 65 61 64 5f 65 71 75 61 6c  rt(pthread_equal
4b70: 28 61 48 6f 6c 64 65 72 5b 69 49 64 78 5d 2c 20  (aHolder[iIdx], 
4b80: 70 74 68 72 65 61 64 5f 73 65 6c 66 28 29 29 29  pthread_self()))
4b90: 3b 0a 20 20 61 48 6f 6c 64 65 72 5b 69 49 64 78  ;.  aHolder[iIdx
4ba0: 5d 20 3d 20 30 3b 0a 20 20 72 63 20 3d 20 70 74  ] = 0;.  rc = pt
4bb0: 68 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f  hread_mutex_unlo
4bc0: 63 6b 28 70 4d 75 74 65 78 29 3b 0a 20 20 61 73  ck(pMutex);.  as
4bd0: 73 65 72 74 28 72 63 3d 3d 30 29 3b 0a 0a 20 20  sert(rc==0);..  
4be0: 72 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 0a  return 0;.}../*.
4bf0: 2a 2a 20 57 72 61 70 70 65 72 20 61 72 6f 75 6e  ** Wrapper aroun
4c00: 64 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f  d pthread_mutex_
4c10: 74 72 79 6c 6f 63 6b 28 29 2e 0a 2a 2f 0a 73 74  trylock()..*/.st
4c20: 61 74 69 63 20 69 6e 74 20 61 73 79 6e 63 5f 6d  atic int async_m
4c30: 75 74 65 78 5f 74 72 79 6c 6f 63 6b 28 70 74 68  utex_trylock(pth
4c40: 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 2a 70 4d  read_mutex_t *pM
4c50: 75 74 65 78 29 7b 0a 20 20 69 6e 74 20 69 49 64  utex){.  int iId
4c60: 78 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 70  x;.  int rc;.  p
4c70: 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 2a  thread_mutex_t *
4c80: 61 4d 75 74 65 78 20 3d 20 28 70 74 68 72 65 61  aMutex = (pthrea
4c90: 64 5f 6d 75 74 65 78 5f 74 20 2a 29 28 26 61 73  d_mutex_t *)(&as
4ca0: 79 6e 63 29 3b 0a 20 20 70 74 68 72 65 61 64 5f  ync);.  pthread_
4cb0: 74 20 2a 61 48 6f 6c 64 65 72 20 3d 20 28 70 74  t *aHolder = (pt
4cc0: 68 72 65 61 64 5f 74 20 2a 29 28 26 61 73 79 6e  hread_t *)(&asyn
4cd0: 63 64 65 62 75 67 29 3b 0a 0a 20 20 66 6f 72 28  cdebug);..  for(
4ce0: 69 49 64 78 3d 30 3b 20 69 49 64 78 3c 33 3b 20  iIdx=0; iIdx<3; 
4cf0: 69 49 64 78 2b 2b 29 7b 0a 20 20 20 20 69 66 28  iIdx++){.    if(
4d00: 20 70 4d 75 74 65 78 3d 3d 26 61 4d 75 74 65 78   pMutex==&aMutex
4d10: 5b 69 49 64 78 5d 20 29 20 62 72 65 61 6b 3b 0a  [iIdx] ) break;.
4d20: 20 20 7d 0a 20 20 61 73 73 65 72 74 28 69 49 64    }.  assert(iId
4d30: 78 3c 33 29 3b 0a 0a 20 20 72 63 20 3d 20 70 74  x<3);..  rc = pt
4d40: 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 72 79 6c  hread_mutex_tryl
4d50: 6f 63 6b 28 70 4d 75 74 65 78 29 3b 0a 20 20 69  ock(pMutex);.  i
4d60: 66 28 20 72 63 3d 3d 30 20 29 7b 0a 20 20 20 20  f( rc==0 ){.    
4d70: 61 73 73 65 72 74 28 61 48 6f 6c 64 65 72 5b 69  assert(aHolder[i
4d80: 49 64 78 5d 3d 3d 30 29 3b 0a 20 20 20 20 61 48  Idx]==0);.    aH
4d90: 6f 6c 64 65 72 5b 69 49 64 78 5d 20 3d 20 70 74  older[iIdx] = pt
4da0: 68 72 65 61 64 5f 73 65 6c 66 28 29 3b 0a 20 20  hread_self();.  
4db0: 7d 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  }.  return rc;.}
4dc0: 0a 0a 2f 2a 0a 2a 2a 20 57 72 61 70 70 65 72 20  ../*.** Wrapper 
4dd0: 61 72 6f 75 6e 64 20 70 74 68 72 65 61 64 5f 63  around pthread_c
4de0: 6f 6e 64 5f 77 61 69 74 28 29 2e 0a 2a 2f 0a 73  ond_wait()..*/.s
4df0: 74 61 74 69 63 20 69 6e 74 20 61 73 79 6e 63 5f  tatic int async_
4e00: 63 6f 6e 64 5f 77 61 69 74 28 70 74 68 72 65 61  cond_wait(pthrea
4e10: 64 5f 63 6f 6e 64 5f 74 20 2a 70 43 6f 6e 64 2c  d_cond_t *pCond,
4e20: 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 74   pthread_mutex_t
4e30: 20 2a 70 4d 75 74 65 78 29 7b 0a 20 20 69 6e 74   *pMutex){.  int
4e40: 20 69 49 64 78 3b 0a 20 20 69 6e 74 20 72 63 3b   iIdx;.  int rc;
4e50: 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78  .  pthread_mutex
4e60: 5f 74 20 2a 61 4d 75 74 65 78 20 3d 20 28 70 74  _t *aMutex = (pt
4e70: 68 72 65 61 64 5f 6d 75 74 65 78 5f 74 20 2a 29  hread_mutex_t *)
4e80: 28 26 61 73 79 6e 63 29 3b 0a 20 20 70 74 68 72  (&async);.  pthr
4e90: 65 61 64 5f 74 20 2a 61 48 6f 6c 64 65 72 20 3d  ead_t *aHolder =
4ea0: 20 28 70 74 68 72 65 61 64 5f 74 20 2a 29 28 26   (pthread_t *)(&
4eb0: 61 73 79 6e 63 64 65 62 75 67 29 3b 0a 0a 20 20  asyncdebug);..  
4ec0: 66 6f 72 28 69 49 64 78 3d 30 3b 20 69 49 64 78  for(iIdx=0; iIdx
4ed0: 3c 33 3b 20 69 49 64 78 2b 2b 29 7b 0a 20 20 20  <3; iIdx++){.   
4ee0: 20 69 66 28 20 70 4d 75 74 65 78 3d 3d 26 61 4d   if( pMutex==&aM
4ef0: 75 74 65 78 5b 69 49 64 78 5d 20 29 20 62 72 65  utex[iIdx] ) bre
4f00: 61 6b 3b 0a 20 20 7d 0a 20 20 61 73 73 65 72 74  ak;.  }.  assert
4f10: 28 69 49 64 78 3c 33 29 3b 0a 0a 20 20 61 73 73  (iIdx<3);..  ass
4f20: 65 72 74 28 70 74 68 72 65 61 64 5f 65 71 75 61  ert(pthread_equa
4f30: 6c 28 61 48 6f 6c 64 65 72 5b 69 49 64 78 5d 2c  l(aHolder[iIdx],
4f40: 70 74 68 72 65 61 64 5f 73 65 6c 66 28 29 29 29  pthread_self()))
4f50: 3b 0a 20 20 61 48 6f 6c 64 65 72 5b 69 49 64 78  ;.  aHolder[iIdx
4f60: 5d 20 3d 20 30 3b 0a 20 20 72 63 20 3d 20 70 74  ] = 0;.  rc = pt
4f70: 68 72 65 61 64 5f 63 6f 6e 64 5f 77 61 69 74 28  hread_cond_wait(
4f80: 70 43 6f 6e 64 2c 20 70 4d 75 74 65 78 29 3b 0a  pCond, pMutex);.
4f90: 20 20 69 66 28 20 72 63 3d 3d 30 20 29 7b 0a 20    if( rc==0 ){. 
4fa0: 20 20 20 61 48 6f 6c 64 65 72 5b 69 49 64 78 5d     aHolder[iIdx]
4fb0: 20 3d 20 70 74 68 72 65 61 64 5f 73 65 6c 66 28   = pthread_self(
4fc0: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
4fd0: 72 63 3b 0a 7d 0a 0a 2f 2a 20 43 61 6c 6c 20 6f  rc;.}../* Call o
4fe0: 75 72 20 61 73 79 6e 63 5f 58 58 20 77 72 61 70  ur async_XX wrap
4ff0: 70 65 72 73 20 69 6e 73 74 65 61 64 20 6f 66 20  pers instead of 
5000: 73 65 6c 65 63 74 65 64 20 70 74 68 72 65 61 64  selected pthread
5010: 5f 58 58 20 66 75 6e 63 74 69 6f 6e 73 20 2a 2f  _XX functions */
5020: 0a 23 64 65 66 69 6e 65 20 70 74 68 72 65 61 64  .#define pthread
5030: 5f 6d 75 74 65 78 5f 6c 6f 63 6b 20 20 20 20 61  _mutex_lock    a
5040: 73 79 6e 63 5f 6d 75 74 65 78 5f 6c 6f 63 6b 0a  sync_mutex_lock.
5050: 23 64 65 66 69 6e 65 20 70 74 68 72 65 61 64 5f  #define pthread_
5060: 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 20 20 61 73  mutex_unlock  as
5070: 79 6e 63 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b  ync_mutex_unlock
5080: 0a 23 64 65 66 69 6e 65 20 70 74 68 72 65 61 64  .#define pthread
5090: 5f 6d 75 74 65 78 5f 74 72 79 6c 6f 63 6b 20 61  _mutex_trylock a
50a0: 73 79 6e 63 5f 6d 75 74 65 78 5f 74 72 79 6c 6f  sync_mutex_trylo
50b0: 63 6b 0a 23 64 65 66 69 6e 65 20 70 74 68 72 65  ck.#define pthre
50c0: 61 64 5f 63 6f 6e 64 5f 77 61 69 74 20 20 20 20  ad_cond_wait    
50d0: 20 61 73 79 6e 63 5f 63 6f 6e 64 5f 77 61 69 74   async_cond_wait
50e0: 0a 0a 23 65 6e 64 69 66 20 20 20 2f 2a 20 21 64  ..#endif   /* !d
50f0: 65 66 69 6e 65 64 28 4e 44 45 42 55 47 29 20 2a  efined(NDEBUG) *
5100: 2f 0a 0a 2f 2a 0a 2a 2a 20 41 64 64 20 61 6e 20  /../*.** Add an 
5110: 65 6e 74 72 79 20 74 6f 20 74 68 65 20 65 6e 64  entry to the end
5120: 20 6f 66 20 74 68 65 20 67 6c 6f 62 61 6c 20 77   of the global w
5130: 72 69 74 65 2d 6f 70 20 6c 69 73 74 2e 20 70 57  rite-op list. pW
5140: 72 69 74 65 20 73 68 6f 75 6c 64 20 70 6f 69 6e  rite should poin
5150: 74 20 0a 2a 2a 20 74 6f 20 61 6e 20 41 73 79 6e  t .** to an Asyn
5160: 63 57 72 69 74 65 20 73 74 72 75 63 74 75 72 65  cWrite structure
5170: 20 61 6c 6c 6f 63 61 74 65 64 20 75 73 69 6e 67   allocated using
5180: 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28   sqlite3_malloc(
5190: 29 2e 20 20 54 68 65 20 77 72 69 74 65 72 0a 2a  ).  The writer.*
51a0: 2a 20 74 68 72 65 61 64 20 77 69 6c 6c 20 63 61  * thread will ca
51b0: 6c 6c 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  ll sqlite3_free(
51c0: 29 20 74 6f 20 66 72 65 65 20 74 68 65 20 73 74  ) to free the st
51d0: 72 75 63 74 75 72 65 20 61 66 74 65 72 20 74 68  ructure after th
51e0: 65 20 73 70 65 63 69 66 69 65 64 0a 2a 2a 20 6f  e specified.** o
51f0: 70 65 72 61 74 69 6f 6e 20 68 61 73 20 62 65 65  peration has bee
5200: 6e 20 63 6f 6d 70 6c 65 74 65 64 2e 0a 2a 2a 0a  n completed..**.
5210: 2a 2a 20 4f 6e 63 65 20 61 6e 20 41 73 79 6e 63  ** Once an Async
5220: 57 72 69 74 65 20 73 74 72 75 63 74 75 72 65 20  Write structure 
5230: 68 61 73 20 62 65 65 6e 20 61 64 64 65 64 20 74  has been added t
5240: 6f 20 74 68 65 20 6c 69 73 74 2c 20 69 74 20 62  o the list, it b
5250: 65 63 6f 6d 65 73 20 74 68 65 0a 2a 2a 20 70 72  ecomes the.** pr
5260: 6f 70 65 72 74 79 20 6f 66 20 74 68 65 20 77 72  operty of the wr
5270: 69 74 65 72 20 74 68 72 65 61 64 20 61 6e 64 20  iter thread and 
5280: 6d 75 73 74 20 6e 6f 74 20 62 65 20 72 65 61 64  must not be read
5290: 20 6f 72 20 6d 6f 64 69 66 69 65 64 20 62 79 20   or modified by 
52a0: 74 68 65 0a 2a 2a 20 63 61 6c 6c 65 72 2e 20 20  the.** caller.  
52b0: 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20  .*/.static void 
52c0: 61 64 64 41 73 79 6e 63 57 72 69 74 65 28 41 73  addAsyncWrite(As
52d0: 79 6e 63 57 72 69 74 65 20 2a 70 57 72 69 74 65  yncWrite *pWrite
52e0: 29 7b 0a 20 20 2f 2a 20 57 65 20 6d 75 73 74 20  ){.  /* We must 
52f0: 68 6f 6c 64 20 74 68 65 20 71 75 65 75 65 20 6d  hold the queue m
5300: 75 74 65 78 20 69 6e 20 6f 72 64 65 72 20 74 6f  utex in order to
5310: 20 6d 6f 64 69 66 79 20 74 68 65 20 71 75 65 75   modify the queu
5320: 65 20 70 6f 69 6e 74 65 72 73 20 2a 2f 0a 20 20  e pointers */.  
5330: 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c 6f  pthread_mutex_lo
5340: 63 6b 28 26 61 73 79 6e 63 2e 71 75 65 75 65 4d  ck(&async.queueM
5350: 75 74 65 78 29 3b 0a 0a 20 20 2f 2a 20 41 64 64  utex);..  /* Add
5360: 20 74 68 65 20 72 65 63 6f 72 64 20 74 6f 20 74   the record to t
5370: 68 65 20 65 6e 64 20 6f 66 20 74 68 65 20 77 72  he end of the wr
5380: 69 74 65 2d 6f 70 20 71 75 65 75 65 20 2a 2f 0a  ite-op queue */.
5390: 20 20 61 73 73 65 72 74 28 20 21 70 57 72 69 74    assert( !pWrit
53a0: 65 2d 3e 70 4e 65 78 74 20 29 3b 0a 20 20 69 66  e->pNext );.  if
53b0: 28 20 61 73 79 6e 63 2e 70 51 75 65 75 65 4c 61  ( async.pQueueLa
53c0: 73 74 20 29 7b 0a 20 20 20 20 61 73 73 65 72 74  st ){.    assert
53d0: 28 20 61 73 79 6e 63 2e 70 51 75 65 75 65 46 69  ( async.pQueueFi
53e0: 72 73 74 20 29 3b 0a 20 20 20 20 61 73 79 6e 63  rst );.    async
53f0: 2e 70 51 75 65 75 65 4c 61 73 74 2d 3e 70 4e 65  .pQueueLast->pNe
5400: 78 74 20 3d 20 70 57 72 69 74 65 3b 0a 20 20 7d  xt = pWrite;.  }
5410: 65 6c 73 65 7b 0a 20 20 20 20 61 73 79 6e 63 2e  else{.    async.
5420: 70 51 75 65 75 65 46 69 72 73 74 20 3d 20 70 57  pQueueFirst = pW
5430: 72 69 74 65 3b 0a 20 20 7d 0a 20 20 61 73 79 6e  rite;.  }.  asyn
5440: 63 2e 70 51 75 65 75 65 4c 61 73 74 20 3d 20 70  c.pQueueLast = p
5450: 57 72 69 74 65 3b 0a 20 20 41 53 59 4e 43 5f 54  Write;.  ASYNC_T
5460: 52 41 43 45 28 28 22 50 55 53 48 20 25 70 20 28  RACE(("PUSH %p (
5470: 25 73 20 25 73 20 25 64 29 5c 6e 22 2c 20 70 57  %s %s %d)\n", pW
5480: 72 69 74 65 2c 20 61 7a 4f 70 63 6f 64 65 4e 61  rite, azOpcodeNa
5490: 6d 65 5b 70 57 72 69 74 65 2d 3e 6f 70 5d 2c 0a  me[pWrite->op],.
54a0: 20 20 20 20 20 20 20 20 20 70 57 72 69 74 65 2d           pWrite-
54b0: 3e 70 46 69 6c 65 44 61 74 61 20 3f 20 70 57 72  >pFileData ? pWr
54c0: 69 74 65 2d 3e 70 46 69 6c 65 44 61 74 61 2d 3e  ite->pFileData->
54d0: 7a 4e 61 6d 65 20 3a 20 22 2d 22 2c 20 70 57 72  zName : "-", pWr
54e0: 69 74 65 2d 3e 69 4f 66 66 73 65 74 29 29 3b 0a  ite->iOffset));.
54f0: 0a 20 20 69 66 28 20 70 57 72 69 74 65 2d 3e 6f  .  if( pWrite->o
5500: 70 3d 3d 41 53 59 4e 43 5f 43 4c 4f 53 45 20 29  p==ASYNC_CLOSE )
5510: 7b 0a 20 20 20 20 61 73 79 6e 63 2e 6e 46 69 6c  {.    async.nFil
5520: 65 2d 2d 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 44  e--;.  }..  /* D
5530: 72 6f 70 20 74 68 65 20 71 75 65 75 65 20 6d 75  rop the queue mu
5540: 74 65 78 20 2a 2f 0a 20 20 70 74 68 72 65 61 64  tex */.  pthread
5550: 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61  _mutex_unlock(&a
5560: 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29  sync.queueMutex)
5570: 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 77 72 69 74  ;..  /* The writ
5580: 65 72 20 74 68 72 65 61 64 20 6d 69 67 68 74 20  er thread might 
5590: 68 61 76 65 20 62 65 65 6e 20 69 64 6c 65 20 62  have been idle b
55a0: 65 63 61 75 73 65 20 74 68 65 72 65 20 77 61 73  ecause there was
55b0: 20 6e 6f 74 68 69 6e 67 0a 20 20 2a 2a 20 6f 6e   nothing.  ** on
55c0: 20 74 68 65 20 77 72 69 74 65 2d 6f 70 20 71 75   the write-op qu
55d0: 65 75 65 20 66 6f 72 20 69 74 20 74 6f 20 64 6f  eue for it to do
55e0: 2e 20 20 53 6f 20 77 61 6b 65 20 69 74 20 75 70  .  So wake it up
55f0: 2e 20 2a 2f 0a 20 20 70 74 68 72 65 61 64 5f 63  . */.  pthread_c
5600: 6f 6e 64 5f 73 69 67 6e 61 6c 28 26 61 73 79 6e  ond_signal(&asyn
5610: 63 2e 71 75 65 75 65 53 69 67 6e 61 6c 29 3b 0a  c.queueSignal);.
5620: 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6e 63 72 65 6d 65  }../*.** Increme
5630: 6e 74 20 61 73 79 6e 63 2e 6e 46 69 6c 65 20 69  nt async.nFile i
5640: 6e 20 61 20 74 68 72 65 61 64 2d 73 61 66 65 20  n a thread-safe 
5650: 6d 61 6e 6e 65 72 2e 0a 2a 2f 0a 73 74 61 74 69  manner..*/.stati
5660: 63 20 76 6f 69 64 20 69 6e 63 72 4f 70 65 6e 46  c void incrOpenF
5670: 69 6c 65 43 6f 75 6e 74 28 29 7b 0a 20 20 2f 2a  ileCount(){.  /*
5680: 20 57 65 20 6d 75 73 74 20 68 6f 6c 64 20 74 68   We must hold th
5690: 65 20 71 75 65 75 65 20 6d 75 74 65 78 20 69 6e  e queue mutex in
56a0: 20 6f 72 64 65 72 20 74 6f 20 6d 6f 64 69 66 79   order to modify
56b0: 20 61 73 79 6e 63 2e 6e 46 69 6c 65 20 2a 2f 0a   async.nFile */.
56c0: 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f    pthread_mutex_
56d0: 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 71 75 65 75  lock(&async.queu
56e0: 65 4d 75 74 65 78 29 3b 0a 20 20 69 66 28 20 61  eMutex);.  if( a
56f0: 73 79 6e 63 2e 6e 46 69 6c 65 3d 3d 30 20 29 7b  sync.nFile==0 ){
5700: 0a 20 20 20 20 61 73 79 6e 63 2e 69 6f 45 72 72  .    async.ioErr
5710: 6f 72 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  or = SQLITE_OK;.
5720: 20 20 7d 0a 20 20 61 73 79 6e 63 2e 6e 46 69 6c    }.  async.nFil
5730: 65 2b 2b 3b 0a 20 20 70 74 68 72 65 61 64 5f 6d  e++;.  pthread_m
5740: 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79  utex_unlock(&asy
5750: 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a  nc.queueMutex);.
5760: 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73  }../*.** This is
5770: 20 61 20 75 74 69 6c 69 74 79 20 66 75 6e 63 74   a utility funct
5780: 69 6f 6e 20 74 6f 20 61 6c 6c 6f 63 61 74 65 20  ion to allocate 
5790: 61 6e 64 20 70 6f 70 75 6c 61 74 65 20 61 20 6e  and populate a n
57a0: 65 77 20 41 73 79 6e 63 57 72 69 74 65 0a 2a 2a  ew AsyncWrite.**
57b0: 20 73 74 72 75 63 74 75 72 65 20 61 6e 64 20 69   structure and i
57c0: 6e 73 65 72 74 20 69 74 20 28 76 69 61 20 61 64  nsert it (via ad
57d0: 64 41 73 79 6e 63 57 72 69 74 65 28 29 20 29 20  dAsyncWrite() ) 
57e0: 69 6e 74 6f 20 74 68 65 20 67 6c 6f 62 61 6c 20  into the global 
57f0: 6c 69 73 74 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  list..*/.static 
5800: 69 6e 74 20 61 64 64 4e 65 77 41 73 79 6e 63 57  int addNewAsyncW
5810: 72 69 74 65 28 0a 20 20 41 73 79 6e 63 46 69 6c  rite(.  AsyncFil
5820: 65 44 61 74 61 20 2a 70 46 69 6c 65 44 61 74 61  eData *pFileData
5830: 2c 20 0a 20 20 69 6e 74 20 6f 70 2c 20 0a 20 20  , .  int op, .  
5840: 69 36 34 20 69 4f 66 66 73 65 74 2c 20 0a 20 20  i64 iOffset, .  
5850: 69 6e 74 20 6e 42 79 74 65 2c 0a 20 20 63 6f 6e  int nByte,.  con
5860: 73 74 20 63 68 61 72 20 2a 7a 42 79 74 65 0a 29  st char *zByte.)
5870: 7b 0a 20 20 41 73 79 6e 63 57 72 69 74 65 20 2a  {.  AsyncWrite *
5880: 70 3b 0a 20 20 69 66 28 20 6f 70 21 3d 41 53 59  p;.  if( op!=ASY
5890: 4e 43 5f 43 4c 4f 53 45 20 26 26 20 61 73 79 6e  NC_CLOSE && asyn
58a0: 63 2e 69 6f 45 72 72 6f 72 20 29 7b 0a 20 20 20  c.ioError ){.   
58b0: 20 72 65 74 75 72 6e 20 61 73 79 6e 63 2e 69 6f   return async.io
58c0: 45 72 72 6f 72 3b 0a 20 20 7d 0a 20 20 70 20 3d  Error;.  }.  p =
58d0: 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28   sqlite3_malloc(
58e0: 73 69 7a 65 6f 66 28 41 73 79 6e 63 57 72 69 74  sizeof(AsyncWrit
58f0: 65 29 20 2b 20 28 7a 42 79 74 65 3f 6e 42 79 74  e) + (zByte?nByt
5900: 65 3a 30 29 29 3b 0a 20 20 69 66 28 20 21 70 20  e:0));.  if( !p 
5910: 29 7b 0a 20 20 20 20 2f 2a 20 54 68 65 20 75 70  ){.    /* The up
5920: 70 65 72 20 6c 61 79 65 72 20 64 6f 65 73 20 6e  per layer does n
5930: 6f 74 20 65 78 70 65 63 74 20 6f 70 65 72 61 74  ot expect operat
5940: 69 6f 6e 73 20 6c 69 6b 65 20 4f 73 57 72 69 74  ions like OsWrit
5950: 65 28 29 20 74 6f 0a 20 20 20 20 2a 2a 20 72 65  e() to.    ** re
5960: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45  turn SQLITE_NOME
5970: 4d 2e 20 54 68 69 73 20 69 73 20 70 61 72 74 6c  M. This is partl
5980: 79 20 62 65 63 61 75 73 65 20 75 6e 64 65 72 20  y because under 
5990: 6e 6f 72 6d 61 6c 20 63 6f 6e 64 69 74 69 6f 6e  normal condition
59a0: 73 0a 20 20 20 20 2a 2a 20 53 51 4c 69 74 65 20  s.    ** SQLite 
59b0: 69 73 20 72 65 71 75 69 72 65 64 20 74 6f 20 64  is required to d
59c0: 6f 20 72 6f 6c 6c 62 61 63 6b 20 77 69 74 68 6f  o rollback witho
59d0: 75 74 20 63 61 6c 6c 69 6e 67 20 6d 61 6c 6c 6f  ut calling mallo
59e0: 63 28 29 2e 20 53 6f 0a 20 20 20 20 2a 2a 20 69  c(). So.    ** i
59f0: 66 20 6d 61 6c 6c 6f 63 28 29 20 66 61 69 6c 73  f malloc() fails
5a00: 20 68 65 72 65 2c 20 74 72 65 61 74 20 69 74 20   here, treat it 
5a10: 61 73 20 61 6e 20 49 2f 4f 20 65 72 72 6f 72 2e  as an I/O error.
5a20: 20 54 68 65 20 61 62 6f 76 65 0a 20 20 20 20 2a   The above.    *
5a30: 2a 20 6c 61 79 65 72 20 6b 6e 6f 77 73 20 68 6f  * layer knows ho
5a40: 77 20 74 6f 20 68 61 6e 64 6c 65 20 74 68 61 74  w to handle that
5a50: 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20 72 65 74  ..    */.    ret
5a60: 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  urn SQLITE_IOERR
5a70: 3b 0a 20 20 7d 0a 20 20 70 2d 3e 6f 70 20 3d 20  ;.  }.  p->op = 
5a80: 6f 70 3b 0a 20 20 70 2d 3e 69 4f 66 66 73 65 74  op;.  p->iOffset
5a90: 20 3d 20 69 4f 66 66 73 65 74 3b 0a 20 20 70 2d   = iOffset;.  p-
5aa0: 3e 6e 42 79 74 65 20 3d 20 6e 42 79 74 65 3b 0a  >nByte = nByte;.
5ab0: 20 20 70 2d 3e 70 46 69 6c 65 44 61 74 61 20 3d    p->pFileData =
5ac0: 20 70 46 69 6c 65 44 61 74 61 3b 0a 20 20 70 2d   pFileData;.  p-
5ad0: 3e 70 4e 65 78 74 20 3d 20 30 3b 0a 20 20 69 66  >pNext = 0;.  if
5ae0: 28 20 7a 42 79 74 65 20 29 7b 0a 20 20 20 20 70  ( zByte ){.    p
5af0: 2d 3e 7a 42 75 66 20 3d 20 28 63 68 61 72 20 2a  ->zBuf = (char *
5b00: 29 26 70 5b 31 5d 3b 0a 20 20 20 20 6d 65 6d 63  )&p[1];.    memc
5b10: 70 79 28 70 2d 3e 7a 42 75 66 2c 20 7a 42 79 74  py(p->zBuf, zByt
5b20: 65 2c 20 6e 42 79 74 65 29 3b 0a 20 20 7d 65 6c  e, nByte);.  }el
5b30: 73 65 7b 0a 20 20 20 20 70 2d 3e 7a 42 75 66 20  se{.    p->zBuf 
5b40: 3d 20 30 3b 0a 20 20 7d 0a 20 20 61 64 64 41 73  = 0;.  }.  addAs
5b50: 79 6e 63 57 72 69 74 65 28 70 29 3b 0a 20 20 72  yncWrite(p);.  r
5b60: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
5b70: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20  .}../*.** Close 
5b80: 74 68 65 20 66 69 6c 65 2e 20 54 68 69 73 20 6a  the file. This j
5b90: 75 73 74 20 61 64 64 73 20 61 6e 20 65 6e 74 72  ust adds an entr
5ba0: 79 20 74 6f 20 74 68 65 20 77 72 69 74 65 2d 6f  y to the write-o
5bb0: 70 20 6c 69 73 74 2c 20 74 68 65 20 66 69 6c 65  p list, the file
5bc0: 20 69 73 0a 2a 2a 20 6e 6f 74 20 61 63 74 75 61   is.** not actua
5bd0: 6c 6c 79 20 63 6c 6f 73 65 64 2e 0a 2a 2f 0a 73  lly closed..*/.s
5be0: 74 61 74 69 63 20 69 6e 74 20 61 73 79 6e 63 43  tatic int asyncC
5bf0: 6c 6f 73 65 28 73 71 6c 69 74 65 33 5f 66 69 6c  lose(sqlite3_fil
5c00: 65 20 2a 70 46 69 6c 65 29 7b 0a 20 20 41 73 79  e *pFile){.  Asy
5c10: 6e 63 46 69 6c 65 44 61 74 61 20 2a 70 20 3d 20  ncFileData *p = 
5c20: 28 28 41 73 79 6e 63 46 69 6c 65 20 2a 29 70 46  ((AsyncFile *)pF
5c30: 69 6c 65 29 2d 3e 70 44 61 74 61 3b 0a 0a 20 20  ile)->pData;..  
5c40: 2f 2a 20 55 6e 6c 6f 63 6b 20 74 68 65 20 66 69  /* Unlock the fi
5c50: 6c 65 2c 20 69 66 20 69 74 20 69 73 20 6c 6f 63  le, if it is loc
5c60: 6b 65 64 20 2a 2f 0a 20 20 70 74 68 72 65 61 64  ked */.  pthread
5c70: 5f 6d 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79  _mutex_lock(&asy
5c80: 6e 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20  nc.lockMutex);. 
5c90: 20 70 2d 3e 6c 6f 63 6b 2e 65 4c 6f 63 6b 20 3d   p->lock.eLock =
5ca0: 20 30 3b 0a 20 20 70 74 68 72 65 61 64 5f 6d 75   0;.  pthread_mu
5cb0: 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e  tex_unlock(&asyn
5cc0: 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 0a 20  c.lockMutex);.. 
5cd0: 20 61 64 64 41 73 79 6e 63 57 72 69 74 65 28 26   addAsyncWrite(&
5ce0: 70 2d 3e 63 6c 6f 73 65 29 3b 0a 20 20 72 65 74  p->close);.  ret
5cf0: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
5d00: 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e  ../*.** Implemen
5d10: 74 61 74 69 6f 6e 20 6f 66 20 73 71 6c 69 74 65  tation of sqlite
5d20: 33 4f 73 57 72 69 74 65 28 29 20 66 6f 72 20 61  3OsWrite() for a
5d30: 73 79 6e 63 68 72 6f 6e 6f 75 73 20 66 69 6c 65  synchronous file
5d40: 73 2e 20 49 6e 73 74 65 61 64 20 6f 66 20 0a 2a  s. Instead of .*
5d50: 2a 20 77 72 69 74 69 6e 67 20 74 6f 20 74 68 65  * writing to the
5d60: 20 75 6e 64 65 72 6c 79 69 6e 67 20 66 69 6c 65   underlying file
5d70: 2c 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  , this function 
5d80: 61 64 64 73 20 61 6e 20 65 6e 74 72 79 20 74 6f  adds an entry to
5d90: 20 74 68 65 20 65 6e 64 20 6f 66 0a 2a 2a 20 74   the end of.** t
5da0: 68 65 20 67 6c 6f 62 61 6c 20 41 73 79 6e 63 57  he global AsyncW
5db0: 72 69 74 65 20 6c 69 73 74 2e 20 45 69 74 68 65  rite list. Eithe
5dc0: 72 20 53 51 4c 49 54 45 5f 4f 4b 20 6f 72 20 53  r SQLITE_OK or S
5dd0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 20 6d 61 79 20  QLITE_NOMEM may 
5de0: 62 65 0a 2a 2a 20 72 65 74 75 72 6e 65 64 2e 0a  be.** returned..
5df0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73  */.static int as
5e00: 79 6e 63 57 72 69 74 65 28 73 71 6c 69 74 65 33  yncWrite(sqlite3
5e10: 5f 66 69 6c 65 20 2a 70 46 69 6c 65 2c 20 63 6f  _file *pFile, co
5e20: 6e 73 74 20 76 6f 69 64 20 2a 70 42 75 66 2c 20  nst void *pBuf, 
5e30: 69 6e 74 20 61 6d 74 2c 20 69 36 34 20 69 4f 66  int amt, i64 iOf
5e40: 66 29 7b 0a 20 20 41 73 79 6e 63 46 69 6c 65 44  f){.  AsyncFileD
5e50: 61 74 61 20 2a 70 20 3d 20 28 28 41 73 79 6e 63  ata *p = ((Async
5e60: 46 69 6c 65 20 2a 29 70 46 69 6c 65 29 2d 3e 70  File *)pFile)->p
5e70: 44 61 74 61 3b 0a 20 20 72 65 74 75 72 6e 20 61  Data;.  return a
5e80: 64 64 4e 65 77 41 73 79 6e 63 57 72 69 74 65 28  ddNewAsyncWrite(
5e90: 70 2c 20 41 53 59 4e 43 5f 57 52 49 54 45 2c 20  p, ASYNC_WRITE, 
5ea0: 69 4f 66 66 2c 20 61 6d 74 2c 20 70 42 75 66 29  iOff, amt, pBuf)
5eb0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 61 64 20  ;.}../*.** Read 
5ec0: 64 61 74 61 20 66 72 6f 6d 20 74 68 65 20 66 69  data from the fi
5ed0: 6c 65 2e 20 46 69 72 73 74 20 77 65 20 72 65 61  le. First we rea
5ee0: 64 20 66 72 6f 6d 20 74 68 65 20 66 69 6c 65 73  d from the files
5ef0: 79 73 74 65 6d 2c 20 74 68 65 6e 20 61 64 6a 75  ystem, then adju
5f00: 73 74 20 0a 2a 2a 20 74 68 65 20 63 6f 6e 74 65  st .** the conte
5f10: 6e 74 73 20 6f 66 20 74 68 65 20 62 75 66 66 65  nts of the buffe
5f20: 72 20 62 61 73 65 64 20 6f 6e 20 41 53 59 4e 43  r based on ASYNC
5f30: 5f 57 52 49 54 45 20 6f 70 65 72 61 74 69 6f 6e  _WRITE operation
5f40: 73 20 69 6e 20 74 68 65 20 0a 2a 2a 20 77 72 69  s in the .** wri
5f50: 74 65 2d 6f 70 20 71 75 65 75 65 2e 0a 2a 2a 0a  te-op queue..**.
5f60: 2a 2a 20 54 68 69 73 20 6d 65 74 68 6f 64 20 68  ** This method h
5f70: 6f 6c 64 73 20 74 68 65 20 6d 75 74 65 78 20 66  olds the mutex f
5f80: 72 6f 6d 20 73 74 61 72 74 20 74 6f 20 66 69 6e  rom start to fin
5f90: 69 73 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ish..*/.static i
5fa0: 6e 74 20 61 73 79 6e 63 52 65 61 64 28 73 71 6c  nt asyncRead(sql
5fb0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 46 69 6c 65  ite3_file *pFile
5fc0: 2c 20 76 6f 69 64 20 2a 7a 4f 75 74 2c 20 69 6e  , void *zOut, in
5fd0: 74 20 69 41 6d 74 2c 20 69 36 34 20 69 4f 66 66  t iAmt, i64 iOff
5fe0: 73 65 74 29 7b 0a 20 20 41 73 79 6e 63 46 69 6c  set){.  AsyncFil
5ff0: 65 44 61 74 61 20 2a 70 20 3d 20 28 28 41 73 79  eData *p = ((Asy
6000: 6e 63 46 69 6c 65 20 2a 29 70 46 69 6c 65 29 2d  ncFile *)pFile)-
6010: 3e 70 44 61 74 61 3b 0a 20 20 69 6e 74 20 72 63  >pData;.  int rc
6020: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
6030: 69 36 34 20 66 69 6c 65 73 69 7a 65 3b 0a 20 20  i64 filesize;.  
6040: 69 6e 74 20 6e 52 65 61 64 3b 0a 20 20 73 71 6c  int nRead;.  sql
6050: 69 74 65 33 5f 66 69 6c 65 20 2a 70 42 61 73 65  ite3_file *pBase
6060: 20 3d 20 70 2d 3e 70 42 61 73 65 52 65 61 64 3b   = p->pBaseRead;
6070: 0a 0a 20 20 2f 2a 20 47 72 61 62 20 74 68 65 20  ..  /* Grab the 
6080: 77 72 69 74 65 20 71 75 65 75 65 20 6d 75 74 65  write queue mute
6090: 78 20 66 6f 72 20 74 68 65 20 64 75 72 61 74 69  x for the durati
60a0: 6f 6e 20 6f 66 20 74 68 65 20 63 61 6c 6c 20 2a  on of the call *
60b0: 2f 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65  /.  pthread_mute
60c0: 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 71 75  x_lock(&async.qu
60d0: 65 75 65 4d 75 74 65 78 29 3b 0a 0a 20 20 2f 2a  eueMutex);..  /*
60e0: 20 49 66 20 61 6e 20 49 2f 4f 20 65 72 72 6f 72   If an I/O error
60f0: 20 68 61 73 20 70 72 65 76 69 6f 75 73 6c 79 20   has previously 
6100: 6f 63 63 75 72 72 65 64 20 69 6e 20 74 68 69 73  occurred in this
6110: 20 76 69 72 74 75 61 6c 20 66 69 6c 65 20 0a 20   virtual file . 
6120: 20 2a 2a 20 73 79 73 74 65 6d 2c 20 74 68 65 6e   ** system, then
6130: 20 61 6c 6c 20 73 75 62 73 65 71 75 65 6e 74 20   all subsequent 
6140: 6f 70 65 72 61 74 69 6f 6e 73 20 66 61 69 6c 2e  operations fail.
6150: 0a 20 20 2a 2f 0a 20 20 69 66 28 20 61 73 79 6e  .  */.  if( asyn
6160: 63 2e 69 6f 45 72 72 6f 72 21 3d 53 51 4c 49 54  c.ioError!=SQLIT
6170: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d  E_OK ){.    rc =
6180: 20 61 73 79 6e 63 2e 69 6f 45 72 72 6f 72 3b 0a   async.ioError;.
6190: 20 20 20 20 67 6f 74 6f 20 61 73 79 6e 63 72 65      goto asyncre
61a0: 61 64 5f 6f 75 74 3b 0a 20 20 7d 0a 0a 20 20 69  ad_out;.  }..  i
61b0: 66 28 20 70 42 61 73 65 2d 3e 70 4d 65 74 68 6f  f( pBase->pMetho
61c0: 64 73 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 73  ds ){.    rc = s
61d0: 71 6c 69 74 65 33 4f 73 46 69 6c 65 53 69 7a 65  qlite3OsFileSize
61e0: 28 70 42 61 73 65 2c 20 26 66 69 6c 65 73 69 7a  (pBase, &filesiz
61f0: 65 29 3b 0a 20 20 20 20 69 66 28 20 72 63 21 3d  e);.    if( rc!=
6200: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
6210: 20 20 20 67 6f 74 6f 20 61 73 79 6e 63 72 65 61     goto asyncrea
6220: 64 5f 6f 75 74 3b 0a 20 20 20 20 7d 0a 20 20 20  d_out;.    }.   
6230: 20 6e 52 65 61 64 20 3d 20 4d 49 4e 28 66 69 6c   nRead = MIN(fil
6240: 65 73 69 7a 65 20 2d 20 69 4f 66 66 73 65 74 2c  esize - iOffset,
6250: 20 69 41 6d 74 29 3b 0a 20 20 20 20 69 66 28 20   iAmt);.    if( 
6260: 6e 52 65 61 64 3e 30 20 29 7b 0a 20 20 20 20 20  nRead>0 ){.     
6270: 20 72 63 20 3d 20 73 71 6c 69 74 65 33 4f 73 52   rc = sqlite3OsR
6280: 65 61 64 28 70 42 61 73 65 2c 20 7a 4f 75 74 2c  ead(pBase, zOut,
6290: 20 6e 52 65 61 64 2c 20 69 4f 66 66 73 65 74 29   nRead, iOffset)
62a0: 3b 0a 20 20 20 20 20 20 41 53 59 4e 43 5f 54 52  ;.      ASYNC_TR
62b0: 41 43 45 28 28 22 52 45 41 44 20 25 73 20 25 64  ACE(("READ %s %d
62c0: 20 62 79 74 65 73 20 61 74 20 25 64 5c 6e 22 2c   bytes at %d\n",
62d0: 20 70 2d 3e 7a 4e 61 6d 65 2c 20 6e 52 65 61 64   p->zName, nRead
62e0: 2c 20 69 4f 66 66 73 65 74 29 29 3b 0a 20 20 20  , iOffset));.   
62f0: 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72 63   }.  }..  if( rc
6300: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
6310: 20 20 20 41 73 79 6e 63 57 72 69 74 65 20 2a 70     AsyncWrite *p
6320: 57 72 69 74 65 3b 0a 20 20 20 20 63 68 61 72 20  Write;.    char 
6330: 2a 7a 4e 61 6d 65 20 3d 20 70 2d 3e 7a 4e 61 6d  *zName = p->zNam
6340: 65 3b 0a 0a 20 20 20 20 66 6f 72 28 70 57 72 69  e;..    for(pWri
6350: 74 65 3d 61 73 79 6e 63 2e 70 51 75 65 75 65 46  te=async.pQueueF
6360: 69 72 73 74 3b 20 70 57 72 69 74 65 3b 20 70 57  irst; pWrite; pW
6370: 72 69 74 65 20 3d 20 70 57 72 69 74 65 2d 3e 70  rite = pWrite->p
6380: 4e 65 78 74 29 7b 0a 20 20 20 20 20 20 69 66 28  Next){.      if(
6390: 20 70 57 72 69 74 65 2d 3e 6f 70 3d 3d 41 53 59   pWrite->op==ASY
63a0: 4e 43 5f 57 52 49 54 45 20 26 26 20 70 57 72 69  NC_WRITE && pWri
63b0: 74 65 2d 3e 70 46 69 6c 65 44 61 74 61 2d 3e 7a  te->pFileData->z
63c0: 4e 61 6d 65 3d 3d 7a 4e 61 6d 65 20 29 7b 0a 20  Name==zName ){. 
63d0: 20 20 20 20 20 20 20 69 6e 74 20 69 42 65 67 69         int iBegi
63e0: 6e 4f 75 74 20 3d 20 28 70 57 72 69 74 65 2d 3e  nOut = (pWrite->
63f0: 69 4f 66 66 73 65 74 2d 69 4f 66 66 73 65 74 29  iOffset-iOffset)
6400: 3b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 69 42  ;.        int iB
6410: 65 67 69 6e 49 6e 20 3d 20 2d 69 42 65 67 69 6e  eginIn = -iBegin
6420: 4f 75 74 3b 0a 20 20 20 20 20 20 20 20 69 6e 74  Out;.        int
6430: 20 6e 43 6f 70 79 3b 0a 0a 20 20 20 20 20 20 20   nCopy;..       
6440: 20 69 66 28 20 69 42 65 67 69 6e 49 6e 3c 30 20   if( iBeginIn<0 
6450: 29 20 69 42 65 67 69 6e 49 6e 20 3d 20 30 3b 0a  ) iBeginIn = 0;.
6460: 20 20 20 20 20 20 20 20 69 66 28 20 69 42 65 67          if( iBeg
6470: 69 6e 4f 75 74 3c 30 20 29 20 69 42 65 67 69 6e  inOut<0 ) iBegin
6480: 4f 75 74 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  Out = 0;.       
6490: 20 6e 43 6f 70 79 20 3d 20 4d 49 4e 28 70 57 72   nCopy = MIN(pWr
64a0: 69 74 65 2d 3e 6e 42 79 74 65 2d 69 42 65 67 69  ite->nByte-iBegi
64b0: 6e 49 6e 2c 20 69 41 6d 74 2d 69 42 65 67 69 6e  nIn, iAmt-iBegin
64c0: 4f 75 74 29 3b 0a 0a 20 20 20 20 20 20 20 20 69  Out);..        i
64d0: 66 28 20 6e 43 6f 70 79 3e 30 20 29 7b 0a 20 20  f( nCopy>0 ){.  
64e0: 20 20 20 20 20 20 20 20 6d 65 6d 63 70 79 28 26          memcpy(&
64f0: 28 28 63 68 61 72 20 2a 29 7a 4f 75 74 29 5b 69  ((char *)zOut)[i
6500: 42 65 67 69 6e 4f 75 74 5d 2c 20 26 70 57 72 69  BeginOut], &pWri
6510: 74 65 2d 3e 7a 42 75 66 5b 69 42 65 67 69 6e 49  te->zBuf[iBeginI
6520: 6e 5d 2c 20 6e 43 6f 70 79 29 3b 0a 20 20 20 20  n], nCopy);.    
6530: 20 20 20 20 20 20 41 53 59 4e 43 5f 54 52 41 43        ASYNC_TRAC
6540: 45 28 28 22 4f 56 45 52 52 45 41 44 20 25 64 20  E(("OVERREAD %d 
6550: 62 79 74 65 73 20 61 74 20 25 64 5c 6e 22 2c 20  bytes at %d\n", 
6560: 6e 43 6f 70 79 2c 20 69 42 65 67 69 6e 4f 75 74  nCopy, iBeginOut
6570: 2b 69 4f 66 66 73 65 74 29 29 3b 0a 20 20 20 20  +iOffset));.    
6580: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20      }.      }.  
6590: 20 20 7d 0a 20 20 7d 0a 0a 61 73 79 6e 63 72 65    }.  }..asyncre
65a0: 61 64 5f 6f 75 74 3a 0a 20 20 70 74 68 72 65 61  ad_out:.  pthrea
65b0: 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26  d_mutex_unlock(&
65c0: 61 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78  async.queueMutex
65d0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
65e0: 7d 0a 0a 2f 2a 0a 2a 2a 20 54 72 75 6e 63 61 74  }../*.** Truncat
65f0: 65 20 74 68 65 20 66 69 6c 65 20 74 6f 20 6e 42  e the file to nB
6600: 79 74 65 20 62 79 74 65 73 20 69 6e 20 6c 65 6e  yte bytes in len
6610: 67 74 68 2e 20 54 68 69 73 20 6a 75 73 74 20 61  gth. This just a
6620: 64 64 73 20 61 6e 20 65 6e 74 72 79 20 74 6f 20  dds an entry to 
6630: 0a 2a 2a 20 74 68 65 20 77 72 69 74 65 2d 6f 70  .** the write-op
6640: 20 6c 69 73 74 2c 20 6e 6f 20 49 4f 20 61 63 74   list, no IO act
6650: 75 61 6c 6c 79 20 74 61 6b 65 73 20 70 6c 61 63  ually takes plac
6660: 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  e..*/.static int
6670: 20 61 73 79 6e 63 54 72 75 6e 63 61 74 65 28 73   asyncTruncate(s
6680: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 46 69  qlite3_file *pFi
6690: 6c 65 2c 20 69 36 34 20 6e 42 79 74 65 29 7b 0a  le, i64 nByte){.
66a0: 20 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 20    AsyncFileData 
66b0: 2a 70 20 3d 20 28 28 41 73 79 6e 63 46 69 6c 65  *p = ((AsyncFile
66c0: 20 2a 29 70 46 69 6c 65 29 2d 3e 70 44 61 74 61   *)pFile)->pData
66d0: 3b 0a 20 20 72 65 74 75 72 6e 20 61 64 64 4e 65  ;.  return addNe
66e0: 77 41 73 79 6e 63 57 72 69 74 65 28 70 2c 20 41  wAsyncWrite(p, A
66f0: 53 59 4e 43 5f 54 52 55 4e 43 41 54 45 2c 20 6e  SYNC_TRUNCATE, n
6700: 42 79 74 65 2c 20 30 2c 20 30 29 3b 0a 7d 0a 0a  Byte, 0, 0);.}..
6710: 2f 2a 0a 2a 2a 20 53 79 6e 63 20 74 68 65 20 66  /*.** Sync the f
6720: 69 6c 65 2e 20 54 68 69 73 20 6a 75 73 74 20 61  ile. This just a
6730: 64 64 73 20 61 6e 20 65 6e 74 72 79 20 74 6f 20  dds an entry to 
6740: 74 68 65 20 77 72 69 74 65 2d 6f 70 20 6c 69 73  the write-op lis
6750: 74 2c 20 74 68 65 20 0a 2a 2a 20 73 79 6e 63 28  t, the .** sync(
6760: 29 20 69 73 20 64 6f 6e 65 20 6c 61 74 65 72 20  ) is done later 
6770: 62 79 20 73 71 6c 69 74 65 33 5f 61 73 79 6e 63  by sqlite3_async
6780: 5f 66 6c 75 73 68 28 29 2e 0a 2a 2f 0a 73 74 61  _flush()..*/.sta
6790: 74 69 63 20 69 6e 74 20 61 73 79 6e 63 53 79 6e  tic int asyncSyn
67a0: 63 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  c(sqlite3_file *
67b0: 70 46 69 6c 65 2c 20 69 6e 74 20 66 6c 61 67 73  pFile, int flags
67c0: 29 7b 0a 20 20 41 73 79 6e 63 46 69 6c 65 44 61  ){.  AsyncFileDa
67d0: 74 61 20 2a 70 20 3d 20 28 28 41 73 79 6e 63 46  ta *p = ((AsyncF
67e0: 69 6c 65 20 2a 29 70 46 69 6c 65 29 2d 3e 70 44  ile *)pFile)->pD
67f0: 61 74 61 3b 0a 20 20 72 65 74 75 72 6e 20 61 64  ata;.  return ad
6800: 64 4e 65 77 41 73 79 6e 63 57 72 69 74 65 28 70  dNewAsyncWrite(p
6810: 2c 20 41 53 59 4e 43 5f 53 59 4e 43 2c 20 30 2c  , ASYNC_SYNC, 0,
6820: 20 66 6c 61 67 73 2c 20 30 29 3b 0a 7d 0a 0a 2f   flags, 0);.}../
6830: 2a 0a 2a 2a 20 52 65 61 64 20 74 68 65 20 73 69  *.** Read the si
6840: 7a 65 20 6f 66 20 74 68 65 20 66 69 6c 65 2e 20  ze of the file. 
6850: 46 69 72 73 74 20 77 65 20 72 65 61 64 20 74 68  First we read th
6860: 65 20 73 69 7a 65 20 6f 66 20 74 68 65 20 66 69  e size of the fi
6870: 6c 65 20 73 79 73 74 65 6d 20 0a 2a 2a 20 65 6e  le system .** en
6880: 74 72 79 2c 20 74 68 65 6e 20 61 64 6a 75 73 74  try, then adjust
6890: 20 66 6f 72 20 61 6e 79 20 41 53 59 4e 43 5f 57   for any ASYNC_W
68a0: 52 49 54 45 20 6f 72 20 41 53 59 4e 43 5f 54 52  RITE or ASYNC_TR
68b0: 55 4e 43 41 54 45 20 6f 70 65 72 61 74 69 6f 6e  UNCATE operation
68c0: 73 20 0a 2a 2a 20 63 75 72 72 65 6e 74 6c 79 20  s .** currently 
68d0: 69 6e 20 74 68 65 20 77 72 69 74 65 2d 6f 70 20  in the write-op 
68e0: 6c 69 73 74 2e 20 0a 2a 2a 0a 2a 2a 20 54 68 69  list. .**.** Thi
68f0: 73 20 6d 65 74 68 6f 64 20 68 6f 6c 64 73 20 74  s method holds t
6900: 68 65 20 6d 75 74 65 78 20 66 72 6f 6d 20 73 74  he mutex from st
6910: 61 72 74 20 74 6f 20 66 69 6e 69 73 68 2e 0a 2a  art to finish..*
6920: 2f 0a 69 6e 74 20 61 73 79 6e 63 46 69 6c 65 53  /.int asyncFileS
6930: 69 7a 65 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ize(sqlite3_file
6940: 20 2a 70 46 69 6c 65 2c 20 69 36 34 20 2a 70 69   *pFile, i64 *pi
6950: 53 69 7a 65 29 7b 0a 20 20 41 73 79 6e 63 46 69  Size){.  AsyncFi
6960: 6c 65 44 61 74 61 20 2a 70 20 3d 20 28 28 41 73  leData *p = ((As
6970: 79 6e 63 46 69 6c 65 20 2a 29 70 46 69 6c 65 29  yncFile *)pFile)
6980: 2d 3e 70 44 61 74 61 3b 0a 20 20 69 6e 74 20 72  ->pData;.  int r
6990: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
69a0: 20 69 36 34 20 73 20 3d 20 30 3b 0a 20 20 73 71   i64 s = 0;.  sq
69b0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 42 61 73  lite3_file *pBas
69c0: 65 3b 0a 0a 20 20 70 74 68 72 65 61 64 5f 6d 75  e;..  pthread_mu
69d0: 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e  tex_lock(&async.
69e0: 71 75 65 75 65 4d 75 74 65 78 29 3b 0a 0a 20 20  queueMutex);..  
69f0: 2f 2a 20 52 65 61 64 20 74 68 65 20 66 69 6c 65  /* Read the file
6a00: 73 79 73 74 65 6d 20 73 69 7a 65 20 66 72 6f 6d  system size from
6a10: 20 74 68 65 20 62 61 73 65 20 66 69 6c 65 2e 20   the base file. 
6a20: 49 66 20 70 42 61 73 65 52 65 61 64 20 69 73 20  If pBaseRead is 
6a30: 4e 55 4c 4c 2c 20 74 68 69 73 0a 20 20 2a 2a 20  NULL, this.  ** 
6a40: 6d 65 61 6e 73 20 74 68 65 20 66 69 6c 65 20 68  means the file h
6a50: 61 73 6e 27 74 20 62 65 65 6e 20 6f 70 65 6e 65  asn't been opene
6a60: 64 20 79 65 74 2e 20 49 6e 20 74 68 69 73 20 63  d yet. In this c
6a70: 61 73 65 20 61 6c 6c 20 72 65 6c 65 76 61 6e 74  ase all relevant
6a80: 20 64 61 74 61 20 0a 20 20 2a 2a 20 6d 75 73 74   data .  ** must
6a90: 20 62 65 20 69 6e 20 74 68 65 20 77 72 69 74 65   be in the write
6aa0: 2d 6f 70 20 71 75 65 75 65 20 61 6e 79 77 61 79  -op queue anyway
6ab0: 2c 20 73 6f 20 77 65 20 63 61 6e 20 6f 6d 69 74  , so we can omit
6ac0: 20 72 65 61 64 69 6e 67 20 66 72 6f 6d 20 74 68   reading from th
6ad0: 65 0a 20 20 2a 2a 20 66 69 6c 65 2d 73 79 73 74  e.  ** file-syst
6ae0: 65 6d 2e 0a 20 20 2a 2f 0a 20 20 70 42 61 73 65  em..  */.  pBase
6af0: 20 3d 20 70 2d 3e 70 42 61 73 65 52 65 61 64 3b   = p->pBaseRead;
6b00: 0a 20 20 69 66 28 20 70 42 61 73 65 2d 3e 70 4d  .  if( pBase->pM
6b10: 65 74 68 6f 64 73 20 29 7b 0a 20 20 20 20 72 63  ethods ){.    rc
6b20: 20 3d 20 73 71 6c 69 74 65 33 4f 73 46 69 6c 65   = sqlite3OsFile
6b30: 53 69 7a 65 28 70 42 61 73 65 2c 20 26 73 29 3b  Size(pBase, &s);
6b40: 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d  .  }..  if( rc==
6b50: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
6b60: 20 41 73 79 6e 63 57 72 69 74 65 20 2a 70 57 72   AsyncWrite *pWr
6b70: 69 74 65 3b 0a 20 20 20 20 66 6f 72 28 70 57 72  ite;.    for(pWr
6b80: 69 74 65 3d 61 73 79 6e 63 2e 70 51 75 65 75 65  ite=async.pQueue
6b90: 46 69 72 73 74 3b 20 70 57 72 69 74 65 3b 20 70  First; pWrite; p
6ba0: 57 72 69 74 65 20 3d 20 70 57 72 69 74 65 2d 3e  Write = pWrite->
6bb0: 70 4e 65 78 74 29 7b 0a 20 20 20 20 20 20 69 66  pNext){.      if
6bc0: 28 20 70 57 72 69 74 65 2d 3e 6f 70 3d 3d 41 53  ( pWrite->op==AS
6bd0: 59 4e 43 5f 44 45 4c 45 54 45 20 26 26 20 73 74  YNC_DELETE && st
6be0: 72 63 6d 70 28 70 2d 3e 7a 4e 61 6d 65 2c 20 70  rcmp(p->zName, p
6bf0: 57 72 69 74 65 2d 3e 7a 42 75 66 29 3d 3d 30 20  Write->zBuf)==0 
6c00: 29 7b 0a 20 20 20 20 20 20 20 20 73 20 3d 20 30  ){.        s = 0
6c10: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 20 69 66  ;.      }else if
6c20: 28 20 70 57 72 69 74 65 2d 3e 70 46 69 6c 65 44  ( pWrite->pFileD
6c30: 61 74 61 20 26 26 20 70 57 72 69 74 65 2d 3e 70  ata && pWrite->p
6c40: 46 69 6c 65 44 61 74 61 2d 3e 7a 4e 61 6d 65 3d  FileData->zName=
6c50: 3d 70 2d 3e 7a 4e 61 6d 65 29 7b 0a 20 20 20 20  =p->zName){.    
6c60: 20 20 20 20 73 77 69 74 63 68 28 20 70 57 72 69      switch( pWri
6c70: 74 65 2d 3e 6f 70 20 29 7b 0a 20 20 20 20 20 20  te->op ){.      
6c80: 20 20 20 20 63 61 73 65 20 41 53 59 4e 43 5f 57      case ASYNC_W
6c90: 52 49 54 45 3a 0a 20 20 20 20 20 20 20 20 20 20  RITE:.          
6ca0: 20 20 73 20 3d 20 4d 41 58 28 70 57 72 69 74 65    s = MAX(pWrite
6cb0: 2d 3e 69 4f 66 66 73 65 74 20 2b 20 28 69 36 34  ->iOffset + (i64
6cc0: 29 28 70 57 72 69 74 65 2d 3e 6e 42 79 74 65 29  )(pWrite->nByte)
6cd0: 2c 20 73 29 3b 0a 20 20 20 20 20 20 20 20 20 20  , s);.          
6ce0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20    break;.       
6cf0: 20 20 20 63 61 73 65 20 41 53 59 4e 43 5f 54 52     case ASYNC_TR
6d00: 55 4e 43 41 54 45 3a 0a 20 20 20 20 20 20 20 20  UNCATE:.        
6d10: 20 20 20 20 73 20 3d 20 4d 49 4e 28 73 2c 20 70      s = MIN(s, p
6d20: 57 72 69 74 65 2d 3e 69 4f 66 66 73 65 74 29 3b  Write->iOffset);
6d30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 62 72 65  .            bre
6d40: 61 6b 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20  ak;.        }.  
6d50: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20      }.    }.    
6d60: 2a 70 69 53 69 7a 65 20 3d 20 73 3b 0a 20 20 7d  *piSize = s;.  }
6d70: 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78  .  pthread_mutex
6d80: 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 71  _unlock(&async.q
6d90: 75 65 75 65 4d 75 74 65 78 29 3b 0a 20 20 72 65  ueueMutex);.  re
6da0: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a  turn rc;.}../*.*
6db0: 2a 20 4c 6f 63 6b 20 6f 72 20 75 6e 6c 6f 63 6b  * Lock or unlock
6dc0: 20 74 68 65 20 61 63 74 75 61 6c 20 66 69 6c 65   the actual file
6dd0: 2d 73 79 73 74 65 6d 20 65 6e 74 72 79 2e 0a 2a  -system entry..*
6de0: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 67 65 74  /.static int get
6df0: 46 69 6c 65 4c 6f 63 6b 28 41 73 79 6e 63 4c 6f  FileLock(AsyncLo
6e00: 63 6b 20 2a 70 4c 6f 63 6b 29 7b 0a 20 20 69 6e  ck *pLock){.  in
6e10: 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b  t rc = SQLITE_OK
6e20: 3b 0a 20 20 41 73 79 6e 63 46 69 6c 65 4c 6f 63  ;.  AsyncFileLoc
6e30: 6b 20 2a 70 49 74 65 72 3b 0a 20 20 69 6e 74 20  k *pIter;.  int 
6e40: 65 52 65 71 75 69 72 65 64 20 3d 20 30 3b 0a 0a  eRequired = 0;..
6e50: 20 20 69 66 28 20 70 4c 6f 63 6b 2d 3e 70 46 69    if( pLock->pFi
6e60: 6c 65 20 29 7b 0a 20 20 20 20 66 6f 72 28 70 49  le ){.    for(pI
6e70: 74 65 72 3d 70 4c 6f 63 6b 2d 3e 70 4c 69 73 74  ter=pLock->pList
6e80: 3b 20 70 49 74 65 72 3b 20 70 49 74 65 72 3d 70  ; pIter; pIter=p
6e90: 49 74 65 72 2d 3e 70 4e 65 78 74 29 7b 0a 20 20  Iter->pNext){.  
6ea0: 20 20 20 20 61 73 73 65 72 74 28 70 49 74 65 72      assert(pIter
6eb0: 2d 3e 65 41 73 79 6e 63 4c 6f 63 6b 3e 3d 70 49  ->eAsyncLock>=pI
6ec0: 74 65 72 2d 3e 65 4c 6f 63 6b 29 3b 0a 20 20 20  ter->eLock);.   
6ed0: 20 20 20 69 66 28 20 70 49 74 65 72 2d 3e 65 41     if( pIter->eA
6ee0: 73 79 6e 63 4c 6f 63 6b 3e 65 52 65 71 75 69 72  syncLock>eRequir
6ef0: 65 64 20 29 7b 0a 20 20 20 20 20 20 20 20 65 52  ed ){.        eR
6f00: 65 71 75 69 72 65 64 20 3d 20 70 49 74 65 72 2d  equired = pIter-
6f10: 3e 65 41 73 79 6e 63 4c 6f 63 6b 3b 0a 20 20 20  >eAsyncLock;.   
6f20: 20 20 20 20 20 61 73 73 65 72 74 28 65 52 65 71       assert(eReq
6f30: 75 69 72 65 64 3e 3d 30 20 26 26 20 65 52 65 71  uired>=0 && eReq
6f40: 75 69 72 65 64 3c 3d 53 51 4c 49 54 45 5f 4c 4f  uired<=SQLITE_LO
6f50: 43 4b 5f 45 58 43 4c 55 53 49 56 45 29 3b 0a 20  CK_EXCLUSIVE);. 
6f60: 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20       }.    }..  
6f70: 20 20 69 66 28 20 65 52 65 71 75 69 72 65 64 3e    if( eRequired>
6f80: 70 4c 6f 63 6b 2d 3e 65 4c 6f 63 6b 20 29 7b 0a  pLock->eLock ){.
6f90: 20 20 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74        rc = sqlit
6fa0: 65 33 4f 73 4c 6f 63 6b 28 70 4c 6f 63 6b 2d 3e  e3OsLock(pLock->
6fb0: 70 46 69 6c 65 2c 20 65 52 65 71 75 69 72 65 64  pFile, eRequired
6fc0: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d  );.      if( rc=
6fd0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
6fe0: 20 20 20 20 20 20 70 4c 6f 63 6b 2d 3e 65 4c 6f        pLock->eLo
6ff0: 63 6b 20 3d 20 65 52 65 71 75 69 72 65 64 3b 0a  ck = eRequired;.
7000: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
7010: 20 20 65 6c 73 65 20 69 66 28 20 65 52 65 71 75    else if( eRequ
7020: 69 72 65 64 3c 70 4c 6f 63 6b 2d 3e 65 4c 6f 63  ired<pLock->eLoc
7030: 6b 20 26 26 20 65 52 65 71 75 69 72 65 64 3c 3d  k && eRequired<=
7040: 53 51 4c 49 54 45 5f 4c 4f 43 4b 5f 53 48 41 52  SQLITE_LOCK_SHAR
7050: 45 44 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  ED ){.      rc =
7060: 20 73 71 6c 69 74 65 33 4f 73 55 6e 6c 6f 63 6b   sqlite3OsUnlock
7070: 28 70 4c 6f 63 6b 2d 3e 70 46 69 6c 65 2c 20 65  (pLock->pFile, e
7080: 52 65 71 75 69 72 65 64 29 3b 0a 20 20 20 20 20  Required);.     
7090: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
70a0: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 70 4c  OK ){.        pL
70b0: 6f 63 6b 2d 3e 65 4c 6f 63 6b 20 3d 20 65 52 65  ock->eLock = eRe
70c0: 71 75 69 72 65 64 3b 0a 20 20 20 20 20 20 7d 0a  quired;.      }.
70d0: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74      }.  }..  ret
70e0: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  urn rc;.}../*.**
70f0: 20 54 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 74   The following t
7100: 77 6f 20 6d 65 74 68 6f 64 73 20 2d 20 61 73 79  wo methods - asy
7110: 6e 63 4c 6f 63 6b 28 29 20 61 6e 64 20 61 73 79  ncLock() and asy
7120: 6e 63 55 6e 6c 6f 63 6b 28 29 20 2d 20 61 72 65  ncUnlock() - are
7130: 20 75 73 65 64 0a 2a 2a 20 74 6f 20 6f 62 74 61   used.** to obta
7140: 69 6e 20 61 6e 64 20 72 65 6c 65 61 73 65 20 6c  in and release l
7150: 6f 63 6b 73 20 6f 6e 20 64 61 74 61 62 61 73 65  ocks on database
7160: 20 66 69 6c 65 73 20 6f 70 65 6e 65 64 20 77 69   files opened wi
7170: 74 68 20 74 68 65 0a 2a 2a 20 61 73 79 6e 63 68  th the.** asynch
7180: 72 6f 6e 6f 75 73 20 62 61 63 6b 65 6e 64 2e 0a  ronous backend..
7190: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73  */.static int as
71a0: 79 6e 63 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f  yncLock(sqlite3_
71b0: 66 69 6c 65 20 2a 70 46 69 6c 65 2c 20 69 6e 74  file *pFile, int
71c0: 20 65 4c 6f 63 6b 29 7b 0a 20 20 69 6e 74 20 72   eLock){.  int r
71d0: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
71e0: 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 20 2a   AsyncFileData *
71f0: 70 20 3d 20 28 28 41 73 79 6e 63 46 69 6c 65 20  p = ((AsyncFile 
7200: 2a 29 70 46 69 6c 65 29 2d 3e 70 44 61 74 61 3b  *)pFile)->pData;
7210: 0a 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65  ..  pthread_mute
7220: 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 6c 6f  x_lock(&async.lo
7230: 63 6b 4d 75 74 65 78 29 3b 0a 20 20 69 66 28 20  ckMutex);.  if( 
7240: 70 2d 3e 6c 6f 63 6b 2e 65 4c 6f 63 6b 3c 65 4c  p->lock.eLock<eL
7250: 6f 63 6b 20 29 7b 0a 20 20 20 20 41 73 79 6e 63  ock ){.    Async
7260: 4c 6f 63 6b 20 2a 70 4c 6f 63 6b 3b 0a 20 20 20  Lock *pLock;.   
7270: 20 41 73 79 6e 63 46 69 6c 65 4c 6f 63 6b 20 2a   AsyncFileLock *
7280: 70 49 74 65 72 3b 0a 20 20 20 20 70 4c 6f 63 6b  pIter;.    pLock
7290: 20 3d 20 28 41 73 79 6e 63 4c 6f 63 6b 20 2a 29   = (AsyncLock *)
72a0: 73 71 6c 69 74 65 33 48 61 73 68 46 69 6e 64 28  sqlite3HashFind(
72b0: 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 2c 20 70 2d  &async.aLock, p-
72c0: 3e 7a 4e 61 6d 65 2c 20 70 2d 3e 6e 4e 61 6d 65  >zName, p->nName
72d0: 29 3b 0a 20 20 20 20 61 73 73 65 72 74 28 70 4c  );.    assert(pL
72e0: 6f 63 6b 20 26 26 20 70 4c 6f 63 6b 2d 3e 70 4c  ock && pLock->pL
72f0: 69 73 74 29 3b 0a 20 20 20 20 66 6f 72 28 70 49  ist);.    for(pI
7300: 74 65 72 3d 70 4c 6f 63 6b 2d 3e 70 4c 69 73 74  ter=pLock->pList
7310: 3b 20 70 49 74 65 72 3b 20 70 49 74 65 72 3d 70  ; pIter; pIter=p
7320: 49 74 65 72 2d 3e 70 4e 65 78 74 29 7b 0a 20 20  Iter->pNext){.  
7330: 20 20 20 20 69 66 28 20 70 49 74 65 72 21 3d 26      if( pIter!=&
7340: 70 2d 3e 6c 6f 63 6b 20 26 26 20 28 0a 20 20 20  p->lock && (.   
7350: 20 20 20 20 20 28 65 4c 6f 63 6b 3d 3d 53 51 4c       (eLock==SQL
7360: 49 54 45 5f 4c 4f 43 4b 5f 45 58 43 4c 55 53 49  ITE_LOCK_EXCLUSI
7370: 56 45 20 26 26 20 70 49 74 65 72 2d 3e 65 4c 6f  VE && pIter->eLo
7380: 63 6b 3e 3d 53 51 4c 49 54 45 5f 4c 4f 43 4b 5f  ck>=SQLITE_LOCK_
7390: 53 48 41 52 45 44 29 20 7c 7c 0a 20 20 20 20 20  SHARED) ||.     
73a0: 20 20 20 28 65 4c 6f 63 6b 3d 3d 53 51 4c 49 54     (eLock==SQLIT
73b0: 45 5f 4c 4f 43 4b 5f 50 45 4e 44 49 4e 47 20 26  E_LOCK_PENDING &
73c0: 26 20 70 49 74 65 72 2d 3e 65 4c 6f 63 6b 3e 3d  & pIter->eLock>=
73d0: 53 51 4c 49 54 45 5f 4c 4f 43 4b 5f 52 45 53 45  SQLITE_LOCK_RESE
73e0: 52 56 45 44 29 20 7c 7c 0a 20 20 20 20 20 20 20  RVED) ||.       
73f0: 20 28 65 4c 6f 63 6b 3d 3d 53 51 4c 49 54 45 5f   (eLock==SQLITE_
7400: 4c 4f 43 4b 5f 52 45 53 45 52 56 45 44 20 26 26  LOCK_RESERVED &&
7410: 20 70 49 74 65 72 2d 3e 65 4c 6f 63 6b 3e 3d 53   pIter->eLock>=S
7420: 51 4c 49 54 45 5f 4c 4f 43 4b 5f 52 45 53 45 52  QLITE_LOCK_RESER
7430: 56 45 44 29 20 7c 7c 0a 20 20 20 20 20 20 20 20  VED) ||.        
7440: 28 65 4c 6f 63 6b 3d 3d 53 51 4c 49 54 45 5f 4c  (eLock==SQLITE_L
7450: 4f 43 4b 5f 53 48 41 52 45 44 20 26 26 20 70 49  OCK_SHARED && pI
7460: 74 65 72 2d 3e 65 4c 6f 63 6b 3e 3d 53 51 4c 49  ter->eLock>=SQLI
7470: 54 45 5f 4c 4f 43 4b 5f 50 45 4e 44 49 4e 47 29  TE_LOCK_PENDING)
7480: 0a 20 20 20 20 20 20 29 29 7b 0a 20 20 20 20 20  .      )){.     
7490: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 42     rc = SQLITE_B
74a0: 55 53 59 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  USY;.      }.   
74b0: 20 7d 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53   }.    if( rc==S
74c0: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
74d0: 20 20 70 2d 3e 6c 6f 63 6b 2e 65 4c 6f 63 6b 20    p->lock.eLock 
74e0: 3d 20 65 4c 6f 63 6b 3b 0a 20 20 20 20 20 20 70  = eLock;.      p
74f0: 2d 3e 6c 6f 63 6b 2e 65 41 73 79 6e 63 4c 6f 63  ->lock.eAsyncLoc
7500: 6b 20 3d 20 4d 41 58 28 70 2d 3e 6c 6f 63 6b 2e  k = MAX(p->lock.
7510: 65 41 73 79 6e 63 4c 6f 63 6b 2c 20 65 4c 6f 63  eAsyncLock, eLoc
7520: 6b 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 61 73  k);.    }.    as
7530: 73 65 72 74 28 70 2d 3e 6c 6f 63 6b 2e 65 41 73  sert(p->lock.eAs
7540: 79 6e 63 4c 6f 63 6b 3e 3d 70 2d 3e 6c 6f 63 6b  yncLock>=p->lock
7550: 2e 65 4c 6f 63 6b 29 3b 0a 20 20 20 20 69 66 28  .eLock);.    if(
7560: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
7570: 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 67 65 74  {.      rc = get
7580: 46 69 6c 65 4c 6f 63 6b 28 70 4c 6f 63 6b 29 3b  FileLock(pLock);
7590: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 70 74 68  .    }.  }.  pth
75a0: 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63  read_mutex_unloc
75b0: 6b 28 26 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75 74  k(&async.lockMut
75c0: 65 78 29 3b 0a 0a 20 20 41 53 59 4e 43 5f 54 52  ex);..  ASYNC_TR
75d0: 41 43 45 28 28 22 4c 4f 43 4b 20 25 64 20 28 25  ACE(("LOCK %d (%
75e0: 73 29 20 72 63 3d 25 64 5c 6e 22 2c 20 65 4c 6f  s) rc=%d\n", eLo
75f0: 63 6b 2c 20 70 2d 3e 7a 4e 61 6d 65 2c 20 72 63  ck, p->zName, rc
7600: 29 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ));.  return rc;
7610: 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73  .}.static int as
7620: 79 6e 63 55 6e 6c 6f 63 6b 28 73 71 6c 69 74 65  yncUnlock(sqlite
7630: 33 5f 66 69 6c 65 20 2a 70 46 69 6c 65 2c 20 69  3_file *pFile, i
7640: 6e 74 20 65 4c 6f 63 6b 29 7b 0a 20 20 41 73 79  nt eLock){.  Asy
7650: 6e 63 46 69 6c 65 44 61 74 61 20 2a 70 20 3d 20  ncFileData *p = 
7660: 28 28 41 73 79 6e 63 46 69 6c 65 20 2a 29 70 46  ((AsyncFile *)pF
7670: 69 6c 65 29 2d 3e 70 44 61 74 61 3b 0a 20 20 41  ile)->pData;.  A
7680: 73 79 6e 63 46 69 6c 65 4c 6f 63 6b 20 2a 70 4c  syncFileLock *pL
7690: 6f 63 6b 20 3d 20 26 70 2d 3e 6c 6f 63 6b 3b 0a  ock = &p->lock;.
76a0: 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f    pthread_mutex_
76b0: 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 6c 6f 63 6b  lock(&async.lock
76c0: 4d 75 74 65 78 29 3b 0a 20 20 70 4c 6f 63 6b 2d  Mutex);.  pLock-
76d0: 3e 65 4c 6f 63 6b 20 3d 20 4d 49 4e 28 70 4c 6f  >eLock = MIN(pLo
76e0: 63 6b 2d 3e 65 4c 6f 63 6b 2c 20 65 4c 6f 63 6b  ck->eLock, eLock
76f0: 29 3b 0a 20 20 70 74 68 72 65 61 64 5f 6d 75 74  );.  pthread_mut
7700: 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e 63  ex_unlock(&async
7710: 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20 20 72  .lockMutex);.  r
7720: 65 74 75 72 6e 20 61 64 64 4e 65 77 41 73 79 6e  eturn addNewAsyn
7730: 63 57 72 69 74 65 28 70 2c 20 41 53 59 4e 43 5f  cWrite(p, ASYNC_
7740: 55 4e 4c 4f 43 4b 2c 20 30 2c 20 65 4c 6f 63 6b  UNLOCK, 0, eLock
7750: 2c 20 30 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54  , 0);.}../*.** T
7760: 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20  his function is 
7770: 63 61 6c 6c 65 64 20 77 68 65 6e 20 74 68 65 20  called when the 
7780: 70 61 67 65 72 20 6c 61 79 65 72 20 66 69 72 73  pager layer firs
7790: 74 20 6f 70 65 6e 73 20 61 20 64 61 74 61 62 61  t opens a databa
77a0: 73 65 20 66 69 6c 65 0a 2a 2a 20 61 6e 64 20 69  se file.** and i
77b0: 73 20 63 68 65 63 6b 69 6e 67 20 66 6f 72 20 61  s checking for a
77c0: 20 68 6f 74 2d 6a 6f 75 72 6e 61 6c 2e 0a 2a 2f   hot-journal..*/
77d0: 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73 79 6e  .static int asyn
77e0: 63 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f  cCheckReservedLo
77f0: 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  ck(sqlite3_file 
7800: 2a 70 46 69 6c 65 29 7b 0a 20 20 69 6e 74 20 72  *pFile){.  int r
7810: 65 74 20 3d 20 30 3b 0a 20 20 41 73 79 6e 63 46  et = 0;.  AsyncF
7820: 69 6c 65 4c 6f 63 6b 20 2a 70 49 74 65 72 3b 0a  ileLock *pIter;.
7830: 20 20 41 73 79 6e 63 4c 6f 63 6b 20 2a 70 4c 6f    AsyncLock *pLo
7840: 63 6b 3b 0a 20 20 41 73 79 6e 63 46 69 6c 65 44  ck;.  AsyncFileD
7850: 61 74 61 20 2a 70 20 3d 20 28 28 41 73 79 6e 63  ata *p = ((Async
7860: 46 69 6c 65 20 2a 29 70 46 69 6c 65 29 2d 3e 70  File *)pFile)->p
7870: 44 61 74 61 3b 0a 0a 20 20 70 74 68 72 65 61 64  Data;..  pthread
7880: 5f 6d 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79  _mutex_lock(&asy
7890: 6e 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20  nc.lockMutex);. 
78a0: 20 70 4c 6f 63 6b 20 3d 20 28 41 73 79 6e 63 4c   pLock = (AsyncL
78b0: 6f 63 6b 20 2a 29 73 71 6c 69 74 65 33 48 61 73  ock *)sqlite3Has
78c0: 68 46 69 6e 64 28 26 61 73 79 6e 63 2e 61 4c 6f  hFind(&async.aLo
78d0: 63 6b 2c 20 70 2d 3e 7a 4e 61 6d 65 2c 20 70 2d  ck, p->zName, p-
78e0: 3e 6e 4e 61 6d 65 29 3b 0a 20 20 66 6f 72 28 70  >nName);.  for(p
78f0: 49 74 65 72 3d 70 4c 6f 63 6b 2d 3e 70 4c 69 73  Iter=pLock->pLis
7900: 74 3b 20 70 49 74 65 72 3b 20 70 49 74 65 72 3d  t; pIter; pIter=
7910: 70 49 74 65 72 2d 3e 70 4e 65 78 74 29 7b 0a 20  pIter->pNext){. 
7920: 20 20 20 69 66 28 20 70 49 74 65 72 2d 3e 65 4c     if( pIter->eL
7930: 6f 63 6b 3e 3d 53 51 4c 49 54 45 5f 4c 4f 43 4b  ock>=SQLITE_LOCK
7940: 5f 52 45 53 45 52 56 45 44 20 29 7b 0a 20 20 20  _RESERVED ){.   
7950: 20 20 20 72 65 74 20 3d 20 31 3b 0a 20 20 20 20     ret = 1;.    
7960: 7d 0a 20 20 7d 0a 20 20 70 74 68 72 65 61 64 5f  }.  }.  pthread_
7970: 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73  mutex_unlock(&as
7980: 79 6e 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a  ync.lockMutex);.
7990: 0a 20 20 41 53 59 4e 43 5f 54 52 41 43 45 28 28  .  ASYNC_TRACE((
79a0: 22 43 48 45 43 4b 2d 4c 4f 43 4b 20 25 64 20 28  "CHECK-LOCK %d (
79b0: 25 73 29 5c 6e 22 2c 20 72 65 74 2c 20 70 2d 3e  %s)\n", ret, p->
79c0: 7a 4e 61 6d 65 29 29 3b 0a 20 20 72 65 74 75 72  zName));.  retur
79d0: 6e 20 72 65 74 3b 0a 7d 0a 0a 2f 2a 20 0a 2a 2a  n ret;.}../* .**
79e0: 20 54 68 69 73 20 69 73 20 61 20 6e 6f 2d 6f 70   This is a no-op
79f0: 2c 20 61 73 20 74 68 65 20 61 73 79 6e 63 68 72  , as the asynchr
7a00: 6f 6e 6f 75 73 20 62 61 63 6b 65 6e 64 20 64 6f  onous backend do
7a10: 65 73 20 6e 6f 74 20 73 75 70 70 6f 72 74 20 6c  es not support l
7a20: 6f 63 6b 69 6e 67 2e 0a 2a 2f 0a 73 74 61 74 69  ocking..*/.stati
7a30: 63 20 69 6e 74 20 61 73 79 6e 63 46 69 6c 65 43  c int asyncFileC
7a40: 6f 6e 74 72 6f 6c 28 73 71 6c 69 74 65 33 5f 66  ontrol(sqlite3_f
7a50: 69 6c 65 20 2a 69 64 2c 20 69 6e 74 20 6f 70 2c  ile *id, int op,
7a60: 20 76 6f 69 64 20 2a 70 41 72 67 29 7b 0a 20 20   void *pArg){.  
7a70: 73 77 69 74 63 68 28 20 6f 70 20 29 7b 0a 20 20  switch( op ){.  
7a80: 20 20 63 61 73 65 20 53 51 4c 49 54 45 5f 46 43    case SQLITE_FC
7a90: 4e 54 4c 5f 4c 4f 43 4b 53 54 41 54 45 3a 20 7b  NTL_LOCKSTATE: {
7aa0: 0a 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d  .      pthread_m
7ab0: 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63  utex_lock(&async
7ac0: 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20 20 20  .lockMutex);.   
7ad0: 20 20 20 2a 28 69 6e 74 2a 29 70 41 72 67 20 3d     *(int*)pArg =
7ae0: 20 28 28 41 73 79 6e 63 46 69 6c 65 2a 29 69 64   ((AsyncFile*)id
7af0: 29 2d 3e 70 44 61 74 61 2d 3e 6c 6f 63 6b 2e 65  )->pData->lock.e
7b00: 4c 6f 63 6b 3b 0a 20 20 20 20 20 20 70 74 68 72  Lock;.      pthr
7b10: 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b  ead_mutex_unlock
7b20: 28 26 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75 74 65  (&async.lockMute
7b30: 78 29 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e  x);.      return
7b40: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20   SQLITE_OK;.    
7b50: 7d 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53  }.  }.  return S
7b60: 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 7d 0a 0a  QLITE_ERROR;.}..
7b70: 2f 2a 20 0a 2a 2a 20 52 65 74 75 72 6e 20 74 68  /* .** Return th
7b80: 65 20 64 65 76 69 63 65 20 63 68 61 72 61 63 74  e device charact
7b90: 65 72 69 73 74 69 63 73 20 61 6e 64 20 73 65 63  eristics and sec
7ba0: 74 6f 72 2d 73 69 7a 65 20 6f 66 20 74 68 65 20  tor-size of the 
7bb0: 64 65 76 69 63 65 2e 20 49 74 0a 2a 2a 20 69 73  device. It.** is
7bc0: 20 6e 6f 74 20 74 72 69 63 6b 79 20 74 6f 20 69   not tricky to i
7bd0: 6d 70 6c 65 6d 65 6e 74 20 74 68 65 73 65 20 63  mplement these c
7be0: 6f 72 72 65 63 74 6c 79 2c 20 61 73 20 74 68 69  orrectly, as thi
7bf0: 73 20 62 61 63 6b 65 6e 64 20 6d 69 67 68 74 20  s backend might 
7c00: 0a 2a 2a 20 6e 6f 74 20 68 61 76 65 20 61 6e 20  .** not have an 
7c10: 6f 70 65 6e 20 66 69 6c 65 20 68 61 6e 64 6c 65  open file handle
7c20: 20 61 74 20 74 68 69 73 20 70 6f 69 6e 74 2e 0a   at this point..
7c30: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73  */.static int as
7c40: 79 6e 63 53 65 63 74 6f 72 53 69 7a 65 28 73 71  yncSectorSize(sq
7c50: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 46 69 6c  lite3_file *pFil
7c60: 65 29 7b 0a 20 20 72 65 74 75 72 6e 20 35 31 32  e){.  return 512
7c70: 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 61  ;.}.static int a
7c80: 73 79 6e 63 44 65 76 69 63 65 43 68 61 72 61 63  syncDeviceCharac
7c90: 74 65 72 69 73 74 69 63 73 28 73 71 6c 69 74 65  teristics(sqlite
7ca0: 33 5f 66 69 6c 65 20 2a 70 46 69 6c 65 29 7b 0a  3_file *pFile){.
7cb0: 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 73    return 0;.}..s
7cc0: 74 61 74 69 63 20 69 6e 74 20 75 6e 6c 69 6e 6b  tatic int unlink
7cd0: 41 73 79 6e 63 46 69 6c 65 28 41 73 79 6e 63 46  AsyncFile(AsyncF
7ce0: 69 6c 65 44 61 74 61 20 2a 70 44 61 74 61 29 7b  ileData *pData){
7cf0: 0a 20 20 41 73 79 6e 63 4c 6f 63 6b 20 2a 70 4c  .  AsyncLock *pL
7d00: 6f 63 6b 3b 0a 20 20 41 73 79 6e 63 46 69 6c 65  ock;.  AsyncFile
7d10: 4c 6f 63 6b 20 2a 2a 70 70 49 74 65 72 3b 0a 20  Lock **ppIter;. 
7d20: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
7d30: 5f 4f 4b 3b 0a 0a 20 20 70 4c 6f 63 6b 20 3d 20  _OK;..  pLock = 
7d40: 73 71 6c 69 74 65 33 48 61 73 68 46 69 6e 64 28  sqlite3HashFind(
7d50: 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 2c 20 70 44  &async.aLock, pD
7d60: 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70 44 61 74  ata->zName, pDat
7d70: 61 2d 3e 6e 4e 61 6d 65 29 3b 0a 20 20 66 6f 72  a->nName);.  for
7d80: 28 70 70 49 74 65 72 3d 26 70 4c 6f 63 6b 2d 3e  (ppIter=&pLock->
7d90: 70 4c 69 73 74 3b 20 2a 70 70 49 74 65 72 3b 20  pList; *ppIter; 
7da0: 70 70 49 74 65 72 3d 26 28 28 2a 70 70 49 74 65  ppIter=&((*ppIte
7db0: 72 29 2d 3e 70 4e 65 78 74 29 29 7b 0a 20 20 20  r)->pNext)){.   
7dc0: 20 69 66 28 20 28 2a 70 70 49 74 65 72 29 3d 3d   if( (*ppIter)==
7dd0: 26 70 44 61 74 61 2d 3e 6c 6f 63 6b 20 29 7b 0a  &pData->lock ){.
7de0: 20 20 20 20 20 20 2a 70 70 49 74 65 72 20 3d 20        *ppIter = 
7df0: 70 44 61 74 61 2d 3e 6c 6f 63 6b 2e 70 4e 65 78  pData->lock.pNex
7e00: 74 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  t;.      break;.
7e10: 20 20 20 20 7d 0a 20 20 7d 0a 20 20 69 66 28 20      }.  }.  if( 
7e20: 21 70 4c 6f 63 6b 2d 3e 70 4c 69 73 74 20 29 7b  !pLock->pList ){
7e30: 0a 20 20 20 20 69 66 28 20 70 4c 6f 63 6b 2d 3e  .    if( pLock->
7e40: 70 46 69 6c 65 20 29 7b 0a 20 20 20 20 20 20 73  pFile ){.      s
7e50: 71 6c 69 74 65 33 4f 73 43 6c 6f 73 65 28 70 4c  qlite3OsClose(pL
7e60: 6f 63 6b 2d 3e 70 46 69 6c 65 29 3b 0a 20 20 20  ock->pFile);.   
7e70: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66   }.    sqlite3_f
7e80: 72 65 65 28 70 4c 6f 63 6b 29 3b 0a 20 20 20 20  ree(pLock);.    
7e90: 73 71 6c 69 74 65 33 48 61 73 68 49 6e 73 65 72  sqlite3HashInser
7ea0: 74 28 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 2c 20  t(&async.aLock, 
7eb0: 70 44 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70 44  pData->zName, pD
7ec0: 61 74 61 2d 3e 6e 4e 61 6d 65 2c 20 30 29 3b 0a  ata->nName, 0);.
7ed0: 20 20 20 20 69 66 28 20 21 73 71 6c 69 74 65 48      if( !sqliteH
7ee0: 61 73 68 46 69 72 73 74 28 26 61 73 79 6e 63 2e  ashFirst(&async.
7ef0: 61 4c 6f 63 6b 29 20 29 7b 0a 20 20 20 20 20 20  aLock) ){.      
7f00: 73 71 6c 69 74 65 33 48 61 73 68 43 6c 65 61 72  sqlite3HashClear
7f10: 28 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 29 3b 0a  (&async.aLock);.
7f20: 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20      }.  }else{. 
7f30: 20 20 20 72 63 20 3d 20 67 65 74 46 69 6c 65 4c     rc = getFileL
7f40: 6f 63 6b 28 70 4c 6f 63 6b 29 3b 0a 20 20 7d 0a  ock(pLock);.  }.
7f50: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
7f60: 0a 2f 2a 0a 2a 2a 20 4f 70 65 6e 20 61 20 66 69  ./*.** Open a fi
7f70: 6c 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  le..*/.static in
7f80: 74 20 61 73 79 6e 63 4f 70 65 6e 28 0a 20 20 73  t asyncOpen(.  s
7f90: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 41 73 79  qlite3_vfs *pAsy
7fa0: 6e 63 56 66 73 2c 0a 20 20 63 6f 6e 73 74 20 63  ncVfs,.  const c
7fb0: 68 61 72 20 2a 7a 4e 61 6d 65 2c 0a 20 20 73 71  har *zName,.  sq
7fc0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 46 69 6c  lite3_file *pFil
7fd0: 65 2c 0a 20 20 69 6e 74 20 66 6c 61 67 73 2c 0a  e,.  int flags,.
7fe0: 20 20 69 6e 74 20 2a 70 4f 75 74 46 6c 61 67 73    int *pOutFlags
7ff0: 0a 29 7b 0a 20 20 73 74 61 74 69 63 20 73 71 6c  .){.  static sql
8000: 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20  ite3_io_methods 
8010: 61 73 79 6e 63 5f 6d 65 74 68 6f 64 73 20 3d 20  async_methods = 
8020: 7b 0a 20 20 20 20 31 2c 20 20 20 20 20 20 20 20  {.    1,        
8030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8040: 20 20 20 20 20 20 20 2f 2a 20 69 56 65 72 73 69         /* iVersi
8050: 6f 6e 20 2a 2f 0a 20 20 20 20 61 73 79 6e 63 43  on */.    asyncC
8060: 6c 6f 73 65 2c 20 20 20 20 20 20 20 20 20 20 20  lose,           
8070: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 78 43             /* xC
8080: 6c 6f 73 65 20 2a 2f 0a 20 20 20 20 61 73 79 6e  lose */.    asyn
8090: 63 52 65 61 64 2c 20 20 20 20 20 20 20 20 20 20  cRead,          
80a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
80b0: 78 52 65 61 64 20 2a 2f 0a 20 20 20 20 61 73 79  xRead */.    asy
80c0: 6e 63 57 72 69 74 65 2c 20 20 20 20 20 20 20 20  ncWrite,        
80d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
80e0: 20 78 57 72 69 74 65 20 2a 2f 0a 20 20 20 20 61   xWrite */.    a
80f0: 73 79 6e 63 54 72 75 6e 63 61 74 65 2c 20 20 20  syncTruncate,   
8100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8110: 2f 2a 20 78 54 72 75 6e 63 61 74 65 20 2a 2f 0a  /* xTruncate */.
8120: 20 20 20 20 61 73 79 6e 63 53 79 6e 63 2c 20 20      asyncSync,  
8130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8140: 20 20 20 20 20 2f 2a 20 78 53 79 6e 63 20 2a 2f       /* xSync */
8150: 0a 20 20 20 20 61 73 79 6e 63 46 69 6c 65 53 69  .    asyncFileSi
8160: 7a 65 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  ze,             
8170: 20 20 20 20 20 20 2f 2a 20 78 46 69 6c 65 53 69        /* xFileSi
8180: 7a 65 20 2a 2f 0a 20 20 20 20 61 73 79 6e 63 4c  ze */.    asyncL
8190: 6f 63 6b 2c 20 20 20 20 20 20 20 20 20 20 20 20  ock,            
81a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 78 4c             /* xL
81b0: 6f 63 6b 20 2a 2f 0a 20 20 20 20 61 73 79 6e 63  ock */.    async
81c0: 55 6e 6c 6f 63 6b 2c 20 20 20 20 20 20 20 20 20  Unlock,         
81d0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 78              /* x
81e0: 55 6e 6c 6f 63 6b 20 2a 2f 0a 20 20 20 20 61 73  Unlock */.    as
81f0: 79 6e 63 43 68 65 63 6b 52 65 73 65 72 76 65 64  yncCheckReserved
8200: 4c 6f 63 6b 2c 20 20 20 20 20 20 20 20 20 20 2f  Lock,          /
8210: 2a 20 78 43 68 65 63 6b 52 65 73 65 72 76 65 64  * xCheckReserved
8220: 4c 6f 63 6b 20 2a 2f 0a 20 20 20 20 61 73 79 6e  Lock */.    asyn
8230: 63 46 69 6c 65 43 6f 6e 74 72 6f 6c 2c 20 20 20  cFileControl,   
8240: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
8250: 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 20 2a 2f 0a  xFileControl */.
8260: 20 20 20 20 61 73 79 6e 63 53 65 63 74 6f 72 53      asyncSectorS
8270: 69 7a 65 2c 20 20 20 20 20 20 20 20 20 20 20 20  ize,            
8280: 20 20 20 20 20 2f 2a 20 78 53 65 63 74 6f 72 53       /* xSectorS
8290: 69 7a 65 20 2a 2f 0a 20 20 20 20 61 73 79 6e 63  ize */.    async
82a0: 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69  DeviceCharacteri
82b0: 73 74 69 63 73 20 20 20 20 20 20 20 2f 2a 20 78  stics       /* x
82c0: 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69  DeviceCharacteri
82d0: 73 74 69 63 73 20 2a 2f 0a 20 20 7d 3b 0a 0a 20  stics */.  };.. 
82e0: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 56   sqlite3_vfs *pV
82f0: 66 73 20 3d 20 28 73 71 6c 69 74 65 33 5f 76 66  fs = (sqlite3_vf
8300: 73 20 2a 29 70 41 73 79 6e 63 56 66 73 2d 3e 70  s *)pAsyncVfs->p
8310: 41 70 70 44 61 74 61 3b 0a 20 20 41 73 79 6e 63  AppData;.  Async
8320: 46 69 6c 65 20 2a 70 20 3d 20 28 41 73 79 6e 63  File *p = (Async
8330: 46 69 6c 65 20 2a 29 70 46 69 6c 65 3b 0a 20 20  File *)pFile;.  
8340: 69 6e 74 20 6e 4e 61 6d 65 20 3d 20 73 74 72 6c  int nName = strl
8350: 65 6e 28 7a 4e 61 6d 65 29 2b 31 3b 0a 20 20 69  en(zName)+1;.  i
8360: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
8370: 4b 3b 0a 20 20 69 6e 74 20 6e 42 79 74 65 3b 0a  K;.  int nByte;.
8380: 20 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 20    AsyncFileData 
8390: 2a 70 44 61 74 61 3b 0a 20 20 41 73 79 6e 63 4c  *pData;.  AsyncL
83a0: 6f 63 6b 20 2a 70 4c 6f 63 6b 20 3d 20 30 3b 0a  ock *pLock = 0;.
83b0: 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20 69 6e 74    char *z;.  int
83c0: 20 69 73 45 78 63 6c 75 73 69 76 65 20 3d 20 28   isExclusive = (
83d0: 66 6c 61 67 73 26 53 51 4c 49 54 45 5f 4f 50 45  flags&SQLITE_OPE
83e0: 4e 5f 45 58 43 4c 55 53 49 56 45 29 3b 0a 0a 20  N_EXCLUSIVE);.. 
83f0: 20 6e 42 79 74 65 20 3d 20 28 0a 20 20 20 20 73   nByte = (.    s
8400: 69 7a 65 6f 66 28 41 73 79 6e 63 46 69 6c 65 44  izeof(AsyncFileD
8410: 61 74 61 29 20 2b 20 20 20 20 20 20 20 20 2f 2a  ata) +        /*
8420: 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 20 73   AsyncFileData s
8430: 74 72 75 63 74 75 72 65 20 2a 2f 0a 20 20 20 20  tructure */.    
8440: 32 20 2a 20 70 56 66 73 2d 3e 73 7a 4f 73 46 69  2 * pVfs->szOsFi
8450: 6c 65 20 2b 20 20 20 20 20 20 20 20 20 20 20 2f  le +           /
8460: 2a 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 2e  * AsyncFileData.
8470: 70 42 61 73 65 52 65 61 64 20 61 6e 64 20 70 42  pBaseRead and pB
8480: 61 73 65 57 72 69 74 65 20 2a 2f 0a 20 20 20 20  aseWrite */.    
8490: 6e 4e 61 6d 65 20 20 20 20 20 20 20 20 20 20 20  nName           
84a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
84b0: 2a 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61 2e  * AsyncFileData.
84c0: 7a 4e 61 6d 65 20 2a 2f 0a 20 20 29 3b 20 0a 20  zName */.  ); . 
84d0: 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c   z = sqlite3_mal
84e0: 6c 6f 63 28 6e 42 79 74 65 29 3b 0a 20 20 69 66  loc(nByte);.  if
84f0: 28 20 21 7a 20 29 7b 0a 20 20 20 20 72 65 74 75  ( !z ){.    retu
8500: 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b  rn SQLITE_NOMEM;
8510: 0a 20 20 7d 0a 20 20 6d 65 6d 73 65 74 28 7a 2c  .  }.  memset(z,
8520: 20 30 2c 20 6e 42 79 74 65 29 3b 0a 20 20 70 44   0, nByte);.  pD
8530: 61 74 61 20 3d 20 28 41 73 79 6e 63 46 69 6c 65  ata = (AsyncFile
8540: 44 61 74 61 2a 29 7a 3b 0a 20 20 7a 20 2b 3d 20  Data*)z;.  z += 
8550: 73 69 7a 65 6f 66 28 70 44 61 74 61 5b 30 5d 29  sizeof(pData[0])
8560: 3b 0a 20 20 70 44 61 74 61 2d 3e 70 42 61 73 65  ;.  pData->pBase
8570: 52 65 61 64 20 3d 20 28 73 71 6c 69 74 65 33 5f  Read = (sqlite3_
8580: 66 69 6c 65 2a 29 7a 3b 0a 20 20 7a 20 2b 3d 20  file*)z;.  z += 
8590: 70 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 3b 0a  pVfs->szOsFile;.
85a0: 20 20 70 44 61 74 61 2d 3e 70 42 61 73 65 57 72    pData->pBaseWr
85b0: 69 74 65 20 3d 20 28 73 71 6c 69 74 65 33 5f 66  ite = (sqlite3_f
85c0: 69 6c 65 2a 29 7a 3b 0a 20 20 7a 20 2b 3d 20 70  ile*)z;.  z += p
85d0: 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 3b 0a 20  Vfs->szOsFile;. 
85e0: 20 70 44 61 74 61 2d 3e 7a 4e 61 6d 65 20 3d 20   pData->zName = 
85f0: 7a 3b 0a 20 20 70 44 61 74 61 2d 3e 6e 4e 61 6d  z;.  pData->nNam
8600: 65 20 3d 20 6e 4e 61 6d 65 3b 0a 20 20 70 44 61  e = nName;.  pDa
8610: 74 61 2d 3e 63 6c 6f 73 65 2e 70 46 69 6c 65 44  ta->close.pFileD
8620: 61 74 61 20 3d 20 70 44 61 74 61 3b 0a 20 20 70  ata = pData;.  p
8630: 44 61 74 61 2d 3e 63 6c 6f 73 65 2e 6f 70 20 3d  Data->close.op =
8640: 20 41 53 59 4e 43 5f 43 4c 4f 53 45 3b 0a 20 20   ASYNC_CLOSE;.  
8650: 6d 65 6d 63 70 79 28 70 44 61 74 61 2d 3e 7a 4e  memcpy(pData->zN
8660: 61 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d  ame, zName, nNam
8670: 65 29 3b 0a 0a 20 20 69 66 28 20 21 69 73 45 78  e);..  if( !isEx
8680: 63 6c 75 73 69 76 65 20 29 7b 0a 20 20 20 20 72  clusive ){.    r
8690: 63 20 3d 20 73 71 6c 69 74 65 33 4f 73 4f 70 65  c = sqlite3OsOpe
86a0: 6e 28 70 56 66 73 2c 20 7a 4e 61 6d 65 2c 20 70  n(pVfs, zName, p
86b0: 44 61 74 61 2d 3e 70 42 61 73 65 52 65 61 64 2c  Data->pBaseRead,
86c0: 20 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c 61 67   flags, pOutFlag
86d0: 73 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d  s);.    if( rc==
86e0: 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 28 28 2a  SQLITE_OK && ((*
86f0: 70 4f 75 74 46 6c 61 67 73 29 26 53 51 4c 49 54  pOutFlags)&SQLIT
8700: 45 5f 4f 50 45 4e 5f 52 45 41 44 57 52 49 54 45  E_OPEN_READWRITE
8710: 29 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  ) ){.      rc = 
8720: 73 71 6c 69 74 65 33 4f 73 4f 70 65 6e 28 70 56  sqlite3OsOpen(pV
8730: 66 73 2c 20 7a 4e 61 6d 65 2c 20 70 44 61 74 61  fs, zName, pData
8740: 2d 3e 70 42 61 73 65 57 72 69 74 65 2c 20 66 6c  ->pBaseWrite, fl
8750: 61 67 73 2c 20 30 29 3b 0a 20 20 20 20 7d 0a 20  ags, 0);.    }. 
8760: 20 7d 0a 0a 20 20 70 74 68 72 65 61 64 5f 6d 75   }..  pthread_mu
8770: 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e  tex_lock(&async.
8780: 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 0a 20 20 69  lockMutex);..  i
8790: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
87a0: 20 29 7b 0a 20 20 20 20 70 4c 6f 63 6b 20 3d 20   ){.    pLock = 
87b0: 73 71 6c 69 74 65 33 48 61 73 68 46 69 6e 64 28  sqlite3HashFind(
87c0: 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 2c 20 70 44  &async.aLock, pD
87d0: 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70 44 61 74  ata->zName, pDat
87e0: 61 2d 3e 6e 4e 61 6d 65 29 3b 0a 20 20 20 20 69  a->nName);.    i
87f0: 66 28 20 21 70 4c 6f 63 6b 20 29 7b 0a 20 20 20  f( !pLock ){.   
8800: 20 20 20 70 4c 6f 63 6b 20 3d 20 73 71 6c 69 74     pLock = sqlit
8810: 65 33 4d 61 6c 6c 6f 63 5a 65 72 6f 28 70 56 66  e3MallocZero(pVf
8820: 73 2d 3e 73 7a 4f 73 46 69 6c 65 20 2b 20 73 69  s->szOsFile + si
8830: 7a 65 6f 66 28 41 73 79 6e 63 4c 6f 63 6b 29 29  zeof(AsyncLock))
8840: 3b 0a 20 20 20 20 20 20 69 66 28 20 70 4c 6f 63  ;.      if( pLoc
8850: 6b 20 29 7b 0a 20 20 20 20 20 20 20 20 41 73 79  k ){.        Asy
8860: 6e 63 4c 6f 63 6b 20 2a 70 44 65 6c 65 74 65 3b  ncLock *pDelete;
8870: 0a 23 69 66 64 65 66 20 45 4e 41 42 4c 45 5f 46  .#ifdef ENABLE_F
8880: 49 4c 45 5f 4c 4f 43 4b 49 4e 47 0a 20 20 20 20  ILE_LOCKING.    
8890: 20 20 20 20 69 66 28 20 66 6c 61 67 73 26 53 51      if( flags&SQ
88a0: 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 44  LITE_OPEN_MAIN_D
88b0: 42 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70  B ){.          p
88c0: 4c 6f 63 6b 2d 3e 70 46 69 6c 65 20 3d 20 28 73  Lock->pFile = (s
88d0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 29 26 70  qlite3_file *)&p
88e0: 4c 6f 63 6b 5b 31 5d 3b 0a 20 20 20 20 20 20 20  Lock[1];.       
88f0: 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 4f     rc = sqlite3O
8900: 73 4f 70 65 6e 28 70 56 66 73 2c 20 7a 4e 61 6d  sOpen(pVfs, zNam
8910: 65 2c 20 70 4c 6f 63 6b 2d 3e 70 46 69 6c 65 2c  e, pLock->pFile,
8920: 20 66 6c 61 67 73 2c 20 30 29 3b 0a 20 20 20 20   flags, 0);.    
8930: 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51        if( rc!=SQ
8940: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
8950: 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66         sqlite3_f
8960: 72 65 65 28 70 4c 6f 63 6b 29 3b 0a 20 20 20 20  ree(pLock);.    
8970: 20 20 20 20 20 20 20 20 70 4c 6f 63 6b 20 3d 20          pLock = 
8980: 30 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20  0;.          }. 
8990: 20 20 20 20 20 20 20 7d 0a 23 65 6e 64 69 66 0a         }.#endif.
89a0: 20 20 20 20 20 20 20 20 70 44 65 6c 65 74 65 20          pDelete 
89b0: 3d 20 73 71 6c 69 74 65 33 48 61 73 68 49 6e 73  = sqlite3HashIns
89c0: 65 72 74 28 0a 20 20 20 20 20 20 20 20 20 20 26  ert(.          &
89d0: 61 73 79 6e 63 2e 61 4c 6f 63 6b 2c 20 70 44 61  async.aLock, pDa
89e0: 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70 44 61 74 61  ta->zName, pData
89f0: 2d 3e 6e 4e 61 6d 65 2c 20 28 76 6f 69 64 20 2a  ->nName, (void *
8a00: 29 70 4c 6f 63 6b 0a 20 20 20 20 20 20 20 20 29  )pLock.        )
8a10: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 70 44  ;.        if( pD
8a20: 65 6c 65 74 65 20 29 7b 0a 20 20 20 20 20 20 20  elete ){.       
8a30: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e     rc = SQLITE_N
8a40: 4f 4d 45 4d 3b 0a 20 20 20 20 20 20 20 20 20 20  OMEM;.          
8a50: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 4c 6f  sqlite3_free(pLo
8a60: 63 6b 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  ck);.        }. 
8a70: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
8a80: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
8a90: 4e 4f 4d 45 4d 3b 0a 20 20 20 20 20 20 7d 0a 20  NOMEM;.      }. 
8aa0: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20     }.  }..  if( 
8ab0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
8ac0: 0a 20 20 20 20 48 61 73 68 45 6c 65 6d 20 2a 70  .    HashElem *p
8ad0: 45 6c 65 6d 3b 0a 20 20 20 20 70 2d 3e 70 4d 65  Elem;.    p->pMe
8ae0: 74 68 6f 64 20 3d 20 26 61 73 79 6e 63 5f 6d 65  thod = &async_me
8af0: 74 68 6f 64 73 3b 0a 20 20 20 20 70 2d 3e 70 44  thods;.    p->pD
8b00: 61 74 61 20 3d 20 70 44 61 74 61 3b 0a 0a 20 20  ata = pData;..  
8b10: 20 20 2f 2a 20 4c 69 6e 6b 20 41 73 79 6e 63 46    /* Link AsyncF
8b20: 69 6c 65 44 61 74 61 2e 6c 6f 63 6b 20 69 6e 74  ileData.lock int
8b30: 6f 20 74 68 65 20 6c 69 6e 6b 65 64 20 6c 69 73  o the linked lis
8b40: 74 20 6f 66 20 0a 20 20 20 20 2a 2a 20 41 73 79  t of .    ** Asy
8b50: 6e 63 46 69 6c 65 4c 6f 63 6b 20 73 74 72 75 63  ncFileLock struc
8b60: 74 75 72 65 73 20 66 6f 72 20 74 68 69 73 20 66  tures for this f
8b70: 69 6c 65 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20  ile..    */.    
8b80: 70 44 61 74 61 2d 3e 6c 6f 63 6b 2e 70 4e 65 78  pData->lock.pNex
8b90: 74 20 3d 20 70 4c 6f 63 6b 2d 3e 70 4c 69 73 74  t = pLock->pList
8ba0: 3b 0a 20 20 20 20 70 4c 6f 63 6b 2d 3e 70 4c 69  ;.    pLock->pLi
8bb0: 73 74 20 3d 20 26 70 44 61 74 61 2d 3e 6c 6f 63  st = &pData->loc
8bc0: 6b 3b 0a 0a 20 20 20 20 70 45 6c 65 6d 20 3d 20  k;..    pElem = 
8bd0: 73 71 6c 69 74 65 33 48 61 73 68 46 69 6e 64 45  sqlite3HashFindE
8be0: 6c 65 6d 28 26 61 73 79 6e 63 2e 61 4c 6f 63 6b  lem(&async.aLock
8bf0: 2c 20 70 44 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20  , pData->zName, 
8c00: 70 44 61 74 61 2d 3e 6e 4e 61 6d 65 29 3b 0a 20  pData->nName);. 
8c10: 20 20 20 70 44 61 74 61 2d 3e 7a 4e 61 6d 65 20     pData->zName 
8c20: 3d 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74 65  = (char *)sqlite
8c30: 48 61 73 68 4b 65 79 28 70 45 6c 65 6d 29 3b 0a  HashKey(pElem);.
8c40: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 73 71 6c    }else{.    sql
8c50: 69 74 65 33 4f 73 43 6c 6f 73 65 28 70 44 61 74  ite3OsClose(pDat
8c60: 61 2d 3e 70 42 61 73 65 52 65 61 64 29 3b 0a 20  a->pBaseRead);. 
8c70: 20 20 20 73 71 6c 69 74 65 33 4f 73 43 6c 6f 73     sqlite3OsClos
8c80: 65 28 70 44 61 74 61 2d 3e 70 42 61 73 65 57 72  e(pData->pBaseWr
8c90: 69 74 65 29 3b 0a 20 20 20 20 73 71 6c 69 74 65  ite);.    sqlite
8ca0: 33 5f 66 72 65 65 28 70 44 61 74 61 29 3b 0a 20  3_free(pData);. 
8cb0: 20 7d 0a 0a 20 20 70 74 68 72 65 61 64 5f 6d 75   }..  pthread_mu
8cc0: 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e  tex_unlock(&asyn
8cd0: 63 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 0a 20  c.lockMutex);.. 
8ce0: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
8cf0: 4f 4b 20 29 7b 0a 20 20 20 20 69 6e 63 72 4f 70  OK ){.    incrOp
8d00: 65 6e 46 69 6c 65 43 6f 75 6e 74 28 29 3b 0a 20  enFileCount();. 
8d10: 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51   }..  if( rc==SQ
8d20: 4c 49 54 45 5f 4f 4b 20 26 26 20 69 73 45 78 63  LITE_OK && isExc
8d30: 6c 75 73 69 76 65 20 29 7b 0a 20 20 20 20 72 63  lusive ){.    rc
8d40: 20 3d 20 61 64 64 4e 65 77 41 73 79 6e 63 57 72   = addNewAsyncWr
8d50: 69 74 65 28 70 44 61 74 61 2c 20 41 53 59 4e 43  ite(pData, ASYNC
8d60: 5f 4f 50 45 4e 45 58 43 4c 55 53 49 56 45 2c 20  _OPENEXCLUSIVE, 
8d70: 28 69 36 34 29 66 6c 61 67 73 2c 20 30 2c 20 30  (i64)flags, 0, 0
8d80: 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53  );.    if( rc==S
8d90: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
8da0: 20 20 69 66 28 20 70 4f 75 74 46 6c 61 67 73 20    if( pOutFlags 
8db0: 29 20 2a 70 4f 75 74 46 6c 61 67 73 20 3d 20 66  ) *pOutFlags = f
8dc0: 6c 61 67 73 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  lags;.    }else{
8dd0: 0a 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d  .      pthread_m
8de0: 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63  utex_lock(&async
8df0: 2e 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20 20 20  .lockMutex);.   
8e00: 20 20 20 75 6e 6c 69 6e 6b 41 73 79 6e 63 46 69     unlinkAsyncFi
8e10: 6c 65 28 70 44 61 74 61 29 3b 0a 20 20 20 20 20  le(pData);.     
8e20: 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 75   pthread_mutex_u
8e30: 6e 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 6c 6f 63  nlock(&async.loc
8e40: 6b 4d 75 74 65 78 29 3b 0a 20 20 20 20 20 20 73  kMutex);.      s
8e50: 71 6c 69 74 65 33 5f 66 72 65 65 28 70 44 61 74  qlite3_free(pDat
8e60: 61 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  a);.    }.  }.  
8e70: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
8e80: 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74 61 74 69  .** Implementati
8e90: 6f 6e 20 6f 66 20 73 71 6c 69 74 65 33 4f 73 44  on of sqlite3OsD
8ea0: 65 6c 65 74 65 2e 20 41 64 64 20 61 6e 20 65 6e  elete. Add an en
8eb0: 74 72 79 20 74 6f 20 74 68 65 20 65 6e 64 20 6f  try to the end o
8ec0: 66 20 74 68 65 20 0a 2a 2a 20 77 72 69 74 65 2d  f the .** write-
8ed0: 6f 70 20 71 75 65 75 65 20 74 6f 20 70 65 72 66  op queue to perf
8ee0: 6f 72 6d 20 74 68 65 20 64 65 6c 65 74 65 2e 0a  orm the delete..
8ef0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73  */.static int as
8f00: 79 6e 63 44 65 6c 65 74 65 28 73 71 6c 69 74 65  yncDelete(sqlite
8f10: 33 5f 76 66 73 20 2a 70 41 73 79 6e 63 56 66 73  3_vfs *pAsyncVfs
8f20: 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 2c  , const char *z,
8f30: 20 69 6e 74 20 73 79 6e 63 44 69 72 29 7b 0a 20   int syncDir){. 
8f40: 20 72 65 74 75 72 6e 20 61 64 64 4e 65 77 41 73   return addNewAs
8f50: 79 6e 63 57 72 69 74 65 28 30 2c 20 41 53 59 4e  yncWrite(0, ASYN
8f60: 43 5f 44 45 4c 45 54 45 2c 20 73 79 6e 63 44 69  C_DELETE, syncDi
8f70: 72 2c 20 73 74 72 6c 65 6e 28 7a 29 2b 31 2c 20  r, strlen(z)+1, 
8f80: 7a 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70  z);.}../*.** Imp
8f90: 6c 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 73  lementation of s
8fa0: 71 6c 69 74 65 33 4f 73 41 63 63 65 73 73 2e 20  qlite3OsAccess. 
8fb0: 54 68 69 73 20 6d 65 74 68 6f 64 20 68 6f 6c 64  This method hold
8fc0: 73 20 74 68 65 20 6d 75 74 65 78 20 66 72 6f 6d  s the mutex from
8fd0: 0a 2a 2a 20 73 74 61 72 74 20 74 6f 20 66 69 6e  .** start to fin
8fe0: 69 73 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ish..*/.static i
8ff0: 6e 74 20 61 73 79 6e 63 41 63 63 65 73 73 28 73  nt asyncAccess(s
9000: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 41 73 79  qlite3_vfs *pAsy
9010: 6e 63 56 66 73 2c 20 63 6f 6e 73 74 20 63 68 61  ncVfs, const cha
9020: 72 20 2a 7a 4e 61 6d 65 2c 20 69 6e 74 20 66 6c  r *zName, int fl
9030: 61 67 73 29 7b 0a 20 20 69 6e 74 20 72 65 74 3b  ags){.  int ret;
9040: 0a 20 20 41 73 79 6e 63 57 72 69 74 65 20 2a 70  .  AsyncWrite *p
9050: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  ;.  sqlite3_vfs 
9060: 2a 70 56 66 73 20 3d 20 28 73 71 6c 69 74 65 33  *pVfs = (sqlite3
9070: 5f 76 66 73 20 2a 29 70 41 73 79 6e 63 56 66 73  _vfs *)pAsyncVfs
9080: 2d 3e 70 41 70 70 44 61 74 61 3b 0a 0a 20 20 61  ->pAppData;..  a
9090: 73 73 65 72 74 28 66 6c 61 67 73 3d 3d 53 51 4c  ssert(flags==SQL
90a0: 49 54 45 5f 41 43 43 45 53 53 5f 52 45 41 44 57  ITE_ACCESS_READW
90b0: 52 49 54 45 20 0a 20 20 20 20 20 20 7c 7c 20 66  RITE .      || f
90c0: 6c 61 67 73 3d 3d 53 51 4c 49 54 45 5f 41 43 43  lags==SQLITE_ACC
90d0: 45 53 53 5f 52 45 41 44 20 0a 20 20 20 20 20 20  ESS_READ .      
90e0: 7c 7c 20 66 6c 61 67 73 3d 3d 53 51 4c 49 54 45  || flags==SQLITE
90f0: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 20 0a  _ACCESS_EXISTS .
9100: 20 20 29 3b 0a 0a 20 20 70 74 68 72 65 61 64 5f    );..  pthread_
9110: 6d 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e  mutex_lock(&asyn
9120: 63 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a 20  c.queueMutex);. 
9130: 20 72 65 74 20 3d 20 73 71 6c 69 74 65 33 4f 73   ret = sqlite3Os
9140: 41 63 63 65 73 73 28 70 56 66 73 2c 20 7a 4e 61  Access(pVfs, zNa
9150: 6d 65 2c 20 66 6c 61 67 73 29 3b 0a 20 20 69 66  me, flags);.  if
9160: 28 20 66 6c 61 67 73 3d 3d 53 51 4c 49 54 45 5f  ( flags==SQLITE_
9170: 41 43 43 45 53 53 5f 45 58 49 53 54 53 20 29 7b  ACCESS_EXISTS ){
9180: 0a 20 20 20 20 66 6f 72 28 70 3d 61 73 79 6e 63  .    for(p=async
9190: 2e 70 51 75 65 75 65 46 69 72 73 74 3b 20 70 3b  .pQueueFirst; p;
91a0: 20 70 20 3d 20 70 2d 3e 70 4e 65 78 74 29 7b 0a   p = p->pNext){.
91b0: 20 20 20 20 20 20 69 66 28 20 70 2d 3e 6f 70 3d        if( p->op=
91c0: 3d 41 53 59 4e 43 5f 44 45 4c 45 54 45 20 26 26  =ASYNC_DELETE &&
91d0: 20 30 3d 3d 73 74 72 63 6d 70 28 70 2d 3e 7a 42   0==strcmp(p->zB
91e0: 75 66 2c 20 7a 4e 61 6d 65 29 20 29 7b 0a 20 20  uf, zName) ){.  
91f0: 20 20 20 20 20 20 72 65 74 20 3d 20 30 3b 0a 20        ret = 0;. 
9200: 20 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 70       }else if( p
9210: 2d 3e 6f 70 3d 3d 41 53 59 4e 43 5f 4f 50 45 4e  ->op==ASYNC_OPEN
9220: 45 58 43 4c 55 53 49 56 45 20 0a 20 20 20 20 20  EXCLUSIVE .     
9230: 20 20 20 20 20 20 20 20 26 26 20 30 3d 3d 73 74          && 0==st
9240: 72 63 6d 70 28 70 2d 3e 70 46 69 6c 65 44 61 74  rcmp(p->pFileDat
9250: 61 2d 3e 7a 4e 61 6d 65 2c 20 7a 4e 61 6d 65 29  a->zName, zName)
9260: 20 0a 20 20 20 20 20 20 29 7b 0a 20 20 20 20 20   .      ){.     
9270: 20 20 20 72 65 74 20 3d 20 31 3b 0a 20 20 20 20     ret = 1;.    
9280: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20    }.    }.  }.  
9290: 41 53 59 4e 43 5f 54 52 41 43 45 28 28 22 41 43  ASYNC_TRACE(("AC
92a0: 43 45 53 53 28 25 73 29 3a 20 25 73 20 3d 20 25  CESS(%s): %s = %
92b0: 64 5c 6e 22 2c 20 0a 20 20 20 20 66 6c 61 67 73  d\n", .    flags
92c0: 3d 3d 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f  ==SQLITE_ACCESS_
92d0: 52 45 41 44 57 52 49 54 45 3f 22 72 65 61 64 2d  READWRITE?"read-
92e0: 77 72 69 74 65 22 3a 0a 20 20 20 20 66 6c 61 67  write":.    flag
92f0: 73 3d 3d 53 51 4c 49 54 45 5f 41 43 43 45 53 53  s==SQLITE_ACCESS
9300: 5f 52 45 41 44 3f 22 72 65 61 64 22 3a 22 65 78  _READ?"read":"ex
9310: 69 73 74 73 22 0a 20 20 20 20 2c 20 7a 4e 61 6d  ists".    , zNam
9320: 65 2c 20 72 65 74 29 0a 20 20 29 3b 0a 20 20 70  e, ret).  );.  p
9330: 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c  thread_mutex_unl
9340: 6f 63 6b 28 26 61 73 79 6e 63 2e 71 75 65 75 65  ock(&async.queue
9350: 4d 75 74 65 78 29 3b 0a 20 20 72 65 74 75 72 6e  Mutex);.  return
9360: 20 72 65 74 3b 0a 7d 0a 0a 73 74 61 74 69 63 20   ret;.}..static 
9370: 69 6e 74 20 61 73 79 6e 63 47 65 74 54 65 6d 70  int asyncGetTemp
9380: 6e 61 6d 65 28 73 71 6c 69 74 65 33 5f 76 66 73  name(sqlite3_vfs
9390: 20 2a 70 41 73 79 6e 63 56 66 73 2c 20 69 6e 74   *pAsyncVfs, int
93a0: 20 6e 42 75 66 4f 75 74 2c 20 63 68 61 72 20 2a   nBufOut, char *
93b0: 7a 42 75 66 4f 75 74 29 7b 0a 20 20 73 71 6c 69  zBufOut){.  sqli
93c0: 74 65 33 5f 76 66 73 20 2a 70 56 66 73 20 3d 20  te3_vfs *pVfs = 
93d0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 29 70  (sqlite3_vfs *)p
93e0: 41 73 79 6e 63 56 66 73 2d 3e 70 41 70 70 44 61  AsyncVfs->pAppDa
93f0: 74 61 3b 0a 20 20 72 65 74 75 72 6e 20 70 56 66  ta;.  return pVf
9400: 73 2d 3e 78 47 65 74 54 65 6d 70 6e 61 6d 65 28  s->xGetTempname(
9410: 70 56 66 73 2c 20 6e 42 75 66 4f 75 74 2c 20 7a  pVfs, nBufOut, z
9420: 42 75 66 4f 75 74 29 3b 0a 7d 0a 0a 2f 2a 0a 2a  BufOut);.}../*.*
9430: 2a 20 46 69 6c 6c 20 69 6e 20 7a 50 61 74 68 4f  * Fill in zPathO
9440: 75 74 20 77 69 74 68 20 74 68 65 20 66 75 6c 6c  ut with the full
9450: 20 70 61 74 68 20 74 6f 20 74 68 65 20 66 69 6c   path to the fil
9460: 65 20 69 64 65 6e 74 69 66 69 65 64 20 62 79 20  e identified by 
9470: 7a 50 61 74 68 2e 0a 2a 2f 0a 73 74 61 74 69 63  zPath..*/.static
9480: 20 69 6e 74 20 61 73 79 6e 63 46 75 6c 6c 50 61   int asyncFullPa
9490: 74 68 6e 61 6d 65 28 0a 20 20 73 71 6c 69 74 65  thname(.  sqlite
94a0: 33 5f 76 66 73 20 2a 70 41 73 79 6e 63 56 66 73  3_vfs *pAsyncVfs
94b0: 2c 20 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  , .  const char 
94c0: 2a 7a 50 61 74 68 2c 20 0a 20 20 69 6e 74 20 6e  *zPath, .  int n
94d0: 50 61 74 68 4f 75 74 2c 0a 20 20 63 68 61 72 20  PathOut,.  char 
94e0: 2a 7a 50 61 74 68 4f 75 74 0a 29 7b 0a 20 20 69  *zPathOut.){.  i
94f0: 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33  nt rc;.  sqlite3
9500: 5f 76 66 73 20 2a 70 56 66 73 20 3d 20 28 73 71  _vfs *pVfs = (sq
9510: 6c 69 74 65 33 5f 76 66 73 20 2a 29 70 41 73 79  lite3_vfs *)pAsy
9520: 6e 63 56 66 73 2d 3e 70 41 70 70 44 61 74 61 3b  ncVfs->pAppData;
9530: 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 4f  .  rc = sqlite3O
9540: 73 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 70 56  sFullPathname(pV
9550: 66 73 2c 20 7a 50 61 74 68 2c 20 6e 50 61 74 68  fs, zPath, nPath
9560: 4f 75 74 2c 20 7a 50 61 74 68 4f 75 74 29 3b 0a  Out, zPathOut);.
9570: 0a 20 20 2f 2a 20 42 65 63 61 75 73 65 20 6f 66  .  /* Because of
9580: 20 74 68 65 20 77 61 79 20 69 6e 74 72 61 2d 70   the way intra-p
9590: 72 6f 63 65 73 73 20 66 69 6c 65 20 6c 6f 63 6b  rocess file lock
95a0: 69 6e 67 20 77 6f 72 6b 73 2c 20 74 68 69 73 20  ing works, this 
95b0: 62 61 63 6b 65 6e 64 0a 20 20 2a 2a 20 6e 65 65  backend.  ** nee
95c0: 64 73 20 74 6f 20 72 65 74 75 72 6e 20 61 20 63  ds to return a c
95d0: 61 6e 6f 6e 69 63 61 6c 20 70 61 74 68 2e 20 54  anonical path. T
95e0: 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 62 6c 6f  he following blo
95f0: 63 6b 20 61 73 73 75 6d 65 73 20 74 68 65 0a 20  ck assumes the. 
9600: 20 2a 2a 20 66 69 6c 65 2d 73 79 73 74 65 6d 20   ** file-system 
9610: 75 73 65 73 20 75 6e 69 78 20 73 74 79 6c 65 20  uses unix style 
9620: 70 61 74 68 73 2e 20 0a 20 20 2a 2f 0a 20 20 69  paths. .  */.  i
9630: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
9640: 20 29 7b 0a 20 20 20 20 69 6e 74 20 69 49 6e 3b   ){.    int iIn;
9650: 0a 20 20 20 20 69 6e 74 20 69 4f 75 74 20 3d 20  .    int iOut = 
9660: 30 3b 0a 20 20 20 20 69 6e 74 20 6e 50 61 74 68  0;.    int nPath
9670: 4f 75 74 20 3d 20 73 74 72 6c 65 6e 28 7a 50 61  Out = strlen(zPa
9680: 74 68 4f 75 74 29 3b 0a 0a 20 20 20 20 66 6f 72  thOut);..    for
9690: 28 69 49 6e 3d 30 3b 20 69 49 6e 3c 6e 50 61 74  (iIn=0; iIn<nPat
96a0: 68 4f 75 74 3b 20 69 49 6e 2b 2b 29 7b 0a 0a 20  hOut; iIn++){.. 
96b0: 20 20 20 20 20 2f 2a 20 52 65 70 6c 61 63 65 20       /* Replace 
96c0: 61 6e 79 20 6f 63 63 75 72 65 6e 63 65 73 20 6f  any occurences o
96d0: 66 20 22 2f 2f 22 20 77 69 74 68 20 22 2f 22 20  f "//" with "/" 
96e0: 2a 2f 0a 20 20 20 20 20 20 69 66 28 20 69 49 6e  */.      if( iIn
96f0: 3c 3d 28 6e 50 61 74 68 4f 75 74 2d 32 29 20 26  <=(nPathOut-2) &
9700: 26 20 7a 50 61 74 68 4f 75 74 5b 69 49 6e 5d 3d  & zPathOut[iIn]=
9710: 3d 27 2f 27 20 26 26 20 7a 50 61 74 68 4f 75 74  ='/' && zPathOut
9720: 5b 69 49 6e 2b 31 5d 3d 3d 27 2f 27 0a 20 20 20  [iIn+1]=='/'.   
9730: 20 20 20 29 7b 0a 20 20 20 20 20 20 20 20 63 6f     ){.        co
9740: 6e 74 69 6e 75 65 3b 0a 20 20 20 20 20 20 7d 0a  ntinue;.      }.
9750: 0a 20 20 20 20 20 20 2f 2a 20 52 65 70 6c 61 63  .      /* Replac
9760: 65 20 61 6e 79 20 6f 63 63 75 72 65 6e 63 65 73  e any occurences
9770: 20 6f 66 20 22 2f 2e 2f 22 20 77 69 74 68 20 22   of "/./" with "
9780: 2f 22 20 2a 2f 0a 20 20 20 20 20 20 69 66 28 20  /" */.      if( 
9790: 69 49 6e 3c 3d 28 6e 50 61 74 68 4f 75 74 2d 33  iIn<=(nPathOut-3
97a0: 29 20 0a 20 20 20 20 20 20 20 26 26 20 7a 50 61  ) .       && zPa
97b0: 74 68 4f 75 74 5b 69 49 6e 5d 3d 3d 27 2f 27 20  thOut[iIn]=='/' 
97c0: 26 26 20 7a 50 61 74 68 4f 75 74 5b 69 49 6e 2b  && zPathOut[iIn+
97d0: 31 5d 3d 3d 27 2e 27 20 26 26 20 7a 50 61 74 68  1]=='.' && zPath
97e0: 4f 75 74 5b 69 49 6e 2b 32 5d 3d 3d 27 2f 27 0a  Out[iIn+2]=='/'.
97f0: 20 20 20 20 20 20 29 7b 0a 20 20 20 20 20 20 20        ){.       
9800: 20 69 49 6e 2b 2b 3b 0a 20 20 20 20 20 20 20 20   iIn++;.        
9810: 63 6f 6e 74 69 6e 75 65 3b 0a 20 20 20 20 20 20  continue;.      
9820: 7d 0a 0a 20 20 20 20 20 20 2f 2a 20 52 65 70 6c  }..      /* Repl
9830: 61 63 65 20 61 6e 79 20 6f 63 63 75 72 65 6e 63  ace any occurenc
9840: 65 73 20 6f 66 20 22 3c 70 61 74 68 2d 63 6f 6d  es of "<path-com
9850: 70 6f 6e 65 6e 74 3e 2f 2e 2e 2f 22 20 77 69 74  ponent>/../" wit
9860: 68 20 22 22 20 2a 2f 0a 20 20 20 20 20 20 69 66  h "" */.      if
9870: 28 20 69 4f 75 74 3e 30 20 26 26 20 69 49 6e 3c  ( iOut>0 && iIn<
9880: 3d 28 6e 50 61 74 68 4f 75 74 2d 34 29 20 0a 20  =(nPathOut-4) . 
9890: 20 20 20 20 20 20 26 26 20 7a 50 61 74 68 4f 75        && zPathOu
98a0: 74 5b 69 49 6e 5d 3d 3d 27 2f 27 20 26 26 20 7a  t[iIn]=='/' && z
98b0: 50 61 74 68 4f 75 74 5b 69 49 6e 2b 31 5d 3d 3d  PathOut[iIn+1]==
98c0: 27 2e 27 20 0a 20 20 20 20 20 20 20 26 26 20 7a  '.' .       && z
98d0: 50 61 74 68 4f 75 74 5b 69 49 6e 2b 32 5d 3d 3d  PathOut[iIn+2]==
98e0: 27 2e 27 20 26 26 20 7a 50 61 74 68 4f 75 74 5b  '.' && zPathOut[
98f0: 69 49 6e 2b 33 5d 3d 3d 27 2f 27 0a 20 20 20 20  iIn+3]=='/'.    
9900: 20 20 29 7b 0a 20 20 20 20 20 20 20 20 69 49 6e    ){.        iIn
9910: 20 2b 3d 20 33 3b 0a 20 20 20 20 20 20 20 20 69   += 3;.        i
9920: 4f 75 74 2d 2d 3b 0a 20 20 20 20 20 20 20 20 66  Out--;.        f
9930: 6f 72 28 20 3b 20 69 4f 75 74 3e 30 20 26 26 20  or( ; iOut>0 && 
9940: 7a 50 61 74 68 4f 75 74 5b 69 4f 75 74 2d 31 5d  zPathOut[iOut-1]
9950: 21 3d 27 2f 27 3b 20 69 4f 75 74 2d 2d 29 3b 0a  !='/'; iOut--);.
9960: 20 20 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65          continue
9970: 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  ;.      }..     
9980: 20 7a 50 61 74 68 4f 75 74 5b 69 4f 75 74 2b 2b   zPathOut[iOut++
9990: 5d 20 3d 20 7a 50 61 74 68 4f 75 74 5b 69 49 6e  ] = zPathOut[iIn
99a0: 5d 3b 0a 20 20 20 20 7d 0a 20 20 20 20 7a 50 61  ];.    }.    zPa
99b0: 74 68 4f 75 74 5b 69 4f 75 74 5d 20 3d 20 27 5c  thOut[iOut] = '\
99c0: 30 27 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72  0';.  }..  retur
99d0: 6e 20 72 63 3b 0a 7d 0a 73 74 61 74 69 63 20 76  n rc;.}.static v
99e0: 6f 69 64 20 2a 61 73 79 6e 63 44 6c 4f 70 65 6e  oid *asyncDlOpen
99f0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 41  (sqlite3_vfs *pA
9a00: 73 79 6e 63 56 66 73 2c 20 63 6f 6e 73 74 20 63  syncVfs, const c
9a10: 68 61 72 20 2a 7a 50 61 74 68 29 7b 0a 20 20 73  har *zPath){.  s
9a20: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73  qlite3_vfs *pVfs
9a30: 20 3d 20 28 73 71 6c 69 74 65 33 5f 76 66 73 20   = (sqlite3_vfs 
9a40: 2a 29 70 41 73 79 6e 63 56 66 73 2d 3e 70 41 70  *)pAsyncVfs->pAp
9a50: 70 44 61 74 61 3b 0a 20 20 72 65 74 75 72 6e 20  pData;.  return 
9a60: 70 56 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 70 56  pVfs->xDlOpen(pV
9a70: 66 73 2c 20 7a 50 61 74 68 29 3b 0a 7d 0a 73 74  fs, zPath);.}.st
9a80: 61 74 69 63 20 76 6f 69 64 20 61 73 79 6e 63 44  atic void asyncD
9a90: 6c 45 72 72 6f 72 28 73 71 6c 69 74 65 33 5f 76  lError(sqlite3_v
9aa0: 66 73 20 2a 70 41 73 79 6e 63 56 66 73 2c 20 69  fs *pAsyncVfs, i
9ab0: 6e 74 20 6e 42 79 74 65 2c 20 63 68 61 72 20 2a  nt nByte, char *
9ac0: 7a 45 72 72 4d 73 67 29 7b 0a 20 20 73 71 6c 69  zErrMsg){.  sqli
9ad0: 74 65 33 5f 76 66 73 20 2a 70 56 66 73 20 3d 20  te3_vfs *pVfs = 
9ae0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 29 70  (sqlite3_vfs *)p
9af0: 41 73 79 6e 63 56 66 73 2d 3e 70 41 70 70 44 61  AsyncVfs->pAppDa
9b00: 74 61 3b 0a 20 20 70 56 66 73 2d 3e 78 44 6c 45  ta;.  pVfs->xDlE
9b10: 72 72 6f 72 28 70 56 66 73 2c 20 6e 42 79 74 65  rror(pVfs, nByte
9b20: 2c 20 7a 45 72 72 4d 73 67 29 3b 0a 7d 0a 73 74  , zErrMsg);.}.st
9b30: 61 74 69 63 20 76 6f 69 64 20 2a 61 73 79 6e 63  atic void *async
9b40: 44 6c 53 79 6d 28 0a 20 20 73 71 6c 69 74 65 33  DlSym(.  sqlite3
9b50: 5f 76 66 73 20 2a 70 41 73 79 6e 63 56 66 73 2c  _vfs *pAsyncVfs,
9b60: 20 0a 20 20 76 6f 69 64 20 2a 70 48 61 6e 64 6c   .  void *pHandl
9b70: 65 2c 20 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  e, .  const char
9b80: 20 2a 7a 53 79 6d 62 6f 6c 0a 29 7b 0a 20 20 73   *zSymbol.){.  s
9b90: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73  qlite3_vfs *pVfs
9ba0: 20 3d 20 28 73 71 6c 69 74 65 33 5f 76 66 73 20   = (sqlite3_vfs 
9bb0: 2a 29 70 41 73 79 6e 63 56 66 73 2d 3e 70 41 70  *)pAsyncVfs->pAp
9bc0: 70 44 61 74 61 3b 0a 20 20 72 65 74 75 72 6e 20  pData;.  return 
9bd0: 70 56 66 73 2d 3e 78 44 6c 53 79 6d 28 70 56 66  pVfs->xDlSym(pVf
9be0: 73 2c 20 70 48 61 6e 64 6c 65 2c 20 7a 53 79 6d  s, pHandle, zSym
9bf0: 62 6f 6c 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76  bol);.}.static v
9c00: 6f 69 64 20 61 73 79 6e 63 44 6c 43 6c 6f 73 65  oid asyncDlClose
9c10: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 41  (sqlite3_vfs *pA
9c20: 73 79 6e 63 56 66 73 2c 20 76 6f 69 64 20 2a 70  syncVfs, void *p
9c30: 48 61 6e 64 6c 65 29 7b 0a 20 20 73 71 6c 69 74  Handle){.  sqlit
9c40: 65 33 5f 76 66 73 20 2a 70 56 66 73 20 3d 20 28  e3_vfs *pVfs = (
9c50: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 29 70 41  sqlite3_vfs *)pA
9c60: 73 79 6e 63 56 66 73 2d 3e 70 41 70 70 44 61 74  syncVfs->pAppDat
9c70: 61 3b 0a 20 20 70 56 66 73 2d 3e 78 44 6c 43 6c  a;.  pVfs->xDlCl
9c80: 6f 73 65 28 70 56 66 73 2c 20 70 48 61 6e 64 6c  ose(pVfs, pHandl
9c90: 65 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  e);.}.static int
9ca0: 20 61 73 79 6e 63 52 61 6e 64 6f 6d 6e 65 73 73   asyncRandomness
9cb0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 41  (sqlite3_vfs *pA
9cc0: 73 79 6e 63 56 66 73 2c 20 69 6e 74 20 6e 42 79  syncVfs, int nBy
9cd0: 74 65 2c 20 63 68 61 72 20 2a 7a 42 75 66 4f 75  te, char *zBufOu
9ce0: 74 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  t){.  sqlite3_vf
9cf0: 73 20 2a 70 56 66 73 20 3d 20 28 73 71 6c 69 74  s *pVfs = (sqlit
9d00: 65 33 5f 76 66 73 20 2a 29 70 41 73 79 6e 63 56  e3_vfs *)pAsyncV
9d10: 66 73 2d 3e 70 41 70 70 44 61 74 61 3b 0a 20 20  fs->pAppData;.  
9d20: 72 65 74 75 72 6e 20 70 56 66 73 2d 3e 78 52 61  return pVfs->xRa
9d30: 6e 64 6f 6d 6e 65 73 73 28 70 56 66 73 2c 20 6e  ndomness(pVfs, n
9d40: 42 79 74 65 2c 20 7a 42 75 66 4f 75 74 29 3b 0a  Byte, zBufOut);.
9d50: 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 61 73 79  }.static int asy
9d60: 6e 63 53 6c 65 65 70 28 73 71 6c 69 74 65 33 5f  ncSleep(sqlite3_
9d70: 76 66 73 20 2a 70 41 73 79 6e 63 56 66 73 2c 20  vfs *pAsyncVfs, 
9d80: 69 6e 74 20 6e 4d 69 63 72 6f 29 7b 0a 20 20 73  int nMicro){.  s
9d90: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73  qlite3_vfs *pVfs
9da0: 20 3d 20 28 73 71 6c 69 74 65 33 5f 76 66 73 20   = (sqlite3_vfs 
9db0: 2a 29 70 41 73 79 6e 63 56 66 73 2d 3e 70 41 70  *)pAsyncVfs->pAp
9dc0: 70 44 61 74 61 3b 0a 20 20 72 65 74 75 72 6e 20  pData;.  return 
9dd0: 70 56 66 73 2d 3e 78 53 6c 65 65 70 28 70 56 66  pVfs->xSleep(pVf
9de0: 73 2c 20 6e 4d 69 63 72 6f 29 3b 0a 7d 0a 73 74  s, nMicro);.}.st
9df0: 61 74 69 63 20 69 6e 74 20 61 73 79 6e 63 43 75  atic int asyncCu
9e00: 72 72 65 6e 74 54 69 6d 65 28 73 71 6c 69 74 65  rrentTime(sqlite
9e10: 33 5f 76 66 73 20 2a 70 41 73 79 6e 63 56 66 73  3_vfs *pAsyncVfs
9e20: 2c 20 64 6f 75 62 6c 65 20 2a 70 54 69 6d 65 4f  , double *pTimeO
9e30: 75 74 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 76  ut){.  sqlite3_v
9e40: 66 73 20 2a 70 56 66 73 20 3d 20 28 73 71 6c 69  fs *pVfs = (sqli
9e50: 74 65 33 5f 76 66 73 20 2a 29 70 41 73 79 6e 63  te3_vfs *)pAsync
9e60: 56 66 73 2d 3e 70 41 70 70 44 61 74 61 3b 0a 20  Vfs->pAppData;. 
9e70: 20 72 65 74 75 72 6e 20 70 56 66 73 2d 3e 78 43   return pVfs->xC
9e80: 75 72 72 65 6e 74 54 69 6d 65 28 70 56 66 73 2c  urrentTime(pVfs,
9e90: 20 70 54 69 6d 65 4f 75 74 29 3b 0a 7d 0a 0a 73   pTimeOut);.}..s
9ea0: 74 61 74 69 63 20 73 71 6c 69 74 65 33 5f 76 66  tatic sqlite3_vf
9eb0: 73 20 61 73 79 6e 63 5f 76 66 73 20 3d 20 7b 0a  s async_vfs = {.
9ec0: 20 20 31 2c 20 20 20 20 20 20 20 20 20 20 20 20    1,            
9ed0: 20 20 20 20 20 20 20 20 2f 2a 20 69 56 65 72 73          /* iVers
9ee0: 69 6f 6e 20 2a 2f 0a 20 20 73 69 7a 65 6f 66 28  ion */.  sizeof(
9ef0: 41 73 79 6e 63 46 69 6c 65 29 2c 20 20 20 20 2f  AsyncFile),    /
9f00: 2a 20 73 7a 4f 73 46 69 6c 65 20 2a 2f 0a 20 20  * szOsFile */.  
9f10: 30 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0,              
9f20: 20 20 20 20 20 20 2f 2a 20 6d 78 50 61 74 68 6e        /* mxPathn
9f30: 61 6d 65 20 2a 2f 0a 20 20 30 2c 20 20 20 20 20  ame */.  0,     
9f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
9f50: 2a 20 70 4e 65 78 74 20 2a 2f 0a 20 20 22 61 73  * pNext */.  "as
9f60: 79 6e 63 22 2c 20 20 20 20 20 20 20 20 20 20 20  ync",           
9f70: 20 20 20 2f 2a 20 7a 4e 61 6d 65 20 2a 2f 0a 20     /* zName */. 
9f80: 20 30 2c 20 20 20 20 20 20 20 20 20 20 20 20 20   0,             
9f90: 20 20 20 20 20 20 20 2f 2a 20 70 41 70 70 44 61         /* pAppDa
9fa0: 74 61 20 2a 2f 0a 20 20 61 73 79 6e 63 4f 70 65  ta */.  asyncOpe
9fb0: 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  n,            /*
9fc0: 20 78 4f 70 65 6e 20 2a 2f 0a 20 20 61 73 79 6e   xOpen */.  asyn
9fd0: 63 44 65 6c 65 74 65 2c 20 20 20 20 20 20 20 20  cDelete,        
9fe0: 20 20 2f 2a 20 78 44 65 6c 65 74 65 20 2a 2f 0a    /* xDelete */.
9ff0: 20 20 61 73 79 6e 63 41 63 63 65 73 73 2c 20 20    asyncAccess,  
a000: 20 20 20 20 20 20 20 20 2f 2a 20 78 41 63 63 65          /* xAcce
a010: 73 73 20 2a 2f 0a 20 20 61 73 79 6e 63 47 65 74  ss */.  asyncGet
a020: 54 65 6d 70 6e 61 6d 65 2c 20 20 20 20 20 2f 2a  Tempname,     /*
a030: 20 78 47 65 74 54 65 6d 70 4e 61 6d 65 20 2a 2f   xGetTempName */
a040: 0a 20 20 61 73 79 6e 63 46 75 6c 6c 50 61 74 68  .  asyncFullPath
a050: 6e 61 6d 65 2c 20 20 20 20 2f 2a 20 78 46 75 6c  name,    /* xFul
a060: 6c 50 61 74 68 6e 61 6d 65 20 2a 2f 0a 20 20 61  lPathname */.  a
a070: 73 79 6e 63 44 6c 4f 70 65 6e 2c 20 20 20 20 20  syncDlOpen,     
a080: 20 20 20 20 20 2f 2a 20 78 44 6c 4f 70 65 6e 20       /* xDlOpen 
a090: 2a 2f 0a 20 20 61 73 79 6e 63 44 6c 45 72 72 6f  */.  asyncDlErro
a0a0: 72 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 78 44  r,         /* xD
a0b0: 6c 45 72 72 6f 72 20 2a 2f 0a 20 20 61 73 79 6e  lError */.  asyn
a0c0: 63 44 6c 53 79 6d 2c 20 20 20 20 20 20 20 20 20  cDlSym,         
a0d0: 20 20 2f 2a 20 78 44 6c 53 79 6d 20 2a 2f 0a 20    /* xDlSym */. 
a0e0: 20 61 73 79 6e 63 44 6c 43 6c 6f 73 65 2c 20 20   asyncDlClose,  
a0f0: 20 20 20 20 20 20 20 2f 2a 20 78 44 6c 43 6c 6f         /* xDlClo
a100: 73 65 20 2a 2f 0a 20 20 61 73 79 6e 63 52 61 6e  se */.  asyncRan
a110: 64 6f 6d 6e 65 73 73 2c 20 20 20 20 20 20 2f 2a  domness,      /*
a120: 20 78 44 6c 45 72 72 6f 72 20 2a 2f 0a 20 20 61   xDlError */.  a
a130: 73 79 6e 63 53 6c 65 65 70 2c 20 20 20 20 20 20  syncSleep,      
a140: 20 20 20 20 20 2f 2a 20 78 44 6c 53 79 6d 20 2a       /* xDlSym *
a150: 2f 0a 20 20 61 73 79 6e 63 43 75 72 72 65 6e 74  /.  asyncCurrent
a160: 54 69 6d 65 20 20 20 20 20 20 2f 2a 20 78 44 6c  Time      /* xDl
a170: 43 6c 6f 73 65 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a  Close */.};../*.
a180: 2a 2a 20 43 61 6c 6c 20 74 68 69 73 20 72 6f 75  ** Call this rou
a190: 74 69 6e 65 20 74 6f 20 65 6e 61 62 6c 65 20 6f  tine to enable o
a1a0: 72 20 64 69 73 61 62 6c 65 20 74 68 65 0a 2a 2a  r disable the.**
a1b0: 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20 49 4f   asynchronous IO
a1c0: 20 66 65 61 74 75 72 65 73 20 69 6d 70 6c 65 6d   features implem
a1d0: 65 6e 74 65 64 20 69 6e 20 74 68 69 73 20 66 69  ented in this fi
a1e0: 6c 65 2e 20 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  le. .**.** This 
a1f0: 72 6f 75 74 69 6e 65 20 69 73 20 6e 6f 74 20 65  routine is not e
a200: 76 65 6e 20 72 65 6d 6f 74 65 6c 79 20 74 68 72  ven remotely thr
a210: 65 61 64 73 61 66 65 2e 20 20 44 6f 20 6e 6f 74  eadsafe.  Do not
a220: 20 63 61 6c 6c 0a 2a 2a 20 74 68 69 73 20 72 6f   call.** this ro
a230: 75 74 69 6e 65 20 77 68 69 6c 65 20 61 6e 79 20  utine while any 
a240: 53 51 4c 69 74 65 20 64 61 74 61 62 61 73 65 20  SQLite database 
a250: 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 61 72 65 20  connections are 
a260: 6f 70 65 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  open..*/.static 
a270: 76 6f 69 64 20 61 73 79 6e 63 45 6e 61 62 6c 65  void asyncEnable
a280: 28 69 6e 74 20 65 6e 61 62 6c 65 29 7b 0a 20 20  (int enable){.  
a290: 69 66 28 20 65 6e 61 62 6c 65 20 29 7b 0a 20 20  if( enable ){.  
a2a0: 20 20 69 66 28 20 21 61 73 79 6e 63 5f 76 66 73    if( !async_vfs
a2b0: 2e 70 41 70 70 44 61 74 61 20 29 7b 0a 20 20 20  .pAppData ){.   
a2c0: 20 20 20 73 74 61 74 69 63 20 69 6e 74 20 68 61     static int ha
a2d0: 73 68 54 61 62 6c 65 49 6e 69 74 20 3d 20 30 3b  shTableInit = 0;
a2e0: 0a 20 20 20 20 20 20 61 73 79 6e 63 5f 76 66 73  .      async_vfs
a2f0: 2e 70 41 70 70 44 61 74 61 20 3d 20 28 76 6f 69  .pAppData = (voi
a300: 64 20 2a 29 73 71 6c 69 74 65 33 5f 76 66 73 5f  d *)sqlite3_vfs_
a310: 66 69 6e 64 28 30 29 3b 0a 20 20 20 20 20 20 61  find(0);.      a
a320: 73 79 6e 63 5f 76 66 73 2e 6d 78 50 61 74 68 6e  sync_vfs.mxPathn
a330: 61 6d 65 20 3d 20 28 28 73 71 6c 69 74 65 33 5f  ame = ((sqlite3_
a340: 76 66 73 20 2a 29 61 73 79 6e 63 5f 76 66 73 2e  vfs *)async_vfs.
a350: 70 41 70 70 44 61 74 61 29 2d 3e 6d 78 50 61 74  pAppData)->mxPat
a360: 68 6e 61 6d 65 3b 0a 20 20 20 20 20 20 73 71 6c  hname;.      sql
a370: 69 74 65 33 5f 76 66 73 5f 72 65 67 69 73 74 65  ite3_vfs_registe
a380: 72 28 26 61 73 79 6e 63 5f 76 66 73 2c 20 31 29  r(&async_vfs, 1)
a390: 3b 0a 20 20 20 20 20 20 69 66 28 20 21 68 61 73  ;.      if( !has
a3a0: 68 54 61 62 6c 65 49 6e 69 74 20 29 7b 0a 20 20  hTableInit ){.  
a3b0: 20 20 20 20 20 20 73 71 6c 69 74 65 33 48 61 73        sqlite3Has
a3c0: 68 49 6e 69 74 28 26 61 73 79 6e 63 2e 61 4c 6f  hInit(&async.aLo
a3d0: 63 6b 2c 20 53 51 4c 49 54 45 5f 48 41 53 48 5f  ck, SQLITE_HASH_
a3e0: 42 49 4e 41 52 59 2c 20 31 29 3b 0a 20 20 20 20  BINARY, 1);.    
a3f0: 20 20 20 20 68 61 73 68 54 61 62 6c 65 49 6e 69      hashTableIni
a400: 74 20 3d 20 31 3b 0a 20 20 20 20 20 20 7d 0a 20  t = 1;.      }. 
a410: 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20     }.  }else{.  
a420: 20 20 69 66 28 20 61 73 79 6e 63 5f 76 66 73 2e    if( async_vfs.
a430: 70 41 70 70 44 61 74 61 20 29 7b 0a 20 20 20 20  pAppData ){.    
a440: 20 20 73 71 6c 69 74 65 33 5f 76 66 73 5f 75 6e    sqlite3_vfs_un
a450: 72 65 67 69 73 74 65 72 28 26 61 73 79 6e 63 5f  register(&async_
a460: 76 66 73 29 3b 0a 20 20 20 20 20 20 61 73 79 6e  vfs);.      asyn
a470: 63 5f 76 66 73 2e 70 41 70 70 44 61 74 61 20 3d  c_vfs.pAppData =
a480: 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 7d 0a   0;.    }.  }.}.
a490: 0a 2f 2a 20 0a 2a 2a 20 54 68 69 73 20 70 72 6f  ./* .** This pro
a4a0: 63 65 64 75 72 65 20 72 75 6e 73 20 69 6e 20 61  cedure runs in a
a4b0: 20 73 65 70 61 72 61 74 65 20 74 68 72 65 61 64   separate thread
a4c0: 2c 20 72 65 61 64 69 6e 67 20 6d 65 73 73 61 67  , reading messag
a4d0: 65 73 20 6f 66 66 20 6f 66 20 74 68 65 0a 2a 2a  es off of the.**
a4e0: 20 77 72 69 74 65 20 71 75 65 75 65 20 61 6e 64   write queue and
a4f0: 20 70 72 6f 63 65 73 73 69 6e 67 20 74 68 65 6d   processing them
a500: 20 6f 6e 65 20 62 79 20 6f 6e 65 2e 20 20 0a 2a   one by one.  .*
a510: 2a 0a 2a 2a 20 49 66 20 61 73 79 6e 63 2e 77 72  *.** If async.wr
a520: 69 74 65 72 48 61 6c 74 4e 6f 77 20 69 73 20 74  iterHaltNow is t
a530: 72 75 65 2c 20 74 68 65 6e 20 74 68 69 73 20 70  rue, then this p
a540: 72 6f 63 65 64 75 72 65 20 65 78 69 74 73 0a 2a  rocedure exits.*
a550: 2a 20 61 66 74 65 72 20 70 72 6f 63 65 73 73 69  * after processi
a560: 6e 67 20 61 20 73 69 6e 67 6c 65 20 6d 65 73 73  ng a single mess
a570: 61 67 65 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 61 73  age..**.** If as
a580: 79 6e 63 2e 77 72 69 74 65 72 48 61 6c 74 57 68  ync.writerHaltWh
a590: 65 6e 49 64 6c 65 20 69 73 20 74 72 75 65 2c 20  enIdle is true, 
a5a0: 74 68 65 6e 20 74 68 69 73 20 70 72 6f 63 65 64  then this proced
a5b0: 75 72 65 20 65 78 69 74 73 20 77 68 65 6e 0a 2a  ure exits when.*
a5c0: 2a 20 74 68 65 20 77 72 69 74 65 20 71 75 65 75  * the write queu
a5d0: 65 20 69 73 20 65 6d 70 74 79 2e 0a 2a 2a 0a 2a  e is empty..**.*
a5e0: 2a 20 49 66 20 62 6f 74 68 20 6f 66 20 74 68 65  * If both of the
a5f0: 20 61 62 6f 76 65 20 76 61 72 69 61 62 6c 65 73   above variables
a600: 20 61 72 65 20 66 61 6c 73 65 2c 20 74 68 69 73   are false, this
a610: 20 70 72 6f 63 65 64 75 72 65 20 72 75 6e 73 0a   procedure runs.
a620: 2a 2a 20 69 6e 64 65 66 69 6e 61 74 65 6c 79 2c  ** indefinately,
a630: 20 77 61 69 74 69 6e 67 20 66 6f 72 20 6f 70 65   waiting for ope
a640: 72 61 74 69 6f 6e 73 20 74 6f 20 62 65 20 61 64  rations to be ad
a650: 64 65 64 20 74 6f 20 74 68 65 20 77 72 69 74 65  ded to the write
a660: 20 71 75 65 75 65 0a 2a 2a 20 61 6e 64 20 70 72   queue.** and pr
a670: 6f 63 65 73 73 69 6e 67 20 74 68 65 6d 20 69 6e  ocessing them in
a680: 20 74 68 65 20 6f 72 64 65 72 20 69 6e 20 77 68   the order in wh
a690: 69 63 68 20 74 68 65 79 20 61 72 72 69 76 65 2e  ich they arrive.
a6a0: 0a 2a 2a 0a 2a 2a 20 41 6e 20 61 72 74 69 66 69  .**.** An artifi
a6b0: 63 61 6c 20 64 65 6c 61 79 20 6f 66 20 61 73 79  cal delay of asy
a6c0: 6e 63 2e 69 6f 44 65 6c 61 79 20 6d 69 6c 6c 69  nc.ioDelay milli
a6d0: 73 65 63 6f 6e 64 73 20 69 73 20 69 6e 73 65 72  seconds is inser
a6e0: 74 65 64 20 62 65 66 6f 72 65 0a 2a 2a 20 65 61  ted before.** ea
a6f0: 63 68 20 77 72 69 74 65 20 6f 70 65 72 61 74 69  ch write operati
a700: 6f 6e 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 73  on in order to s
a710: 69 6d 75 6c 61 74 65 20 74 68 65 20 65 66 66 65  imulate the effe
a720: 63 74 20 6f 66 20 61 20 73 6c 6f 77 20 64 69 73  ct of a slow dis
a730: 6b 2e 0a 2a 2a 0a 2a 2a 20 4f 6e 6c 79 20 6f 6e  k..**.** Only on
a740: 65 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68  e instance of th
a750: 69 73 20 70 72 6f 63 65 64 75 72 65 20 6d 61 79  is procedure may
a760: 20 62 65 20 72 75 6e 6e 69 6e 67 20 61 74 20 61   be running at a
a770: 20 74 69 6d 65 2e 0a 2a 2f 0a 73 74 61 74 69 63   time..*/.static
a780: 20 76 6f 69 64 20 2a 61 73 79 6e 63 57 72 69 74   void *asyncWrit
a790: 65 72 54 68 72 65 61 64 28 76 6f 69 64 20 2a 70  erThread(void *p
a7a0: 49 73 53 74 61 72 74 65 64 29 7b 0a 20 20 73 71  IsStarted){.  sq
a7b0: 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73 20  lite3_vfs *pVfs 
a7c0: 3d 20 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  = (sqlite3_vfs *
a7d0: 29 28 61 73 79 6e 63 5f 76 66 73 2e 70 41 70 70  )(async_vfs.pApp
a7e0: 44 61 74 61 29 3b 0a 20 20 41 73 79 6e 63 57 72  Data);.  AsyncWr
a7f0: 69 74 65 20 2a 70 20 3d 20 30 3b 0a 20 20 69 6e  ite *p = 0;.  in
a800: 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b  t rc = SQLITE_OK
a810: 3b 0a 20 20 69 6e 74 20 68 6f 6c 64 69 6e 67 4d  ;.  int holdingM
a820: 75 74 65 78 20 3d 20 30 3b 0a 0a 20 20 69 66 28  utex = 0;..  if(
a830: 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 74   pthread_mutex_t
a840: 72 79 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 77 72  rylock(&async.wr
a850: 69 74 65 72 4d 75 74 65 78 29 20 29 7b 0a 20 20  iterMutex) ){.  
a860: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 7d 0a    return 0;.  }.
a870: 20 20 28 2a 28 69 6e 74 20 2a 29 70 49 73 53 74    (*(int *)pIsSt
a880: 61 72 74 65 64 29 20 3d 20 31 3b 0a 20 20 77 68  arted) = 1;.  wh
a890: 69 6c 65 28 20 61 73 79 6e 63 2e 77 72 69 74 65  ile( async.write
a8a0: 72 48 61 6c 74 4e 6f 77 3d 3d 30 20 29 7b 0a 20  rHaltNow==0 ){. 
a8b0: 20 20 20 69 6e 74 20 64 6f 4e 6f 74 46 72 65 65     int doNotFree
a8c0: 20 3d 20 30 3b 0a 20 20 20 20 73 71 6c 69 74 65   = 0;.    sqlite
a8d0: 33 5f 66 69 6c 65 20 2a 70 42 61 73 65 20 3d 20  3_file *pBase = 
a8e0: 30 3b 0a 0a 20 20 20 20 69 66 28 20 21 68 6f 6c  0;..    if( !hol
a8f0: 64 69 6e 67 4d 75 74 65 78 20 29 7b 0a 20 20 20  dingMutex ){.   
a900: 20 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78     pthread_mutex
a910: 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 71 75 65  _lock(&async.que
a920: 75 65 4d 75 74 65 78 29 3b 0a 20 20 20 20 7d 0a  ueMutex);.    }.
a930: 20 20 20 20 77 68 69 6c 65 28 20 28 70 20 3d 20      while( (p = 
a940: 61 73 79 6e 63 2e 70 51 75 65 75 65 46 69 72 73  async.pQueueFirs
a950: 74 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 70  t)==0 ){.      p
a960: 74 68 72 65 61 64 5f 63 6f 6e 64 5f 62 72 6f 61  thread_cond_broa
a970: 64 63 61 73 74 28 26 61 73 79 6e 63 2e 65 6d 70  dcast(&async.emp
a980: 74 79 53 69 67 6e 61 6c 29 3b 0a 20 20 20 20 20  tySignal);.     
a990: 20 69 66 28 20 61 73 79 6e 63 2e 77 72 69 74 65   if( async.write
a9a0: 72 48 61 6c 74 57 68 65 6e 49 64 6c 65 20 29 7b  rHaltWhenIdle ){
a9b0: 0a 20 20 20 20 20 20 20 20 70 74 68 72 65 61 64  .        pthread
a9c0: 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61  _mutex_unlock(&a
a9d0: 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29  sync.queueMutex)
a9e0: 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b  ;.        break;
a9f0: 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  .      }else{.  
aa00: 20 20 20 20 20 20 41 53 59 4e 43 5f 54 52 41 43        ASYNC_TRAC
aa10: 45 28 28 22 49 44 4c 45 5c 6e 22 29 29 3b 0a 20  E(("IDLE\n"));. 
aa20: 20 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 63         pthread_c
aa30: 6f 6e 64 5f 77 61 69 74 28 26 61 73 79 6e 63 2e  ond_wait(&async.
aa40: 71 75 65 75 65 53 69 67 6e 61 6c 2c 20 26 61 73  queueSignal, &as
aa50: 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29 3b  ync.queueMutex);
aa60: 0a 20 20 20 20 20 20 20 20 41 53 59 4e 43 5f 54  .        ASYNC_T
aa70: 52 41 43 45 28 28 22 57 41 4b 45 55 50 5c 6e 22  RACE(("WAKEUP\n"
aa80: 29 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  ));.      }.    
aa90: 7d 0a 20 20 20 20 69 66 28 20 70 3d 3d 30 20 29  }.    if( p==0 )
aaa0: 20 62 72 65 61 6b 3b 0a 20 20 20 20 68 6f 6c 64   break;.    hold
aab0: 69 6e 67 4d 75 74 65 78 20 3d 20 31 3b 0a 0a 20  ingMutex = 1;.. 
aac0: 20 20 20 2f 2a 20 52 69 67 68 74 20 6e 6f 77 20     /* Right now 
aad0: 74 68 69 73 20 74 68 72 65 61 64 20 69 73 20 68  this thread is h
aae0: 6f 6c 64 69 6e 67 20 74 68 65 20 6d 75 74 65 78  olding the mutex
aaf0: 20 6f 6e 20 74 68 65 20 77 72 69 74 65 2d 6f 70   on the write-op
ab00: 20 71 75 65 75 65 2e 0a 20 20 20 20 2a 2a 20 56   queue..    ** V
ab10: 61 72 69 61 62 6c 65 20 27 70 27 20 70 6f 69 6e  ariable 'p' poin
ab20: 74 73 20 74 6f 20 74 68 65 20 66 69 72 73 74 20  ts to the first 
ab30: 65 6e 74 72 79 20 69 6e 20 74 68 65 20 77 72 69  entry in the wri
ab40: 74 65 2d 6f 70 20 71 75 65 75 65 2e 20 49 6e 0a  te-op queue. In.
ab50: 20 20 20 20 2a 2a 20 74 68 65 20 67 65 6e 65 72      ** the gener
ab60: 61 6c 20 63 61 73 65 2c 20 77 65 20 68 6f 6c 64  al case, we hold
ab70: 20 6f 6e 20 74 6f 20 74 68 65 20 6d 75 74 65 78   on to the mutex
ab80: 20 66 6f 72 20 74 68 65 20 65 6e 74 69 72 65 20   for the entire 
ab90: 62 6f 64 79 20 6f 66 0a 20 20 20 20 2a 2a 20 74  body of.    ** t
aba0: 68 65 20 6c 6f 6f 70 2e 20 0a 20 20 20 20 2a 2a  he loop. .    **
abb0: 0a 20 20 20 20 2a 2a 20 48 6f 77 65 76 65 72 20  .    ** However 
abc0: 69 6e 20 74 68 65 20 63 61 73 65 73 20 65 6e 75  in the cases enu
abd0: 6d 65 72 61 74 65 64 20 62 65 6c 6f 77 2c 20 77  merated below, w
abe0: 65 20 72 65 6c 69 6e 71 75 69 73 68 20 74 68 65  e relinquish the
abf0: 20 6d 75 74 65 78 2c 0a 20 20 20 20 2a 2a 20 70   mutex,.    ** p
ac00: 65 72 66 6f 72 6d 20 74 68 65 20 49 4f 2c 20 61  erform the IO, a
ac10: 6e 64 20 74 68 65 6e 20 72 65 2d 72 65 71 75 65  nd then re-reque
ac20: 73 74 20 74 68 65 20 6d 75 74 65 78 20 62 65 66  st the mutex bef
ac30: 6f 72 65 20 72 65 6d 6f 76 69 6e 67 20 27 70 27  ore removing 'p'
ac40: 20 66 72 6f 6d 0a 20 20 20 20 2a 2a 20 74 68 65   from.    ** the
ac50: 20 68 65 61 64 20 6f 66 20 74 68 65 20 77 72 69   head of the wri
ac60: 74 65 2d 6f 70 20 71 75 65 75 65 2e 20 54 68 65  te-op queue. The
ac70: 20 69 64 65 61 20 69 73 20 74 6f 20 69 6e 63 72   idea is to incr
ac80: 65 61 73 65 20 63 6f 6e 63 75 72 72 65 6e 63 79  ease concurrency
ac90: 20 77 69 74 68 0a 20 20 20 20 2a 2a 20 73 71 6c   with.    ** sql
aca0: 69 74 65 20 74 68 72 65 61 64 73 2e 0a 20 20 20  ite threads..   
acb0: 20 2a 2a 0a 20 20 20 20 2a 2a 20 20 20 20 20 2a   **.    **     *
acc0: 20 41 6e 20 41 53 59 4e 43 5f 43 4c 4f 53 45 20   An ASYNC_CLOSE 
acd0: 6f 70 65 72 61 74 69 6f 6e 2e 0a 20 20 20 20 2a  operation..    *
ace0: 2a 20 20 20 20 20 2a 20 41 6e 20 41 53 59 4e 43  *     * An ASYNC
acf0: 5f 4f 50 45 4e 45 58 43 4c 55 53 49 56 45 20 6f  _OPENEXCLUSIVE o
ad00: 70 65 72 61 74 69 6f 6e 2e 20 46 6f 72 20 74 68  peration. For th
ad10: 69 73 20 6f 6e 65 2c 20 77 65 20 72 65 6c 69 6e  is one, we relin
ad20: 71 75 69 73 68 20 0a 20 20 20 20 2a 2a 20 20 20  quish .    **   
ad30: 20 20 20 20 74 68 65 20 6d 75 74 65 78 2c 20 63      the mutex, c
ad40: 61 6c 6c 20 74 68 65 20 75 6e 64 65 72 6c 79 69  all the underlyi
ad50: 6e 67 20 78 4f 70 65 6e 45 78 63 6c 75 73 69 76  ng xOpenExclusiv
ad60: 65 28 29 20 66 75 6e 63 74 69 6f 6e 2c 20 74 68  e() function, th
ad70: 65 6e 0a 20 20 20 20 2a 2a 20 20 20 20 20 20 20  en.    **       
ad80: 72 65 2d 61 71 75 69 72 65 20 74 68 65 20 6d 75  re-aquire the mu
ad90: 74 65 78 20 62 65 66 6f 72 65 20 73 65 74 69 6e  tex before setin
ada0: 67 20 74 68 65 20 41 73 79 6e 63 46 69 6c 65 2e  g the AsyncFile.
adb0: 70 42 61 73 65 52 65 61 64 20 0a 20 20 20 20 2a  pBaseRead .    *
adc0: 2a 20 20 20 20 20 20 20 76 61 72 69 61 62 6c 65  *       variable
add0: 2e 0a 20 20 20 20 2a 2a 20 20 20 20 20 2a 20 41  ..    **     * A
ade0: 53 59 4e 43 5f 53 59 4e 43 20 61 6e 64 20 41 53  SYNC_SYNC and AS
adf0: 59 4e 43 5f 57 52 49 54 45 20 6f 70 65 72 61 74  YNC_WRITE operat
ae00: 69 6f 6e 73 2c 20 69 66 20 0a 20 20 20 20 2a 2a  ions, if .    **
ae10: 20 20 20 20 20 20 20 53 51 4c 49 54 45 5f 41 53         SQLITE_AS
ae20: 59 4e 43 5f 54 57 4f 5f 46 49 4c 45 48 41 4e 44  YNC_TWO_FILEHAND
ae30: 4c 45 53 20 77 61 73 20 73 65 74 20 61 74 20 63  LES was set at c
ae40: 6f 6d 70 69 6c 65 20 74 69 6d 65 20 61 6e 64 20  ompile time and 
ae50: 74 77 6f 0a 20 20 20 20 2a 2a 20 20 20 20 20 20  two.    **      
ae60: 20 66 69 6c 65 2d 68 61 6e 64 6c 65 73 20 61 72   file-handles ar
ae70: 65 20 6f 70 65 6e 20 66 6f 72 20 74 68 65 20 70  e open for the p
ae80: 61 72 74 69 63 75 6c 61 72 20 66 69 6c 65 20 62  articular file b
ae90: 65 69 6e 67 20 22 73 79 6e 63 65 64 22 2e 0a 20  eing "synced".. 
aea0: 20 20 20 2a 2f 0a 20 20 20 20 69 66 28 20 61 73     */.    if( as
aeb0: 79 6e 63 2e 69 6f 45 72 72 6f 72 21 3d 53 51 4c  ync.ioError!=SQL
aec0: 49 54 45 5f 4f 4b 20 26 26 20 70 2d 3e 6f 70 21  ITE_OK && p->op!
aed0: 3d 41 53 59 4e 43 5f 43 4c 4f 53 45 20 29 7b 0a  =ASYNC_CLOSE ){.
aee0: 20 20 20 20 20 20 70 2d 3e 6f 70 20 3d 20 41 53        p->op = AS
aef0: 59 4e 43 5f 4e 4f 4f 50 3b 0a 20 20 20 20 7d 0a  YNC_NOOP;.    }.
af00: 20 20 20 20 69 66 28 20 70 2d 3e 70 46 69 6c 65      if( p->pFile
af10: 44 61 74 61 20 29 7b 0a 20 20 20 20 20 20 70 42  Data ){.      pB
af20: 61 73 65 20 3d 20 70 2d 3e 70 46 69 6c 65 44 61  ase = p->pFileDa
af30: 74 61 2d 3e 70 42 61 73 65 57 72 69 74 65 3b 0a  ta->pBaseWrite;.
af40: 20 20 20 20 20 20 69 66 28 20 0a 20 20 20 20 20        if( .     
af50: 20 20 20 70 2d 3e 6f 70 3d 3d 41 53 59 4e 43 5f     p->op==ASYNC_
af60: 43 4c 4f 53 45 20 7c 7c 20 0a 20 20 20 20 20 20  CLOSE || .      
af70: 20 20 70 2d 3e 6f 70 3d 3d 41 53 59 4e 43 5f 4f    p->op==ASYNC_O
af80: 50 45 4e 45 58 43 4c 55 53 49 56 45 20 7c 7c 0a  PENEXCLUSIVE ||.
af90: 20 20 20 20 20 20 20 20 28 70 42 61 73 65 2d 3e          (pBase->
afa0: 70 4d 65 74 68 6f 64 73 20 26 26 20 28 70 2d 3e  pMethods && (p->
afb0: 6f 70 3d 3d 41 53 59 4e 43 5f 53 59 4e 43 20 7c  op==ASYNC_SYNC |
afc0: 7c 20 70 2d 3e 6f 70 3d 3d 41 53 59 4e 43 5f 57  | p->op==ASYNC_W
afd0: 52 49 54 45 29 20 29 20 0a 20 20 20 20 20 20 29  RITE) ) .      )
afe0: 7b 0a 20 20 20 20 20 20 20 20 70 74 68 72 65 61  {.        pthrea
aff0: 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26  d_mutex_unlock(&
b000: 61 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78  async.queueMutex
b010: 29 3b 0a 20 20 20 20 20 20 20 20 68 6f 6c 64 69  );.        holdi
b020: 6e 67 4d 75 74 65 78 20 3d 20 30 3b 0a 20 20 20  ngMutex = 0;.   
b030: 20 20 20 7d 0a 20 20 20 20 20 20 69 66 28 20 21     }.      if( !
b040: 70 42 61 73 65 2d 3e 70 4d 65 74 68 6f 64 73 20  pBase->pMethods 
b050: 29 7b 0a 20 20 20 20 20 20 20 20 70 42 61 73 65  ){.        pBase
b060: 20 3d 20 70 2d 3e 70 46 69 6c 65 44 61 74 61 2d   = p->pFileData-
b070: 3e 70 42 61 73 65 52 65 61 64 3b 0a 20 20 20 20  >pBaseRead;.    
b080: 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20 73    }.    }..    s
b090: 77 69 74 63 68 28 20 70 2d 3e 6f 70 20 29 7b 0a  witch( p->op ){.
b0a0: 20 20 20 20 20 20 63 61 73 65 20 41 53 59 4e 43        case ASYNC
b0b0: 5f 4e 4f 4f 50 3a 0a 20 20 20 20 20 20 20 20 62  _NOOP:.        b
b0c0: 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73  reak;..      cas
b0d0: 65 20 41 53 59 4e 43 5f 57 52 49 54 45 3a 0a 20  e ASYNC_WRITE:. 
b0e0: 20 20 20 20 20 20 20 61 73 73 65 72 74 28 20 70         assert( p
b0f0: 42 61 73 65 20 29 3b 0a 20 20 20 20 20 20 20 20  Base );.        
b100: 41 53 59 4e 43 5f 54 52 41 43 45 28 28 22 57 52  ASYNC_TRACE(("WR
b110: 49 54 45 20 25 73 20 25 64 20 62 79 74 65 73 20  ITE %s %d bytes 
b120: 61 74 20 25 64 5c 6e 22 2c 0a 20 20 20 20 20 20  at %d\n",.      
b130: 20 20 20 20 20 20 20 20 20 20 70 2d 3e 70 46 69            p->pFi
b140: 6c 65 44 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70  leData->zName, p
b150: 2d 3e 6e 42 79 74 65 2c 20 70 2d 3e 69 4f 66 66  ->nByte, p->iOff
b160: 73 65 74 29 29 3b 0a 20 20 20 20 20 20 20 20 72  set));.        r
b170: 63 20 3d 20 73 71 6c 69 74 65 33 4f 73 57 72 69  c = sqlite3OsWri
b180: 74 65 28 70 42 61 73 65 2c 20 28 76 6f 69 64 20  te(pBase, (void 
b190: 2a 29 28 70 2d 3e 7a 42 75 66 29 2c 20 70 2d 3e  *)(p->zBuf), p->
b1a0: 6e 42 79 74 65 2c 20 70 2d 3e 69 4f 66 66 73 65  nByte, p->iOffse
b1b0: 74 29 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61  t);.        brea
b1c0: 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65 20 41  k;..      case A
b1d0: 53 59 4e 43 5f 53 59 4e 43 3a 0a 20 20 20 20 20  SYNC_SYNC:.     
b1e0: 20 20 20 61 73 73 65 72 74 28 20 70 42 61 73 65     assert( pBase
b1f0: 20 29 3b 0a 20 20 20 20 20 20 20 20 41 53 59 4e   );.        ASYN
b200: 43 5f 54 52 41 43 45 28 28 22 53 59 4e 43 20 25  C_TRACE(("SYNC %
b210: 73 5c 6e 22 2c 20 70 2d 3e 70 46 69 6c 65 44 61  s\n", p->pFileDa
b220: 74 61 2d 3e 7a 4e 61 6d 65 29 29 3b 0a 20 20 20  ta->zName));.   
b230: 20 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65       rc = sqlite
b240: 33 4f 73 53 79 6e 63 28 70 42 61 73 65 2c 20 70  3OsSync(pBase, p
b250: 2d 3e 6e 42 79 74 65 29 3b 0a 20 20 20 20 20 20  ->nByte);.      
b260: 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20    break;..      
b270: 63 61 73 65 20 41 53 59 4e 43 5f 54 52 55 4e 43  case ASYNC_TRUNC
b280: 41 54 45 3a 0a 20 20 20 20 20 20 20 20 61 73 73  ATE:.        ass
b290: 65 72 74 28 20 70 42 61 73 65 20 29 3b 0a 20 20  ert( pBase );.  
b2a0: 20 20 20 20 20 20 41 53 59 4e 43 5f 54 52 41 43        ASYNC_TRAC
b2b0: 45 28 28 22 54 52 55 4e 43 41 54 45 20 25 73 20  E(("TRUNCATE %s 
b2c0: 74 6f 20 25 64 20 62 79 74 65 73 5c 6e 22 2c 20  to %d bytes\n", 
b2d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
b2e0: 20 70 2d 3e 70 46 69 6c 65 44 61 74 61 2d 3e 7a   p->pFileData->z
b2f0: 4e 61 6d 65 2c 20 70 2d 3e 69 4f 66 66 73 65 74  Name, p->iOffset
b300: 29 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d  ));.        rc =
b310: 20 73 71 6c 69 74 65 33 4f 73 54 72 75 6e 63 61   sqlite3OsTrunca
b320: 74 65 28 70 42 61 73 65 2c 20 70 2d 3e 69 4f 66  te(pBase, p->iOf
b330: 66 73 65 74 29 3b 0a 20 20 20 20 20 20 20 20 62  fset);.        b
b340: 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73  reak;..      cas
b350: 65 20 41 53 59 4e 43 5f 43 4c 4f 53 45 3a 20 7b  e ASYNC_CLOSE: {
b360: 0a 20 20 20 20 20 20 20 20 41 73 79 6e 63 46 69  .        AsyncFi
b370: 6c 65 44 61 74 61 20 2a 70 44 61 74 61 20 3d 20  leData *pData = 
b380: 70 2d 3e 70 46 69 6c 65 44 61 74 61 3b 0a 20 20  p->pFileData;.  
b390: 20 20 20 20 20 20 41 53 59 4e 43 5f 54 52 41 43        ASYNC_TRAC
b3a0: 45 28 28 22 43 4c 4f 53 45 20 25 73 5c 6e 22 2c  E(("CLOSE %s\n",
b3b0: 20 70 2d 3e 70 46 69 6c 65 44 61 74 61 2d 3e 7a   p->pFileData->z
b3c0: 4e 61 6d 65 29 29 3b 0a 20 20 20 20 20 20 20 20  Name));.        
b3d0: 73 71 6c 69 74 65 33 4f 73 43 6c 6f 73 65 28 70  sqlite3OsClose(p
b3e0: 44 61 74 61 2d 3e 70 42 61 73 65 57 72 69 74 65  Data->pBaseWrite
b3f0: 29 3b 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74  );.        sqlit
b400: 65 33 4f 73 43 6c 6f 73 65 28 70 44 61 74 61 2d  e3OsClose(pData-
b410: 3e 70 42 61 73 65 52 65 61 64 29 3b 0a 0a 20 20  >pBaseRead);..  
b420: 20 20 20 20 20 20 2f 2a 20 55 6e 6c 69 6e 6b 20        /* Unlink 
b430: 41 73 79 6e 63 46 69 6c 65 44 61 74 61 2e 6c 6f  AsyncFileData.lo
b440: 63 6b 20 66 72 6f 6d 20 74 68 65 20 6c 69 6e 6b  ck from the link
b450: 65 64 20 6c 69 73 74 20 6f 66 20 41 73 79 6e 63  ed list of Async
b460: 46 69 6c 65 4c 6f 63 6b 20 0a 20 20 20 20 20 20  FileLock .      
b470: 20 20 2a 2a 20 73 74 72 75 63 74 75 72 65 73 20    ** structures 
b480: 66 6f 72 20 74 68 69 73 20 66 69 6c 65 2e 20 4f  for this file. O
b490: 62 74 61 69 6e 20 74 68 65 20 61 73 79 6e 63 2e  btain the async.
b4a0: 6c 6f 63 6b 4d 75 74 65 78 20 6d 75 74 65 78 20  lockMutex mutex 
b4b0: 0a 20 20 20 20 20 20 20 20 2a 2a 20 62 65 66 6f  .        ** befo
b4c0: 72 65 20 64 6f 69 6e 67 20 73 6f 2e 0a 20 20 20  re doing so..   
b4d0: 20 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 20 20       */.        
b4e0: 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c 6f  pthread_mutex_lo
b4f0: 63 6b 28 26 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75  ck(&async.lockMu
b500: 74 65 78 29 3b 0a 20 20 20 20 20 20 20 20 72 63  tex);.        rc
b510: 20 3d 20 75 6e 6c 69 6e 6b 41 73 79 6e 63 46 69   = unlinkAsyncFi
b520: 6c 65 28 70 44 61 74 61 29 3b 0a 20 20 20 20 20  le(pData);.     
b530: 20 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65 78     pthread_mutex
b540: 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 6c  _unlock(&async.l
b550: 6f 63 6b 4d 75 74 65 78 29 3b 0a 0a 20 20 20 20  ockMutex);..    
b560: 20 20 20 20 61 73 79 6e 63 2e 70 51 75 65 75 65      async.pQueue
b570: 46 69 72 73 74 20 3d 20 70 2d 3e 70 4e 65 78 74  First = p->pNext
b580: 3b 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65  ;.        sqlite
b590: 33 5f 66 72 65 65 28 70 44 61 74 61 29 3b 0a 20  3_free(pData);. 
b5a0: 20 20 20 20 20 20 20 64 6f 4e 6f 74 46 72 65 65         doNotFree
b5b0: 20 3d 20 31 3b 0a 20 20 20 20 20 20 20 20 62 72   = 1;.        br
b5c0: 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20  eak;.      }..  
b5d0: 20 20 20 20 63 61 73 65 20 41 53 59 4e 43 5f 55      case ASYNC_U
b5e0: 4e 4c 4f 43 4b 3a 20 7b 0a 20 20 20 20 20 20 20  NLOCK: {.       
b5f0: 20 41 73 79 6e 63 4c 6f 63 6b 20 2a 70 4c 6f 63   AsyncLock *pLoc
b600: 6b 3b 0a 20 20 20 20 20 20 20 20 41 73 79 6e 63  k;.        Async
b610: 46 69 6c 65 44 61 74 61 20 2a 70 44 61 74 61 20  FileData *pData 
b620: 3d 20 70 2d 3e 70 46 69 6c 65 44 61 74 61 3b 0a  = p->pFileData;.
b630: 20 20 20 20 20 20 20 20 69 6e 74 20 65 4c 6f 63          int eLoc
b640: 6b 20 3d 20 70 2d 3e 6e 42 79 74 65 3b 0a 20 20  k = p->nByte;.  
b650: 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d 75        pthread_mu
b660: 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e  tex_lock(&async.
b670: 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20 20 20 20  lockMutex);.    
b680: 20 20 20 20 70 44 61 74 61 2d 3e 6c 6f 63 6b 2e      pData->lock.
b690: 65 41 73 79 6e 63 4c 6f 63 6b 20 3d 20 4d 49 4e  eAsyncLock = MIN
b6a0: 28 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 44  (.            pD
b6b0: 61 74 61 2d 3e 6c 6f 63 6b 2e 65 41 73 79 6e 63  ata->lock.eAsync
b6c0: 4c 6f 63 6b 2c 20 4d 41 58 28 70 44 61 74 61 2d  Lock, MAX(pData-
b6d0: 3e 6c 6f 63 6b 2e 65 4c 6f 63 6b 2c 20 65 4c 6f  >lock.eLock, eLo
b6e0: 63 6b 29 0a 20 20 20 20 20 20 20 20 29 3b 0a 20  ck).        );. 
b6f0: 20 20 20 20 20 20 20 61 73 73 65 72 74 28 70 44         assert(pD
b700: 61 74 61 2d 3e 6c 6f 63 6b 2e 65 41 73 79 6e 63  ata->lock.eAsync
b710: 4c 6f 63 6b 3e 3d 70 44 61 74 61 2d 3e 6c 6f 63  Lock>=pData->loc
b720: 6b 2e 65 4c 6f 63 6b 29 3b 0a 20 20 20 20 20 20  k.eLock);.      
b730: 20 20 70 4c 6f 63 6b 20 3d 20 73 71 6c 69 74 65    pLock = sqlite
b740: 33 48 61 73 68 46 69 6e 64 28 26 61 73 79 6e 63  3HashFind(&async
b750: 2e 61 4c 6f 63 6b 2c 20 70 44 61 74 61 2d 3e 7a  .aLock, pData->z
b760: 4e 61 6d 65 2c 20 70 44 61 74 61 2d 3e 6e 4e 61  Name, pData->nNa
b770: 6d 65 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20  me);.        rc 
b780: 3d 20 67 65 74 46 69 6c 65 4c 6f 63 6b 28 70 4c  = getFileLock(pL
b790: 6f 63 6b 29 3b 0a 20 20 20 20 20 20 20 20 70 74  ock);.        pt
b7a0: 68 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f  hread_mutex_unlo
b7b0: 63 6b 28 26 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75  ck(&async.lockMu
b7c0: 74 65 78 29 3b 0a 20 20 20 20 20 20 20 20 62 72  tex);.        br
b7d0: 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20  eak;.      }..  
b7e0: 20 20 20 20 63 61 73 65 20 41 53 59 4e 43 5f 44      case ASYNC_D
b7f0: 45 4c 45 54 45 3a 0a 20 20 20 20 20 20 20 20 41  ELETE:.        A
b800: 53 59 4e 43 5f 54 52 41 43 45 28 28 22 44 45 4c  SYNC_TRACE(("DEL
b810: 45 54 45 20 25 73 5c 6e 22 2c 20 70 2d 3e 7a 42  ETE %s\n", p->zB
b820: 75 66 29 29 3b 0a 20 20 20 20 20 20 20 20 72 63  uf));.        rc
b830: 20 3d 20 73 71 6c 69 74 65 33 4f 73 44 65 6c 65   = sqlite3OsDele
b840: 74 65 28 70 56 66 73 2c 20 70 2d 3e 7a 42 75 66  te(pVfs, p->zBuf
b850: 2c 20 28 69 6e 74 29 70 2d 3e 69 4f 66 66 73 65  , (int)p->iOffse
b860: 74 29 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61  t);.        brea
b870: 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65 20 41  k;..      case A
b880: 53 59 4e 43 5f 4f 50 45 4e 45 58 43 4c 55 53 49  SYNC_OPENEXCLUSI
b890: 56 45 3a 20 7b 0a 20 20 20 20 20 20 20 20 69 6e  VE: {.        in
b8a0: 74 20 66 6c 61 67 73 20 3d 20 28 69 6e 74 29 70  t flags = (int)p
b8b0: 2d 3e 69 4f 66 66 73 65 74 3b 0a 20 20 20 20 20  ->iOffset;.     
b8c0: 20 20 20 41 73 79 6e 63 46 69 6c 65 44 61 74 61     AsyncFileData
b8d0: 20 2a 70 44 61 74 61 20 3d 20 70 2d 3e 70 46 69   *pData = p->pFi
b8e0: 6c 65 44 61 74 61 3b 0a 20 20 20 20 20 20 20 20  leData;.        
b8f0: 41 53 59 4e 43 5f 54 52 41 43 45 28 28 22 4f 50  ASYNC_TRACE(("OP
b900: 45 4e 20 25 73 20 66 6c 61 67 73 3d 25 64 5c 6e  EN %s flags=%d\n
b910: 22 2c 20 70 2d 3e 7a 42 75 66 2c 20 28 69 6e 74  ", p->zBuf, (int
b920: 29 70 2d 3e 69 4f 66 66 73 65 74 29 29 3b 0a 20  )p->iOffset));. 
b930: 20 20 20 20 20 20 20 61 73 73 65 72 74 28 70 44         assert(pD
b940: 61 74 61 2d 3e 70 42 61 73 65 52 65 61 64 2d 3e  ata->pBaseRead->
b950: 70 4d 65 74 68 6f 64 73 3d 3d 30 20 26 26 20 70  pMethods==0 && p
b960: 44 61 74 61 2d 3e 70 42 61 73 65 57 72 69 74 65  Data->pBaseWrite
b970: 2d 3e 70 4d 65 74 68 6f 64 73 3d 3d 30 29 3b 0a  ->pMethods==0);.
b980: 20 20 20 20 20 20 20 20 72 63 20 3d 20 73 71 6c          rc = sql
b990: 69 74 65 33 4f 73 4f 70 65 6e 28 70 56 66 73 2c  ite3OsOpen(pVfs,
b9a0: 20 70 44 61 74 61 2d 3e 7a 4e 61 6d 65 2c 20 70   pData->zName, p
b9b0: 44 61 74 61 2d 3e 70 42 61 73 65 52 65 61 64 2c  Data->pBaseRead,
b9c0: 20 66 6c 61 67 73 2c 20 30 29 3b 0a 20 20 20 20   flags, 0);.    
b9d0: 20 20 20 20 61 73 73 65 72 74 28 20 68 6f 6c 64      assert( hold
b9e0: 69 6e 67 4d 75 74 65 78 3d 3d 30 20 29 3b 0a 20  ingMutex==0 );. 
b9f0: 20 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d         pthread_m
ba00: 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63  utex_lock(&async
ba10: 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a 20 20  .queueMutex);.  
ba20: 20 20 20 20 20 20 68 6f 6c 64 69 6e 67 4d 75 74        holdingMut
ba30: 65 78 20 3d 20 31 3b 0a 20 20 20 20 20 20 20 20  ex = 1;.        
ba40: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 0a  break;.      }..
ba50: 20 20 20 20 20 20 64 65 66 61 75 6c 74 3a 20 61        default: a
ba60: 73 73 65 72 74 28 21 22 49 6c 6c 65 67 61 6c 20  ssert(!"Illegal 
ba70: 76 61 6c 75 65 20 66 6f 72 20 41 73 79 6e 63 57  value for AsyncW
ba80: 72 69 74 65 2e 6f 70 22 29 3b 0a 20 20 20 20 7d  rite.op");.    }
ba90: 0a 0a 20 20 20 20 2f 2a 20 49 66 20 77 65 20 64  ..    /* If we d
baa0: 69 64 6e 27 74 20 68 61 6e 67 20 6f 6e 20 74 6f  idn't hang on to
bab0: 20 74 68 65 20 6d 75 74 65 78 20 64 75 72 69 6e   the mutex durin
bac0: 67 20 74 68 65 20 49 4f 20 6f 70 2c 20 6f 62 74  g the IO op, obt
bad0: 61 69 6e 20 69 74 20 6e 6f 77 0a 20 20 20 20 2a  ain it now.    *
bae0: 2a 20 73 6f 20 74 68 61 74 20 74 68 65 20 41 73  * so that the As
baf0: 79 6e 63 57 72 69 74 65 20 73 74 72 75 63 74 75  yncWrite structu
bb00: 72 65 20 63 61 6e 20 62 65 20 73 61 66 65 6c 79  re can be safely
bb10: 20 72 65 6d 6f 76 65 64 20 66 72 6f 6d 20 74 68   removed from th
bb20: 65 20 0a 20 20 20 20 2a 2a 20 67 6c 6f 62 61 6c  e .    ** global
bb30: 20 77 72 69 74 65 2d 6f 70 20 71 75 65 75 65 2e   write-op queue.
bb40: 0a 20 20 20 20 2a 2f 0a 20 20 20 20 69 66 28 20  .    */.    if( 
bb50: 21 68 6f 6c 64 69 6e 67 4d 75 74 65 78 20 29 7b  !holdingMutex ){
bb60: 0a 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d  .      pthread_m
bb70: 75 74 65 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63  utex_lock(&async
bb80: 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a 20 20  .queueMutex);.  
bb90: 20 20 20 20 68 6f 6c 64 69 6e 67 4d 75 74 65 78      holdingMutex
bba0: 20 3d 20 31 3b 0a 20 20 20 20 7d 0a 20 20 20 20   = 1;.    }.    
bbb0: 2f 2a 20 41 53 59 4e 43 5f 54 52 41 43 45 28 28  /* ASYNC_TRACE((
bbc0: 22 55 4e 4c 49 4e 4b 20 25 70 5c 6e 22 2c 20 70  "UNLINK %p\n", p
bbd0: 29 29 3b 20 2a 2f 0a 20 20 20 20 69 66 28 20 70  )); */.    if( p
bbe0: 3d 3d 61 73 79 6e 63 2e 70 51 75 65 75 65 4c 61  ==async.pQueueLa
bbf0: 73 74 20 29 7b 0a 20 20 20 20 20 20 61 73 79 6e  st ){.      asyn
bc00: 63 2e 70 51 75 65 75 65 4c 61 73 74 20 3d 20 30  c.pQueueLast = 0
bc10: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20  ;.    }.    if( 
bc20: 21 64 6f 4e 6f 74 46 72 65 65 20 29 7b 0a 20 20  !doNotFree ){.  
bc30: 20 20 20 20 61 73 79 6e 63 2e 70 51 75 65 75 65      async.pQueue
bc40: 46 69 72 73 74 20 3d 20 70 2d 3e 70 4e 65 78 74  First = p->pNext
bc50: 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f  ;.      sqlite3_
bc60: 66 72 65 65 28 70 29 3b 0a 20 20 20 20 7d 0a 20  free(p);.    }. 
bc70: 20 20 20 61 73 73 65 72 74 28 20 68 6f 6c 64 69     assert( holdi
bc80: 6e 67 4d 75 74 65 78 20 29 3b 0a 0a 20 20 20 20  ngMutex );..    
bc90: 2f 2a 20 41 6e 20 49 4f 20 65 72 72 6f 72 20 68  /* An IO error h
bca0: 61 73 20 6f 63 63 75 72 65 64 2e 20 57 65 20 63  as occured. We c
bcb0: 61 6e 6e 6f 74 20 72 65 70 6f 72 74 20 74 68 65  annot report the
bcc0: 20 65 72 72 6f 72 20 62 61 63 6b 20 74 6f 20 74   error back to t
bcd0: 68 65 0a 20 20 20 20 2a 2a 20 63 6f 6e 6e 65 63  he.    ** connec
bce0: 74 69 6f 6e 20 74 68 61 74 20 72 65 71 75 65 73  tion that reques
bcf0: 74 65 64 20 74 68 65 20 49 2f 4f 20 73 69 6e 63  ted the I/O sinc
bd00: 65 20 74 68 65 20 65 72 72 6f 72 20 68 61 70 70  e the error happ
bd10: 65 6e 65 64 20 0a 20 20 20 20 2a 2a 20 61 73 79  ened .    ** asy
bd20: 6e 63 68 72 6f 6e 6f 75 73 6c 79 2e 20 20 54 68  nchronously.  Th
bd30: 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 68 61 73  e connection has
bd40: 20 61 6c 72 65 61 64 79 20 6d 6f 76 65 64 20 6f   already moved o
bd50: 6e 2e 20 20 54 68 65 72 65 20 0a 20 20 20 20 2a  n.  There .    *
bd60: 2a 20 72 65 61 6c 6c 79 20 69 73 20 6e 6f 62 6f  * really is nobo
bd70: 64 79 20 74 6f 20 72 65 70 6f 72 74 20 74 68 65  dy to report the
bd80: 20 65 72 72 6f 72 20 74 6f 2e 0a 20 20 20 20 2a   error to..    *
bd90: 2a 0a 20 20 20 20 2a 2a 20 54 68 65 20 66 69 6c  *.    ** The fil
bda0: 65 20 66 6f 72 20 77 68 69 63 68 20 74 68 65 20  e for which the 
bdb0: 65 72 72 6f 72 20 6f 63 63 75 72 65 64 20 6d 61  error occured ma
bdc0: 79 20 68 61 76 65 20 62 65 65 6e 20 61 20 64 61  y have been a da
bdd0: 74 61 62 61 73 65 20 6f 72 0a 20 20 20 20 2a 2a  tabase or.    **
bde0: 20 6a 6f 75 72 6e 61 6c 20 66 69 6c 65 2e 20 52   journal file. R
bdf0: 65 67 61 72 64 6c 65 73 73 2c 20 6e 6f 6e 65 20  egardless, none 
be00: 6f 66 20 74 68 65 20 63 75 72 72 65 6e 74 6c 79  of the currently
be10: 20 71 75 65 75 65 64 20 6f 70 65 72 61 74 69 6f   queued operatio
be20: 6e 73 0a 20 20 20 20 2a 2a 20 61 73 73 6f 63 69  ns.    ** associ
be30: 61 74 65 64 20 77 69 74 68 20 74 68 65 20 73 61  ated with the sa
be40: 6d 65 20 64 61 74 61 62 61 73 65 20 73 68 6f 75  me database shou
be50: 6c 64 20 6e 6f 77 20 62 65 20 70 65 72 66 6f 72  ld now be perfor
be60: 6d 65 64 2e 20 4e 6f 72 20 73 68 6f 75 6c 64 0a  med. Nor should.
be70: 20 20 20 20 2a 2a 20 61 6e 79 20 73 75 62 73 65      ** any subse
be80: 71 75 65 6e 74 6c 79 20 72 65 71 75 65 73 74 65  quently requeste
be90: 64 20 49 4f 20 6f 6e 20 65 69 74 68 65 72 20 61  d IO on either a
bea0: 20 64 61 74 61 62 61 73 65 20 6f 72 20 6a 6f 75   database or jou
beb0: 72 6e 61 6c 20 66 69 6c 65 20 0a 20 20 20 20 2a  rnal file .    *
bec0: 2a 20 68 61 6e 64 6c 65 20 66 6f 72 20 74 68 65  * handle for the
bed0: 20 73 61 6d 65 20 64 61 74 61 62 61 73 65 20 62   same database b
bee0: 65 20 61 63 63 65 70 74 65 64 20 75 6e 74 69 6c  e accepted until
bef0: 20 74 68 65 20 6d 61 69 6e 20 64 61 74 61 62 61   the main databa
bf00: 73 65 0a 20 20 20 20 2a 2a 20 66 69 6c 65 20 68  se.    ** file h
bf10: 61 6e 64 6c 65 20 68 61 73 20 62 65 65 6e 20 63  andle has been c
bf20: 6c 6f 73 65 64 20 61 6e 64 20 72 65 6f 70 65 6e  losed and reopen
bf30: 65 64 2e 0a 20 20 20 20 2a 2a 0a 20 20 20 20 2a  ed..    **.    *
bf40: 2a 20 46 75 72 74 68 65 72 6d 6f 72 65 2c 20 6e  * Furthermore, n
bf50: 6f 20 66 75 72 74 68 65 72 20 49 4f 20 73 68 6f  o further IO sho
bf60: 75 6c 64 20 62 65 20 71 75 65 75 65 64 20 6f 72  uld be queued or
bf70: 20 70 65 72 66 6f 72 6d 65 64 20 6f 6e 20 61 6e   performed on an
bf80: 79 20 66 69 6c 65 0a 20 20 20 20 2a 2a 20 68 61  y file.    ** ha
bf90: 6e 64 6c 65 20 61 73 73 6f 63 69 61 74 65 64 20  ndle associated 
bfa0: 77 69 74 68 20 61 20 64 61 74 61 62 61 73 65 20  with a database 
bfb0: 74 68 61 74 20 6d 61 79 20 68 61 76 65 20 62 65  that may have be
bfc0: 65 6e 20 70 61 72 74 20 6f 66 20 61 20 0a 20 20  en part of a .  
bfd0: 20 20 2a 2a 20 6d 75 6c 74 69 2d 66 69 6c 65 20    ** multi-file 
bfe0: 74 72 61 6e 73 61 63 74 69 6f 6e 20 74 68 61 74  transaction that
bff0: 20 69 6e 63 6c 75 64 65 64 20 74 68 65 20 64 61   included the da
c000: 74 61 62 61 73 65 20 61 73 73 6f 63 69 61 74 65  tabase associate
c010: 64 20 77 69 74 68 20 0a 20 20 20 20 2a 2a 20 74  d with .    ** t
c020: 68 65 20 49 4f 20 65 72 72 6f 72 20 28 69 2e 65  he IO error (i.e
c030: 2e 20 61 20 64 61 74 61 62 61 73 65 20 41 54 54  . a database ATT
c040: 41 43 48 65 64 20 74 6f 20 74 68 65 20 73 61 6d  ACHed to the sam
c050: 65 20 68 61 6e 64 6c 65 20 61 74 20 73 6f 6d 65  e handle at some
c060: 20 0a 20 20 20 20 2a 2a 20 70 6f 69 6e 74 20 69   .    ** point i
c070: 6e 20 74 69 6d 65 29 2e 0a 20 20 20 20 2a 2f 0a  n time)..    */.
c080: 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49      if( rc!=SQLI
c090: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 61  TE_OK ){.      a
c0a0: 73 79 6e 63 2e 69 6f 45 72 72 6f 72 20 3d 20 72  sync.ioError = r
c0b0: 63 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 69 66  c;.    }..    if
c0c0: 28 20 61 73 79 6e 63 2e 69 6f 45 72 72 6f 72 20  ( async.ioError 
c0d0: 26 26 20 21 61 73 79 6e 63 2e 70 51 75 65 75 65  && !async.pQueue
c0e0: 46 69 72 73 74 20 29 7b 0a 20 20 20 20 20 20 70  First ){.      p
c0f0: 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 6c 6f 63  thread_mutex_loc
c100: 6b 28 26 61 73 79 6e 63 2e 6c 6f 63 6b 4d 75 74  k(&async.lockMut
c110: 65 78 29 3b 0a 20 20 20 20 20 20 69 66 28 20 30  ex);.      if( 0
c120: 3d 3d 73 71 6c 69 74 65 48 61 73 68 46 69 72 73  ==sqliteHashFirs
c130: 74 28 26 61 73 79 6e 63 2e 61 4c 6f 63 6b 29 20  t(&async.aLock) 
c140: 29 7b 0a 20 20 20 20 20 20 20 20 61 73 79 6e 63  ){.        async
c150: 2e 69 6f 45 72 72 6f 72 20 3d 20 53 51 4c 49 54  .ioError = SQLIT
c160: 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a 20 20  E_OK;.      }.  
c170: 20 20 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65      pthread_mute
c180: 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79 6e 63 2e  x_unlock(&async.
c190: 6c 6f 63 6b 4d 75 74 65 78 29 3b 0a 20 20 20 20  lockMutex);.    
c1a0: 7d 0a 0a 20 20 20 20 2f 2a 20 44 72 6f 70 20 74  }..    /* Drop t
c1b0: 68 65 20 71 75 65 75 65 20 6d 75 74 65 78 20 62  he queue mutex b
c1c0: 65 66 6f 72 65 20 63 6f 6e 74 69 6e 75 69 6e 67  efore continuing
c1d0: 20 74 6f 20 74 68 65 20 6e 65 78 74 20 77 72 69   to the next wri
c1e0: 74 65 20 6f 70 65 72 61 74 69 6f 6e 0a 20 20 20  te operation.   
c1f0: 20 2a 2a 20 69 6e 20 6f 72 64 65 72 20 74 6f 20   ** in order to 
c200: 67 69 76 65 20 6f 74 68 65 72 20 74 68 72 65 61  give other threa
c210: 64 73 20 61 20 63 68 61 6e 63 65 20 74 6f 20 77  ds a chance to w
c220: 6f 72 6b 20 77 69 74 68 20 74 68 65 20 77 72 69  ork with the wri
c230: 74 65 20 71 75 65 75 65 2e 0a 20 20 20 20 2a 2f  te queue..    */
c240: 0a 20 20 20 20 69 66 28 20 21 61 73 79 6e 63 2e  .    if( !async.
c250: 70 51 75 65 75 65 46 69 72 73 74 20 7c 7c 20 21  pQueueFirst || !
c260: 61 73 79 6e 63 2e 69 6f 45 72 72 6f 72 20 29 7b  async.ioError ){
c270: 0a 20 20 20 20 20 20 70 74 68 72 65 61 64 5f 6d  .      pthread_m
c280: 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79  utex_unlock(&asy
c290: 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a  nc.queueMutex);.
c2a0: 20 20 20 20 20 20 68 6f 6c 64 69 6e 67 4d 75 74        holdingMut
c2b0: 65 78 20 3d 20 30 3b 0a 20 20 20 20 20 20 69 66  ex = 0;.      if
c2c0: 28 20 61 73 79 6e 63 2e 69 6f 44 65 6c 61 79 3e  ( async.ioDelay>
c2d0: 30 20 29 7b 0a 20 20 20 20 20 20 20 20 73 71 6c  0 ){.        sql
c2e0: 69 74 65 33 4f 73 53 6c 65 65 70 28 70 56 66 73  ite3OsSleep(pVfs
c2f0: 2c 20 61 73 79 6e 63 2e 69 6f 44 65 6c 61 79 29  , async.ioDelay)
c300: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
c310: 20 20 20 20 20 20 20 73 63 68 65 64 5f 79 69 65         sched_yie
c320: 6c 64 28 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  ld();.      }.  
c330: 20 20 7d 0a 20 20 7d 0a 20 20 0a 20 20 70 74 68    }.  }.  .  pth
c340: 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63  read_mutex_unloc
c350: 6b 28 26 61 73 79 6e 63 2e 77 72 69 74 65 72 4d  k(&async.writerM
c360: 75 74 65 78 29 3b 0a 20 20 72 65 74 75 72 6e 20  utex);.  return 
c370: 30 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a  0;.}../*********
c380: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c390: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c3a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c3b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c3c0: 2a 0a 2a 2a 20 54 68 65 20 72 65 6d 61 69 6e 69  *.** The remaini
c3d0: 6e 67 20 63 6f 64 65 20 64 65 66 69 6e 65 73 20  ng code defines 
c3e0: 61 20 54 63 6c 20 69 6e 74 65 72 66 61 63 65 20  a Tcl interface 
c3f0: 66 6f 72 20 74 65 73 74 69 6e 67 20 74 68 65 20  for testing the 
c400: 61 73 79 6e 63 68 72 6f 6e 6f 75 73 0a 2a 2a 20  asynchronous.** 
c410: 49 4f 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f  IO implementatio
c420: 6e 20 69 6e 20 74 68 69 73 20 66 69 6c 65 2e 0a  n in this file..
c430: 2a 2a 0a 2a 2a 20 54 6f 20 61 64 61 70 74 20 74  **.** To adapt t
c440: 68 65 20 63 6f 64 65 20 74 6f 20 61 20 6e 6f 6e  he code to a non
c450: 2d 54 43 4c 20 65 6e 76 69 72 6f 6e 6d 65 6e 74  -TCL environment
c460: 2c 20 64 65 6c 65 74 65 20 6f 72 20 63 6f 6d 6d  , delete or comm
c470: 65 6e 74 20 6f 75 74 0a 2a 2a 20 74 68 65 20 63  ent out.** the c
c480: 6f 64 65 20 74 68 61 74 20 66 6f 6c 6c 6f 77 73  ode that follows
c490: 2e 0a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 73 71 6c 69  ..*/../*.** sqli
c4a0: 74 65 33 61 73 79 6e 63 5f 65 6e 61 62 6c 65 20  te3async_enable 
c4b0: 3f 59 45 53 2f 4e 4f 3f 0a 2a 2a 0a 2a 2a 20 45  ?YES/NO?.**.** E
c4c0: 6e 61 62 6c 65 20 6f 72 20 64 69 73 61 62 6c 65  nable or disable
c4d0: 20 74 68 65 20 61 73 79 6e 63 68 72 6f 6e 6f 75   the asynchronou
c4e0: 73 20 49 2f 4f 20 62 61 63 6b 65 6e 64 2e 20 20  s I/O backend.  
c4f0: 54 68 69 73 20 63 6f 6d 6d 61 6e 64 20 69 73 0a  This command is.
c500: 2a 2a 20 6e 6f 74 20 74 68 72 65 61 64 2d 73 61  ** not thread-sa
c510: 66 65 2e 20 20 44 6f 20 6e 6f 74 20 63 61 6c 6c  fe.  Do not call
c520: 20 69 74 20 77 68 69 6c 65 20 61 6e 79 20 64 61   it while any da
c530: 74 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f  tabase connectio
c540: 6e 73 0a 2a 2a 20 61 72 65 20 6f 70 65 6e 2e 0a  ns.** are open..
c550: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65  */.static int te
c560: 73 74 41 73 79 6e 63 45 6e 61 62 6c 65 28 0a 20  stAsyncEnable(. 
c570: 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61   void * clientDa
c580: 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70  ta,.  Tcl_Interp
c590: 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20   *interp,.  int 
c5a0: 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20  objc,.  Tcl_Obj 
c5b0: 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b  *CONST objv[].){
c5c0: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 31 20 26  .  if( objc!=1 &
c5d0: 26 20 6f 62 6a 63 21 3d 32 20 29 7b 0a 20 20 20  & objc!=2 ){.   
c5e0: 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67   Tcl_WrongNumArg
c5f0: 73 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a  s(interp, 1, obj
c600: 76 2c 20 22 3f 59 45 53 2f 4e 4f 3f 22 29 3b 0a  v, "?YES/NO?");.
c610: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
c620: 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 69 66 28 20  RROR;.  }.  if( 
c630: 6f 62 6a 63 3d 3d 31 20 29 7b 0a 20 20 20 20 54  objc==1 ){.    T
c640: 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74 28  cl_SetObjResult(
c650: 69 6e 74 65 72 70 2c 20 54 63 6c 5f 4e 65 77 42  interp, Tcl_NewB
c660: 6f 6f 6c 65 61 6e 4f 62 6a 28 61 73 79 6e 63 5f  ooleanObj(async_
c670: 76 66 73 2e 70 41 70 70 44 61 74 61 21 3d 30 29  vfs.pAppData!=0)
c680: 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  );.  }else{.    
c690: 69 6e 74 20 65 6e 3b 0a 20 20 20 20 69 66 28 20  int en;.    if( 
c6a0: 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61 6e 46 72  Tcl_GetBooleanFr
c6b0: 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f 62  omObj(interp, ob
c6c0: 6a 76 5b 31 5d 2c 20 26 65 6e 29 20 29 20 72 65  jv[1], &en) ) re
c6d0: 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a  turn TCL_ERROR;.
c6e0: 20 20 20 20 61 73 79 6e 63 45 6e 61 62 6c 65 28      asyncEnable(
c6f0: 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  en);.  }.  retur
c700: 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a  n TCL_OK;.}../*.
c710: 2a 2a 20 73 71 6c 69 74 65 33 61 73 79 6e 63 5f  ** sqlite3async_
c720: 68 61 6c 74 20 20 22 6e 6f 77 22 7c 22 69 64 6c  halt  "now"|"idl
c730: 65 22 7c 22 6e 65 76 65 72 22 0a 2a 2a 0a 2a 2a  e"|"never".**.**
c740: 20 53 65 74 20 74 68 65 20 63 6f 6e 64 69 74 69   Set the conditi
c750: 6f 6e 73 20 61 74 20 77 68 69 63 68 20 74 68 65  ons at which the
c760: 20 77 72 69 74 65 72 20 74 68 72 65 61 64 20 77   writer thread w
c770: 69 6c 6c 20 68 61 6c 74 2e 0a 2a 2f 0a 73 74 61  ill halt..*/.sta
c780: 74 69 63 20 69 6e 74 20 74 65 73 74 41 73 79 6e  tic int testAsyn
c790: 63 48 61 6c 74 28 0a 20 20 76 6f 69 64 20 2a 20  cHalt(.  void * 
c7a0: 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63  clientData,.  Tc
c7b0: 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70  l_Interp *interp
c7c0: 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20  ,.  int objc,.  
c7d0: 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f  Tcl_Obj *CONST o
c7e0: 62 6a 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74  bjv[].){.  const
c7f0: 20 63 68 61 72 20 2a 7a 43 6f 6e 64 3b 0a 20 20   char *zCond;.  
c800: 69 66 28 20 6f 62 6a 63 21 3d 32 20 29 7b 0a 20  if( objc!=2 ){. 
c810: 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41     Tcl_WrongNumA
c820: 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f  rgs(interp, 1, o
c830: 62 6a 76 2c 20 22 5c 22 6e 6f 77 5c 22 7c 5c 22  bjv, "\"now\"|\"
c840: 69 64 6c 65 5c 22 7c 5c 22 6e 65 76 65 72 5c 22  idle\"|\"never\"
c850: 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54  ");.    return T
c860: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20  CL_ERROR;.  }.  
c870: 7a 43 6f 6e 64 20 3d 20 54 63 6c 5f 47 65 74 53  zCond = Tcl_GetS
c880: 74 72 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 3b 0a  tring(objv[1]);.
c890: 20 20 69 66 28 20 73 74 72 63 6d 70 28 7a 43 6f    if( strcmp(zCo
c8a0: 6e 64 2c 20 22 6e 6f 77 22 29 3d 3d 30 20 29 7b  nd, "now")==0 ){
c8b0: 0a 20 20 20 20 61 73 79 6e 63 2e 77 72 69 74 65  .    async.write
c8c0: 72 48 61 6c 74 4e 6f 77 20 3d 20 31 3b 0a 20 20  rHaltNow = 1;.  
c8d0: 20 20 70 74 68 72 65 61 64 5f 63 6f 6e 64 5f 62    pthread_cond_b
c8e0: 72 6f 61 64 63 61 73 74 28 26 61 73 79 6e 63 2e  roadcast(&async.
c8f0: 71 75 65 75 65 53 69 67 6e 61 6c 29 3b 0a 20 20  queueSignal);.  
c900: 7d 65 6c 73 65 20 69 66 28 20 73 74 72 63 6d 70  }else if( strcmp
c910: 28 7a 43 6f 6e 64 2c 20 22 69 64 6c 65 22 29 3d  (zCond, "idle")=
c920: 3d 30 20 29 7b 0a 20 20 20 20 61 73 79 6e 63 2e  =0 ){.    async.
c930: 77 72 69 74 65 72 48 61 6c 74 57 68 65 6e 49 64  writerHaltWhenId
c940: 6c 65 20 3d 20 31 3b 0a 20 20 20 20 61 73 79 6e  le = 1;.    asyn
c950: 63 2e 77 72 69 74 65 72 48 61 6c 74 4e 6f 77 20  c.writerHaltNow 
c960: 3d 20 30 3b 0a 20 20 20 20 70 74 68 72 65 61 64  = 0;.    pthread
c970: 5f 63 6f 6e 64 5f 62 72 6f 61 64 63 61 73 74 28  _cond_broadcast(
c980: 26 61 73 79 6e 63 2e 71 75 65 75 65 53 69 67 6e  &async.queueSign
c990: 61 6c 29 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28  al);.  }else if(
c9a0: 20 73 74 72 63 6d 70 28 7a 43 6f 6e 64 2c 20 22   strcmp(zCond, "
c9b0: 6e 65 76 65 72 22 29 3d 3d 30 20 29 7b 0a 20 20  never")==0 ){.  
c9c0: 20 20 61 73 79 6e 63 2e 77 72 69 74 65 72 48 61    async.writerHa
c9d0: 6c 74 57 68 65 6e 49 64 6c 65 20 3d 20 30 3b 0a  ltWhenIdle = 0;.
c9e0: 20 20 20 20 61 73 79 6e 63 2e 77 72 69 74 65 72      async.writer
c9f0: 48 61 6c 74 4e 6f 77 20 3d 20 30 3b 0a 20 20 7d  HaltNow = 0;.  }
ca00: 65 6c 73 65 7b 0a 20 20 20 20 54 63 6c 5f 41 70  else{.    Tcl_Ap
ca10: 70 65 6e 64 52 65 73 75 6c 74 28 69 6e 74 65 72  pendResult(inter
ca20: 70 2c 20 0a 20 20 20 20 20 20 22 73 68 6f 75 6c  p, .      "shoul
ca30: 64 20 62 65 20 6f 6e 65 20 6f 66 3a 20 5c 22 6e  d be one of: \"n
ca40: 6f 77 5c 22 2c 20 5c 22 69 64 6c 65 5c 22 2c 20  ow\", \"idle\", 
ca50: 6f 72 20 5c 22 6e 65 76 65 72 5c 22 22 2c 20 28  or \"never\"", (
ca60: 63 68 61 72 2a 29 30 29 3b 0a 20 20 20 20 72 65  char*)0);.    re
ca70: 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a  turn TCL_ERROR;.
ca80: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 54 43 4c    }.  return TCL
ca90: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 73 71  _OK;.}../*.** sq
caa0: 6c 69 74 65 33 61 73 79 6e 63 5f 64 65 6c 61 79  lite3async_delay
cab0: 20 3f 4d 53 3f 0a 2a 2a 0a 2a 2a 20 51 75 65 72   ?MS?.**.** Quer
cac0: 79 20 6f 72 20 73 65 74 20 74 68 65 20 6e 75 6d  y or set the num
cad0: 62 65 72 20 6f 66 20 6d 69 6c 6c 69 73 65 63 6f  ber of milliseco
cae0: 6e 64 73 20 6f 66 20 64 65 6c 61 79 20 69 6e 20  nds of delay in 
caf0: 74 68 65 20 77 72 69 74 65 72 0a 2a 2a 20 74 68  the writer.** th
cb00: 72 65 61 64 20 61 66 74 65 72 20 65 61 63 68 20  read after each 
cb10: 77 72 69 74 65 20 6f 70 65 72 61 74 69 6f 6e 2e  write operation.
cb20: 20 20 54 68 65 20 64 65 66 61 75 6c 74 20 69 73    The default is
cb30: 20 30 2e 20 20 42 79 20 69 6e 63 72 65 61 73 69   0.  By increasi
cb40: 6e 67 0a 2a 2a 20 74 68 65 20 6d 65 6d 6f 72 79  ng.** the memory
cb50: 20 64 65 6c 61 79 20 77 65 20 63 61 6e 20 73 69   delay we can si
cb60: 6d 75 6c 61 74 65 20 74 68 65 20 65 66 66 65 63  mulate the effec
cb70: 74 20 6f 66 20 73 6c 6f 77 20 64 69 73 6b 20 49  t of slow disk I
cb80: 2f 4f 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  /O..*/.static in
cb90: 74 20 74 65 73 74 41 73 79 6e 63 44 65 6c 61 79  t testAsyncDelay
cba0: 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e  (.  void * clien
cbb0: 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74  tData,.  Tcl_Int
cbc0: 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69  erp *interp,.  i
cbd0: 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f  nt objc,.  Tcl_O
cbe0: 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d  bj *CONST objv[]
cbf0: 0a 29 7b 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d  .){.  if( objc!=
cc00: 31 20 26 26 20 6f 62 6a 63 21 3d 32 20 29 7b 0a  1 && objc!=2 ){.
cc10: 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d      Tcl_WrongNum
cc20: 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c 20  Args(interp, 1, 
cc30: 6f 62 6a 76 2c 20 22 3f 4d 53 3f 22 29 3b 0a 20  objv, "?MS?");. 
cc40: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
cc50: 52 4f 52 3b 0a 20 20 7d 0a 20 20 69 66 28 20 6f  ROR;.  }.  if( o
cc60: 62 6a 63 3d 3d 31 20 29 7b 0a 20 20 20 20 54 63  bjc==1 ){.    Tc
cc70: 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74 28 69  l_SetObjResult(i
cc80: 6e 74 65 72 70 2c 20 54 63 6c 5f 4e 65 77 49 6e  nterp, Tcl_NewIn
cc90: 74 4f 62 6a 28 61 73 79 6e 63 2e 69 6f 44 65 6c  tObj(async.ioDel
cca0: 61 79 29 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20  ay));.  }else{. 
ccb0: 20 20 20 69 6e 74 20 69 6f 44 65 6c 61 79 3b 0a     int ioDelay;.
ccc0: 20 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74 49      if( Tcl_GetI
ccd0: 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70  ntFromObj(interp
cce0: 2c 20 6f 62 6a 76 5b 31 5d 2c 20 26 69 6f 44 65  , objv[1], &ioDe
ccf0: 6c 61 79 29 20 29 20 72 65 74 75 72 6e 20 54 43  lay) ) return TC
cd00: 4c 5f 45 52 52 4f 52 3b 0a 20 20 20 20 61 73 79  L_ERROR;.    asy
cd10: 6e 63 2e 69 6f 44 65 6c 61 79 20 3d 20 69 6f 44  nc.ioDelay = ioD
cd20: 65 6c 61 79 3b 0a 20 20 7d 0a 20 20 72 65 74 75  elay;.  }.  retu
cd30: 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn TCL_OK;.}../*
cd40: 0a 2a 2a 20 73 71 6c 69 74 65 33 61 73 79 6e 63  .** sqlite3async
cd50: 5f 73 74 61 72 74 0a 2a 2a 0a 2a 2a 20 53 74 61  _start.**.** Sta
cd60: 72 74 20 61 20 6e 65 77 20 77 72 69 74 65 72 20  rt a new writer 
cd70: 74 68 72 65 61 64 2e 0a 2a 2f 0a 73 74 61 74 69  thread..*/.stati
cd80: 63 20 69 6e 74 20 74 65 73 74 41 73 79 6e 63 53  c int testAsyncS
cd90: 74 61 72 74 28 0a 20 20 76 6f 69 64 20 2a 20 63  tart(.  void * c
cda0: 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c  lientData,.  Tcl
cdb0: 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c  _Interp *interp,
cdc0: 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54  .  int objc,.  T
cdd0: 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62  cl_Obj *CONST ob
cde0: 6a 76 5b 5d 0a 29 7b 0a 20 20 70 74 68 72 65 61  jv[].){.  pthrea
cdf0: 64 5f 74 20 78 3b 0a 20 20 69 6e 74 20 72 63 3b  d_t x;.  int rc;
ce00: 0a 20 20 76 6f 6c 61 74 69 6c 65 20 69 6e 74 20  .  volatile int 
ce10: 69 73 53 74 61 72 74 65 64 20 3d 20 30 3b 0a 20  isStarted = 0;. 
ce20: 20 72 63 20 3d 20 70 74 68 72 65 61 64 5f 63 72   rc = pthread_cr
ce30: 65 61 74 65 28 26 78 2c 20 30 2c 20 61 73 79 6e  eate(&x, 0, asyn
ce40: 63 57 72 69 74 65 72 54 68 72 65 61 64 2c 20 28  cWriterThread, (
ce50: 76 6f 69 64 20 2a 29 26 69 73 53 74 61 72 74 65  void *)&isStarte
ce60: 64 29 3b 0a 20 20 69 66 28 20 72 63 20 29 7b 0a  d);.  if( rc ){.
ce70: 20 20 20 20 54 63 6c 5f 41 70 70 65 6e 64 52 65      Tcl_AppendRe
ce80: 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 22 66 61  sult(interp, "fa
ce90: 69 6c 65 64 20 74 6f 20 63 72 65 61 74 65 20 74  iled to create t
cea0: 68 65 20 74 68 72 65 61 64 22 2c 20 30 29 3b 0a  he thread", 0);.
ceb0: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
cec0: 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 70 74 68 72  RROR;.  }.  pthr
ced0: 65 61 64 5f 64 65 74 61 63 68 28 78 29 3b 0a 20  ead_detach(x);. 
cee0: 20 77 68 69 6c 65 28 20 69 73 53 74 61 72 74 65   while( isStarte
cef0: 64 3d 3d 30 20 29 7b 0a 20 20 20 20 73 63 68 65  d==0 ){.    sche
cf00: 64 5f 79 69 65 6c 64 28 29 3b 0a 20 20 7d 0a 20  d_yield();.  }. 
cf10: 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a   return TCL_OK;.
cf20: 7d 0a 0a 2f 2a 0a 2a 2a 20 73 71 6c 69 74 65 33  }../*.** sqlite3
cf30: 61 73 79 6e 63 5f 77 61 69 74 0a 2a 2a 0a 2a 2a  async_wait.**.**
cf40: 20 57 61 69 74 20 66 6f 72 20 74 68 65 20 63 75   Wait for the cu
cf50: 72 72 65 6e 74 20 77 72 69 74 65 72 20 74 68 72  rrent writer thr
cf60: 65 61 64 20 74 6f 20 74 65 72 6d 69 6e 61 74 65  ead to terminate
cf70: 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 74 68 65 20 63  ..**.** If the c
cf80: 75 72 72 65 6e 74 20 77 72 69 74 65 72 20 74 68  urrent writer th
cf90: 72 65 61 64 20 69 73 20 73 65 74 20 74 6f 20 72  read is set to r
cfa0: 75 6e 20 66 6f 72 65 76 65 72 20 74 68 65 6e 20  un forever then 
cfb0: 74 68 69 73 0a 2a 2a 20 63 6f 6d 6d 61 6e 64 20  this.** command 
cfc0: 77 6f 75 6c 64 20 62 6c 6f 63 6b 20 66 6f 72 65  would block fore
cfd0: 76 65 72 2e 20 20 54 6f 20 70 72 65 76 65 6e 74  ver.  To prevent
cfe0: 20 74 68 61 74 2c 20 61 6e 20 65 72 72 6f 72 20   that, an error 
cff0: 69 73 20 72 65 74 75 72 6e 65 64 2e 20 0a 2a 2f  is returned. .*/
d000: 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74  .static int test
d010: 41 73 79 6e 63 57 61 69 74 28 0a 20 20 76 6f 69  AsyncWait(.  voi
d020: 64 20 2a 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a  d * clientData,.
d030: 20 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e    Tcl_Interp *in
d040: 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63  terp,.  int objc
d050: 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e  ,.  Tcl_Obj *CON
d060: 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 69  ST objv[].){.  i
d070: 6e 74 20 63 6e 74 20 3d 20 31 30 3b 0a 20 20 69  nt cnt = 10;.  i
d080: 66 28 20 61 73 79 6e 63 2e 77 72 69 74 65 72 48  f( async.writerH
d090: 61 6c 74 4e 6f 77 3d 3d 30 20 26 26 20 61 73 79  altNow==0 && asy
d0a0: 6e 63 2e 77 72 69 74 65 72 48 61 6c 74 57 68 65  nc.writerHaltWhe
d0b0: 6e 49 64 6c 65 3d 3d 30 20 29 7b 0a 20 20 20 20  nIdle==0 ){.    
d0c0: 54 63 6c 5f 41 70 70 65 6e 64 52 65 73 75 6c 74  Tcl_AppendResult
d0d0: 28 69 6e 74 65 72 70 2c 20 22 77 6f 75 6c 64 20  (interp, "would 
d0e0: 62 6c 6f 63 6b 20 66 6f 72 65 76 65 72 22 2c 20  block forever", 
d0f0: 28 63 68 61 72 2a 29 30 29 3b 0a 20 20 20 20 72  (char*)0);.    r
d100: 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b  eturn TCL_ERROR;
d110: 0a 20 20 7d 0a 0a 20 20 77 68 69 6c 65 28 20 63  .  }..  while( c
d120: 6e 74 2d 2d 20 26 26 20 21 70 74 68 72 65 61 64  nt-- && !pthread
d130: 5f 6d 75 74 65 78 5f 74 72 79 6c 6f 63 6b 28 26  _mutex_trylock(&
d140: 61 73 79 6e 63 2e 77 72 69 74 65 72 4d 75 74 65  async.writerMute
d150: 78 29 20 29 7b 0a 20 20 20 20 70 74 68 72 65 61  x) ){.    pthrea
d160: 64 5f 6d 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26  d_mutex_unlock(&
d170: 61 73 79 6e 63 2e 77 72 69 74 65 72 4d 75 74 65  async.writerMute
d180: 78 29 3b 0a 20 20 20 20 73 63 68 65 64 5f 79 69  x);.    sched_yi
d190: 65 6c 64 28 29 3b 0a 20 20 7d 0a 20 20 69 66 28  eld();.  }.  if(
d1a0: 20 63 6e 74 3e 3d 30 20 29 7b 0a 20 20 20 20 41   cnt>=0 ){.    A
d1b0: 53 59 4e 43 5f 54 52 41 43 45 28 28 22 57 41 49  SYNC_TRACE(("WAI
d1c0: 54 5c 6e 22 29 29 3b 0a 20 20 20 20 70 74 68 72  T\n"));.    pthr
d1d0: 65 61 64 5f 6d 75 74 65 78 5f 6c 6f 63 6b 28 26  ead_mutex_lock(&
d1e0: 61 73 79 6e 63 2e 71 75 65 75 65 4d 75 74 65 78  async.queueMutex
d1f0: 29 3b 0a 20 20 20 20 70 74 68 72 65 61 64 5f 63  );.    pthread_c
d200: 6f 6e 64 5f 62 72 6f 61 64 63 61 73 74 28 26 61  ond_broadcast(&a
d210: 73 79 6e 63 2e 71 75 65 75 65 53 69 67 6e 61 6c  sync.queueSignal
d220: 29 3b 0a 20 20 20 20 70 74 68 72 65 61 64 5f 6d  );.    pthread_m
d230: 75 74 65 78 5f 75 6e 6c 6f 63 6b 28 26 61 73 79  utex_unlock(&asy
d240: 6e 63 2e 71 75 65 75 65 4d 75 74 65 78 29 3b 0a  nc.queueMutex);.
d250: 20 20 20 20 70 74 68 72 65 61 64 5f 6d 75 74 65      pthread_mute
d260: 78 5f 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 77 72  x_lock(&async.wr
d270: 69 74 65 72 4d 75 74 65 78 29 3b 0a 20 20 20 20  iterMutex);.    
d280: 70 74 68 72 65 61 64 5f 6d 75 74 65 78 5f 75 6e  pthread_mutex_un
d290: 6c 6f 63 6b 28 26 61 73 79 6e 63 2e 77 72 69 74  lock(&async.writ
d2a0: 65 72 4d 75 74 65 78 29 3b 0a 20 20 7d 65 6c 73  erMutex);.  }els
d2b0: 65 7b 0a 20 20 20 20 41 53 59 4e 43 5f 54 52 41  e{.    ASYNC_TRA
d2c0: 43 45 28 28 22 4e 4f 2d 57 41 49 54 5c 6e 22 29  CE(("NO-WAIT\n")
d2d0: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
d2e0: 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 0a 23 65 6e 64  TCL_OK;.}...#end
d2f0: 69 66 20 20 2f 2a 20 4f 53 5f 55 4e 49 58 20 61  if  /* OS_UNIX a
d300: 6e 64 20 53 51 4c 49 54 45 5f 54 48 52 45 41 44  nd SQLITE_THREAD
d310: 53 41 46 45 20 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54  SAFE */../*.** T
d320: 68 69 73 20 72 6f 75 74 69 6e 65 20 72 65 67 69  his routine regi
d330: 73 74 65 72 73 20 74 68 65 20 63 75 73 74 6f 6d  sters the custom
d340: 20 54 43 4c 20 63 6f 6d 6d 61 6e 64 73 20 64 65   TCL commands de
d350: 66 69 6e 65 64 20 69 6e 20 74 68 69 73 0a 2a 2a  fined in this.**
d360: 20 6d 6f 64 75 6c 65 2e 20 20 54 68 69 73 20 73   module.  This s
d370: 68 6f 75 6c 64 20 62 65 20 74 68 65 20 6f 6e 6c  hould be the onl
d380: 79 20 70 72 6f 63 65 64 75 72 65 20 76 69 73 69  y procedure visi
d390: 62 6c 65 20 66 72 6f 6d 20 6f 75 74 73 69 64 65  ble from outside
d3a0: 0a 2a 2a 20 6f 66 20 74 68 69 73 20 6d 6f 64 75  .** of this modu
d3b0: 6c 65 2e 0a 2a 2f 0a 69 6e 74 20 53 71 6c 69 74  le..*/.int Sqlit
d3c0: 65 74 65 73 74 61 73 79 6e 63 5f 49 6e 69 74 28  etestasync_Init(
d3d0: 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65  Tcl_Interp *inte
d3e0: 72 70 29 7b 0a 23 69 66 20 4f 53 5f 55 4e 49 58  rp){.#if OS_UNIX
d3f0: 20 26 26 20 53 51 4c 49 54 45 5f 54 48 52 45 41   && SQLITE_THREA
d400: 44 53 41 46 45 0a 20 20 54 63 6c 5f 43 72 65 61  DSAFE.  Tcl_Crea
d410: 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74  teObjCommand(int
d420: 65 72 70 2c 22 73 71 6c 69 74 65 33 61 73 79 6e  erp,"sqlite3asyn
d430: 63 5f 65 6e 61 62 6c 65 22 2c 74 65 73 74 41 73  c_enable",testAs
d440: 79 6e 63 45 6e 61 62 6c 65 2c 30 2c 30 29 3b 0a  yncEnable,0,0);.
d450: 20 20 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43    Tcl_CreateObjC
d460: 6f 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c 22 73  ommand(interp,"s
d470: 71 6c 69 74 65 33 61 73 79 6e 63 5f 68 61 6c 74  qlite3async_halt
d480: 22 2c 74 65 73 74 41 73 79 6e 63 48 61 6c 74 2c  ",testAsyncHalt,
d490: 30 2c 30 29 3b 0a 20 20 54 63 6c 5f 43 72 65 61  0,0);.  Tcl_Crea
d4a0: 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74  teObjCommand(int
d4b0: 65 72 70 2c 22 73 71 6c 69 74 65 33 61 73 79 6e  erp,"sqlite3asyn
d4c0: 63 5f 64 65 6c 61 79 22 2c 74 65 73 74 41 73 79  c_delay",testAsy
d4d0: 6e 63 44 65 6c 61 79 2c 30 2c 30 29 3b 0a 20 20  ncDelay,0,0);.  
d4e0: 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d  Tcl_CreateObjCom
d4f0: 6d 61 6e 64 28 69 6e 74 65 72 70 2c 22 73 71 6c  mand(interp,"sql
d500: 69 74 65 33 61 73 79 6e 63 5f 73 74 61 72 74 22  ite3async_start"
d510: 2c 74 65 73 74 41 73 79 6e 63 53 74 61 72 74 2c  ,testAsyncStart,
d520: 30 2c 30 29 3b 0a 20 20 54 63 6c 5f 43 72 65 61  0,0);.  Tcl_Crea
d530: 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74  teObjCommand(int
d540: 65 72 70 2c 22 73 71 6c 69 74 65 33 61 73 79 6e  erp,"sqlite3asyn
d550: 63 5f 77 61 69 74 22 2c 74 65 73 74 41 73 79 6e  c_wait",testAsyn
d560: 63 57 61 69 74 2c 30 2c 30 29 3b 0a 20 20 54 63  cWait,0,0);.  Tc
d570: 6c 5f 4c 69 6e 6b 56 61 72 28 69 6e 74 65 72 70  l_LinkVar(interp
d580: 2c 20 22 73 71 6c 69 74 65 33 61 73 79 6e 63 5f  , "sqlite3async_
d590: 74 72 61 63 65 22 2c 0a 20 20 20 20 20 20 28 63  trace",.      (c
d5a0: 68 61 72 2a 29 26 73 71 6c 69 74 65 33 61 73 79  har*)&sqlite3asy
d5b0: 6e 63 5f 74 72 61 63 65 2c 20 54 43 4c 5f 4c 49  nc_trace, TCL_LI
d5c0: 4e 4b 5f 49 4e 54 29 3b 0a 23 65 6e 64 69 66 20  NK_INT);.#endif 
d5d0: 20 2f 2a 20 4f 53 5f 55 4e 49 58 20 61 6e 64 20   /* OS_UNIX and 
d5e0: 53 51 4c 49 54 45 5f 54 48 52 45 41 44 53 41 46  SQLITE_THREADSAF
d5f0: 45 20 2a 2f 0a 20 20 72 65 74 75 72 6e 20 54 43  E */.  return TC
d600: 4c 5f 4f 4b 3b 0a 7d 0a                          L_OK;.}.