drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 1 | The 5 states of an historical rollback lock as implemented by the |
| 2 | xLock, xUnlock, and xCheckReservedLock methods of the sqlite3_io_methods |
| 3 | objec are: |
| 4 | |
| 5 | UNLOCKED |
| 6 | SHARED |
| 7 | RESERVED |
| 8 | PENDING |
| 9 | EXCLUSIVE |
| 10 | |
| 11 | The wal-index file has a similar locking hierarchy implemented using |
| 12 | the xShmLock method of the sqlite3_vfs object, but with 7 |
| 13 | states. Each connection to a wal-index file must be in one of |
| 14 | the following 7 states: |
| 15 | |
| 16 | UNLOCKED |
| 17 | READ |
| 18 | READ_FULL |
| 19 | WRITE |
| 20 | PENDING |
| 21 | CHECKPOINT |
| 22 | RECOVER |
| 23 | |
| 24 | These roughly correspond to the 5 states of a rollback lock except |
| 25 | that SHARED is split out into 2 states: READ and READ_FULL and |
| 26 | there is an extra RECOVER state used for wal-index reconstruction. |
| 27 | |
| 28 | The meanings of the various wal-index locking states is as follows: |
| 29 | |
| 30 | UNLOCKED - The wal-index is not in use. |
| 31 | |
| 32 | READ - Some prefix of the wal-index is being read. Additional |
| 33 | wal-index information can be appended at any time. The |
| 34 | newly appended content will be ignored by the holder of |
| 35 | the READ lock. |
| 36 | |
| 37 | READ_FULL - The entire wal-index is being read. No new information |
| 38 | can be added to the wal-index. The holder of a READ_FULL |
| 39 | lock promises never to read pages from the database file |
| 40 | that are available anywhere in the wal-index. |
| 41 | |
| 42 | WRITE - It is OK to append to the wal-index file and to adjust |
| 43 | the header to indicate the new "last valid frame". |
| 44 | |
| 45 | PENDING - Waiting on all READ locks to clear so that a |
| 46 | CHECKPOINT lock can be acquired. |
| 47 | |
| 48 | CHECKPOINT - It is OK to write any WAL data into the database file |
| 49 | and zero the last valid frame field of the wal-index |
| 50 | header. The wal-index file itself may not be changed |
| 51 | other than to zero the last valid frame field in the |
| 52 | header. |
| 53 | |
| 54 | RECOVER - Held during wal-index recovery. Used to prevent a |
| 55 | race if multiple clients try to recover a wal-index at |
| 56 | the same time. |
| 57 | |
| 58 | |
| 59 | A particular lock manager implementation may coalesce one or more of |
| 60 | the wal-index locking states, though with a reduction in concurrency. |
| 61 | For example, an implemention might implement only exclusive locking, |
| 62 | in which case all states would be equivalent to CHECKPOINT, meaning that |
| 63 | only one reader or one writer or one checkpointer could be active at a |
| 64 | time. Or, an implementation might combine READ and READ_FULL into |
| 65 | a single state equivalent to READ, meaning that a writer could |
| 66 | coexist with a reader, but no reader or writers could coexist with a |
| 67 | checkpointer. |
| 68 | |
| 69 | The lock manager must obey the following rules: |
| 70 | |
| 71 | (1) A READ cannot coexist with CHECKPOINT. |
| 72 | (2) A READ_FULL cannot coexist with WRITE. |
| 73 | (3) None of WRITE, PENDING, CHECKPOINT, or RECOVER can coexist. |
| 74 | |
| 75 | The SQLite core will obey the next set of rules. These rules are |
| 76 | assertions on the behavior of the SQLite core which might be verified |
| 77 | during testing using an instrumented lock manager. |
| 78 | |
| 79 | (5) No part of the wal-index will be read without holding either some |
| 80 | kind of SHM lock or an EXCLUSIVE lock on the original database. |
drh | d9e5c4f | 2010-05-12 18:01:39 +0000 | [diff] [blame] | 81 | The original database is the file named in the 2nd parameter to |
| 82 | the xShmOpen method. |
| 83 | |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 84 | (6) A holder of a READ_FULL will never read any page of the database |
| 85 | file that is contained anywhere in the wal-index. |
drh | d9e5c4f | 2010-05-12 18:01:39 +0000 | [diff] [blame] | 86 | |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 87 | (7) No part of the wal-index other than the header will be written nor |
drh | d9e5c4f | 2010-05-12 18:01:39 +0000 | [diff] [blame] | 88 | will the size of the wal-index grow without holding a WRITE or |
| 89 | an EXCLUSIVE on the original database file. |
| 90 | |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 91 | (8) The wal-index header will not be written without holding one of |
drh | d9e5c4f | 2010-05-12 18:01:39 +0000 | [diff] [blame] | 92 | WRITE, CHECKPOINT, or RECOVER on the wal-index or an EXCLUSIVE on |
| 93 | the original database files. |
| 94 | |
| 95 | (9) A CHECKPOINT or RECOVER must be held on the wal-index, or an |
| 96 | EXCLUSIVE on the original database file, in order to reset the |
| 97 | last valid frame counter in the header of the wal-index back to zero. |
| 98 | |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 99 | (10) A WRITE can only increase the last valid frame pointer in the header. |
| 100 | |
| 101 | The SQLite core will only ever send requests for UNLOCK, READ, WRITE, |
| 102 | CHECKPOINT, or RECOVER to the lock manager. The SQLite core will never |
| 103 | request a READ_FULL or PENDING lock though the lock manager may deliver |
| 104 | those locking states in response to READ and CHECKPOINT requests, |
| 105 | respectively, if and only if the requested READ or CHECKPOINT cannot |
| 106 | be delivered. |
| 107 | |
| 108 | The following are the allowed lock transitions: |
| 109 | |
| 110 | Original-State Request New-State |
| 111 | -------------- ---------- ---------- |
| 112 | (11a) UNLOCK READ READ |
| 113 | (11b) UNLOCK READ READ_FULL |
| 114 | (11c) UNLOCK CHECKPOINT PENDING |
| 115 | (11d) UNLOCK CHECKPOINT CHECKPOINT |
| 116 | (11e) READ UNLOCK UNLOCK |
| 117 | (11f) READ WRITE WRITE |
| 118 | (11g) READ RECOVER RECOVER |
| 119 | (11h) READ_FULL UNLOCK UNLOCK |
| 120 | (11i) READ_FULL WRITE WRITE |
| 121 | (11j) READ_FULL RECOVER RECOVER |
| 122 | (11k) WRITE READ READ |
| 123 | (11l) PENDING UNLOCK UNLOCK |
| 124 | (11m) PENDING CHECKPOINT CHECKPOINT |
| 125 | (11n) CHECKPOINT UNLOCK UNLOCK |
dan | 65be0d8 | 2010-05-06 18:48:27 +0000 | [diff] [blame] | 126 | (11o) RECOVER READ READ |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 127 | |
drh | 08fba00 | 2010-05-06 19:04:48 +0000 | [diff] [blame] | 128 | These 15 transitions are all that needs to be supported. The lock |
| 129 | manager implementation can assert that fact. The other 27 possible |
drh | 24e3971 | 2010-05-06 11:55:56 +0000 | [diff] [blame] | 130 | transitions among the 7 locking states will never occur. |