wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.IO; |
||
4 | |||
5 | using i16 = System.Int16; |
||
6 | using i64 = System.Int64; |
||
7 | |||
8 | using u8 = System.Byte; |
||
9 | using u16 = System.UInt16; |
||
10 | using u32 = System.UInt32; |
||
11 | |||
12 | using Pgno = System.UInt32; |
||
13 | using sqlite3_int64 = System.Int64; |
||
14 | |||
15 | namespace Community.CsharpSqlite |
||
16 | { |
||
17 | using System.Text; |
||
18 | using DbPage = Sqlite3.PgHdr; |
||
19 | public partial class Sqlite3 |
||
20 | { |
||
21 | /* |
||
22 | ** 2001 September 15 |
||
23 | ** |
||
24 | ** The author disclaims copyright to this source code. In place of |
||
25 | ** a legal notice, here is a blessing: |
||
26 | ** |
||
27 | ** May you do good and not evil. |
||
28 | ** May you find forgiveness for yourself and forgive others. |
||
29 | ** May you share freely, never taking more than you give. |
||
30 | ** |
||
31 | ************************************************************************* |
||
32 | ** This is the implementation of the page cache subsystem or "pager". |
||
33 | ** |
||
34 | ** The pager is used to access a database disk file. It implements |
||
35 | ** atomic commit and rollback through the use of a journal file that |
||
36 | ** is separate from the database file. The pager also implements file |
||
37 | ** locking to prevent two processes from writing the same database |
||
38 | ** file simultaneously, or one process from reading the database while |
||
39 | ** another is writing. |
||
40 | ************************************************************************* |
||
41 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
42 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
43 | ** |
||
44 | ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 |
||
45 | ** |
||
46 | ************************************************************************* |
||
47 | */ |
||
48 | #if !SQLITE_OMIT_DISKIO |
||
49 | //#include "sqliteInt.h" |
||
50 | //#include "wal.h" |
||
51 | |||
52 | |||
53 | /******************* NOTES ON THE DESIGN OF THE PAGER ************************ |
||
54 | ** |
||
55 | ** This comment block describes invariants that hold when using a rollback |
||
56 | ** journal. These invariants do not apply for journal_mode=WAL, |
||
57 | ** journal_mode=MEMORY, or journal_mode=OFF. |
||
58 | ** |
||
59 | ** Within this comment block, a page is deemed to have been synced |
||
60 | ** automatically as soon as it is written when PRAGMA synchronous=OFF. |
||
61 | ** Otherwise, the page is not synced until the xSync method of the VFS |
||
62 | ** is called successfully on the file containing the page. |
||
63 | ** |
||
64 | ** Definition: A page of the database file is said to be "overwriteable" if |
||
65 | ** one or more of the following are true about the page: |
||
66 | ** |
||
67 | ** (a) The original content of the page as it was at the beginning of |
||
68 | ** the transaction has been written into the rollback journal and |
||
69 | ** synced. |
||
70 | ** |
||
71 | ** (b) The page was a freelist leaf page at the start of the transaction. |
||
72 | ** |
||
73 | ** (c) The page number is greater than the largest page that existed in |
||
74 | ** the database file at the start of the transaction. |
||
75 | ** |
||
76 | ** (1) A page of the database file is never overwritten unless one of the |
||
77 | ** following are true: |
||
78 | ** |
||
79 | ** (a) The page and all other pages on the same sector are overwriteable. |
||
80 | ** |
||
81 | ** (b) The atomic page write optimization is enabled, and the entire |
||
82 | ** transaction other than the update of the transaction sequence |
||
83 | ** number consists of a single page change. |
||
84 | ** |
||
85 | ** (2) The content of a page written into the rollback journal exactly matches |
||
86 | ** both the content in the database when the rollback journal was written |
||
87 | ** and the content in the database at the beginning of the current |
||
88 | ** transaction. |
||
89 | ** |
||
90 | ** (3) Writes to the database file are an integer multiple of the page size |
||
91 | ** in length and are aligned on a page boundary. |
||
92 | ** |
||
93 | ** (4) Reads from the database file are either aligned on a page boundary and |
||
94 | ** an integer multiple of the page size in length or are taken from the |
||
95 | ** first 100 bytes of the database file. |
||
96 | ** |
||
97 | ** (5) All writes to the database file are synced prior to the rollback journal |
||
98 | ** being deleted, truncated, or zeroed. |
||
99 | ** |
||
100 | ** (6) If a master journal file is used, then all writes to the database file |
||
101 | ** are synced prior to the master journal being deleted. |
||
102 | ** |
||
103 | ** Definition: Two databases (or the same database at two points it time) |
||
104 | ** are said to be "logically equivalent" if they give the same answer to |
||
105 | ** all queries. Note in particular the the content of freelist leaf |
||
106 | ** pages can be changed arbitarily without effecting the logical equivalence |
||
107 | ** of the database. |
||
108 | ** |
||
109 | ** (7) At any time, if any subset, including the empty set and the total set, |
||
110 | ** of the unsynced changes to a rollback journal are removed and the |
||
111 | ** journal is rolled back, the resulting database file will be logical |
||
112 | ** equivalent to the database file at the beginning of the transaction. |
||
113 | ** |
||
114 | ** (8) When a transaction is rolled back, the xTruncate method of the VFS |
||
115 | ** is called to restore the database file to the same size it was at |
||
116 | ** the beginning of the transaction. (In some VFSes, the xTruncate |
||
117 | ** method is a no-op, but that does not change the fact the SQLite will |
||
118 | ** invoke it.) |
||
119 | ** |
||
120 | ** (9) Whenever the database file is modified, at least one bit in the range |
||
121 | ** of bytes from 24 through 39 inclusive will be changed prior to releasing |
||
122 | ** the EXCLUSIVE lock, thus signaling other connections on the same |
||
123 | ** database to flush their caches. |
||
124 | ** |
||
125 | ** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less |
||
126 | ** than one billion transactions. |
||
127 | ** |
||
128 | ** (11) A database file is well-formed at the beginning and at the conclusion |
||
129 | ** of every transaction. |
||
130 | ** |
||
131 | ** (12) An EXCLUSIVE lock is held on the database file when writing to |
||
132 | ** the database file. |
||
133 | ** |
||
134 | ** (13) A SHARED lock is held on the database file while reading any |
||
135 | ** content out of the database file. |
||
136 | ** |
||
137 | ******************************************************************************/ |
||
138 | |||
139 | /* |
||
140 | ** Macros for troubleshooting. Normally turned off |
||
141 | */ |
||
142 | #if TRACE |
||
143 | |||
144 | static bool sqlite3PagerTrace = false; /* True to enable tracing */ |
||
145 | //#define sqlite3DebugPrintf printf |
||
146 | //#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; } |
||
147 | static void PAGERTRACE( string T, params object[] ap ) { if ( sqlite3PagerTrace )sqlite3DebugPrintf( T, ap ); } |
||
148 | #else |
||
149 | //#define PAGERTRACE(X) |
||
150 | static void PAGERTRACE( string T, params object[] ap ) |
||
151 | { |
||
152 | } |
||
153 | #endif |
||
154 | |||
155 | /* |
||
156 | ** The following two macros are used within the PAGERTRACE() macros above |
||
157 | ** to print out file-descriptors. |
||
158 | ** |
||
159 | ** PAGERID() takes a pointer to a Pager struct as its argument. The |
||
160 | ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file |
||
161 | ** struct as its argument. |
||
162 | */ |
||
163 | //#define PAGERID(p) ((int)(p.fd)) |
||
164 | static int PAGERID( Pager p ) |
||
165 | { |
||
166 | return p.GetHashCode(); |
||
167 | } |
||
168 | |||
169 | //#define FILEHANDLEID(fd) ((int)fd) |
||
170 | static int FILEHANDLEID( sqlite3_file fd ) |
||
171 | { |
||
172 | return fd.GetHashCode(); |
||
173 | } |
||
174 | |||
175 | /* |
||
176 | ** The Pager.eState variable stores the current 'state' of a pager. A |
||
177 | ** pager may be in any one of the seven states shown in the following |
||
178 | ** state diagram. |
||
179 | ** |
||
180 | ** OPEN <------+------+ |
||
181 | ** | | | |
||
182 | ** V | | |
||
183 | ** +---------> READER-------+ | |
||
184 | ** | | | |
||
185 | ** | V | |
||
186 | ** |<-------WRITER_LOCKED------> ERROR |
||
187 | ** | | ^ |
||
188 | ** | V | |
||
189 | ** |<------WRITER_CACHEMOD-------->| |
||
190 | ** | | | |
||
191 | ** | V | |
||
192 | ** |<-------WRITER_DBMOD---------->| |
||
193 | ** | | | |
||
194 | ** | V | |
||
195 | ** +<------WRITER_FINISHED-------->+ |
||
196 | ** |
||
197 | ** |
||
198 | ** List of state transitions and the C [function] that performs each: |
||
199 | ** |
||
200 | ** OPEN -> READER [sqlite3PagerSharedLock] |
||
201 | ** READER -> OPEN [pager_unlock] |
||
202 | ** |
||
203 | ** READER -> WRITER_LOCKED [sqlite3PagerBegin] |
||
204 | ** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] |
||
205 | ** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] |
||
206 | ** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] |
||
207 | ** WRITER_*** -> READER [pager_end_transaction] |
||
208 | ** |
||
209 | ** WRITER_*** -> ERROR [pager_error] |
||
210 | ** ERROR -> OPEN [pager_unlock] |
||
211 | ** |
||
212 | ** |
||
213 | ** OPEN: |
||
214 | ** |
||
215 | ** The pager starts up in this state. Nothing is guaranteed in this |
||
216 | ** state - the file may or may not be locked and the database size is |
||
217 | ** unknown. The database may not be read or written. |
||
218 | ** |
||
219 | ** * No read or write transaction is active. |
||
220 | ** * Any lock, or no lock at all, may be held on the database file. |
||
221 | ** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. |
||
222 | ** |
||
223 | ** READER: |
||
224 | ** |
||
225 | ** In this state all the requirements for reading the database in |
||
226 | ** rollback (non-WAL) mode are met. Unless the pager is (or recently |
||
227 | ** was) in exclusive-locking mode, a user-level read transaction is |
||
228 | ** open. The database size is known in this state. |
||
229 | ** |
||
230 | ** A connection running with locking_mode=normal enters this state when |
||
231 | ** it opens a read-transaction on the database and returns to state |
||
232 | ** OPEN after the read-transaction is completed. However a connection |
||
233 | ** running in locking_mode=exclusive (including temp databases) remains in |
||
234 | ** this state even after the read-transaction is closed. The only way |
||
235 | ** a locking_mode=exclusive connection can transition from READER to OPEN |
||
236 | ** is via the ERROR state (see below). |
||
237 | ** |
||
238 | ** * A read transaction may be active (but a write-transaction cannot). |
||
239 | ** * A SHARED or greater lock is held on the database file. |
||
240 | ** * The dbSize variable may be trusted (even if a user-level read |
||
241 | ** transaction is not active). The dbOrigSize and dbFileSize variables |
||
242 | ** may not be trusted at this point. |
||
243 | ** * If the database is a WAL database, then the WAL connection is open. |
||
244 | ** * Even if a read-transaction is not open, it is guaranteed that |
||
245 | ** there is no hot-journal in the file-system. |
||
246 | ** |
||
247 | ** WRITER_LOCKED: |
||
248 | ** |
||
249 | ** The pager moves to this state from READER when a write-transaction |
||
250 | ** is first opened on the database. In WRITER_LOCKED state, all locks |
||
251 | ** required to start a write-transaction are held, but no actual |
||
252 | ** modifications to the cache or database have taken place. |
||
253 | ** |
||
254 | ** In rollback mode, a RESERVED or (if the transaction was opened with |
||
255 | ** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when |
||
256 | ** moving to this state, but the journal file is not written to or opened |
||
257 | ** to in this state. If the transaction is committed or rolled back while |
||
258 | ** in WRITER_LOCKED state, all that is required is to unlock the database |
||
259 | ** file. |
||
260 | ** |
||
261 | ** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. |
||
262 | ** If the connection is running with locking_mode=exclusive, an attempt |
||
263 | ** is made to obtain an EXCLUSIVE lock on the database file. |
||
264 | ** |
||
265 | ** * A write transaction is active. |
||
266 | ** * If the connection is open in rollback-mode, a RESERVED or greater |
||
267 | ** lock is held on the database file. |
||
268 | ** * If the connection is open in WAL-mode, a WAL write transaction |
||
269 | ** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully |
||
270 | ** called). |
||
271 | ** * The dbSize, dbOrigSize and dbFileSize variables are all valid. |
||
272 | ** * The contents of the pager cache have not been modified. |
||
273 | ** * The journal file may or may not be open. |
||
274 | ** * Nothing (not even the first header) has been written to the journal. |
||
275 | ** |
||
276 | ** WRITER_CACHEMOD: |
||
277 | ** |
||
278 | ** A pager moves from WRITER_LOCKED state to this state when a page is |
||
279 | ** first modified by the upper layer. In rollback mode the journal file |
||
280 | ** is opened (if it is not already open) and a header written to the |
||
281 | ** start of it. The database file on disk has not been modified. |
||
282 | ** |
||
283 | ** * A write transaction is active. |
||
284 | ** * A RESERVED or greater lock is held on the database file. |
||
285 | ** * The journal file is open and the first header has been written |
||
286 | ** to it, but the header has not been synced to disk. |
||
287 | ** * The contents of the page cache have been modified. |
||
288 | ** |
||
289 | ** WRITER_DBMOD: |
||
290 | ** |
||
291 | ** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state |
||
292 | ** when it modifies the contents of the database file. WAL connections |
||
293 | ** never enter this state (since they do not modify the database file, |
||
294 | ** just the log file). |
||
295 | ** |
||
296 | ** * A write transaction is active. |
||
297 | ** * An EXCLUSIVE or greater lock is held on the database file. |
||
298 | ** * The journal file is open and the first header has been written |
||
299 | ** and synced to disk. |
||
300 | ** * The contents of the page cache have been modified (and possibly |
||
301 | ** written to disk). |
||
302 | ** |
||
303 | ** WRITER_FINISHED: |
||
304 | ** |
||
305 | ** It is not possible for a WAL connection to enter this state. |
||
306 | ** |
||
307 | ** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD |
||
308 | ** state after the entire transaction has been successfully written into the |
||
309 | ** database file. In this state the transaction may be committed simply |
||
310 | ** by finalizing the journal file. Once in WRITER_FINISHED state, it is |
||
311 | ** not possible to modify the database further. At this point, the upper |
||
312 | ** layer must either commit or rollback the transaction. |
||
313 | ** |
||
314 | ** * A write transaction is active. |
||
315 | ** * An EXCLUSIVE or greater lock is held on the database file. |
||
316 | ** * All writing and syncing of journal and database data has finished. |
||
317 | ** If no error occured, all that remains is to finalize the journal to |
||
318 | ** commit the transaction. If an error did occur, the caller will need |
||
319 | ** to rollback the transaction. |
||
320 | ** |
||
321 | ** ERROR: |
||
322 | ** |
||
323 | ** The ERROR state is entered when an IO or disk-full error (including |
||
324 | ** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it |
||
325 | ** difficult to be sure that the in-memory pager state (cache contents, |
||
326 | ** db size etc.) are consistent with the contents of the file-system. |
||
327 | ** |
||
328 | ** Temporary pager files may enter the ERROR state, but in-memory pagers |
||
329 | ** cannot. |
||
330 | ** |
||
331 | ** For example, if an IO error occurs while performing a rollback, |
||
332 | ** the contents of the page-cache may be left in an inconsistent state. |
||
333 | ** At this point it would be dangerous to change back to READER state |
||
334 | ** (as usually happens after a rollback). Any subsequent readers might |
||
335 | ** report database corruption (due to the inconsistent cache), and if |
||
336 | ** they upgrade to writers, they may inadvertently corrupt the database |
||
337 | ** file. To avoid this hazard, the pager switches into the ERROR state |
||
338 | ** instead of READER following such an error. |
||
339 | ** |
||
340 | ** Once it has entered the ERROR state, any attempt to use the pager |
||
341 | ** to read or write data returns an error. Eventually, once all |
||
342 | ** outstanding transactions have been abandoned, the pager is able to |
||
343 | ** transition back to OPEN state, discarding the contents of the |
||
344 | ** page-cache and any other in-memory state at the same time. Everything |
||
345 | ** is reloaded from disk (and, if necessary, hot-journal rollback peformed) |
||
346 | ** when a read-transaction is next opened on the pager (transitioning |
||
347 | ** the pager into READER state). At that point the system has recovered |
||
348 | ** from the error. |
||
349 | ** |
||
350 | ** Specifically, the pager jumps into the ERROR state if: |
||
351 | ** |
||
352 | ** 1. An error occurs while attempting a rollback. This happens in |
||
353 | ** function sqlite3PagerRollback(). |
||
354 | ** |
||
355 | ** 2. An error occurs while attempting to finalize a journal file |
||
356 | ** following a commit in function sqlite3PagerCommitPhaseTwo(). |
||
357 | ** |
||
358 | ** 3. An error occurs while attempting to write to the journal or |
||
359 | ** database file in function pagerStress() in order to free up |
||
360 | ** memory. |
||
361 | ** |
||
362 | ** In other cases, the error is returned to the b-tree layer. The b-tree |
||
363 | ** layer then attempts a rollback operation. If the error condition |
||
364 | ** persists, the pager enters the ERROR state via condition (1) above. |
||
365 | ** |
||
366 | ** Condition (3) is necessary because it can be triggered by a read-only |
||
367 | ** statement executed within a transaction. In this case, if the error |
||
368 | ** code were simply returned to the user, the b-tree layer would not |
||
369 | ** automatically attempt a rollback, as it assumes that an error in a |
||
370 | ** read-only statement cannot leave the pager in an internally inconsistent |
||
371 | ** state. |
||
372 | ** |
||
373 | ** * The Pager.errCode variable is set to something other than SQLITE_OK. |
||
374 | ** * There are one or more outstanding references to pages (after the |
||
375 | ** last reference is dropped the pager should move back to OPEN state). |
||
376 | ** * The pager is not an in-memory pager. |
||
377 | ** |
||
378 | ** |
||
379 | ** Notes: |
||
380 | ** |
||
381 | ** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the |
||
382 | ** connection is open in WAL mode. A WAL connection is always in one |
||
383 | ** of the first four states. |
||
384 | ** |
||
385 | ** * Normally, a connection open in exclusive mode is never in PAGER_OPEN |
||
386 | ** state. There are two exceptions: immediately after exclusive-mode has |
||
387 | ** been turned on (and before any read or write transactions are |
||
388 | ** executed), and when the pager is leaving the "error state". |
||
389 | ** |
||
390 | ** * See also: assert_pager_state(). |
||
391 | */ |
||
392 | |||
393 | //#define PAGER_OPEN 0 |
||
394 | //#define PAGER_READER 1 |
||
395 | //#define PAGER_WRITER_LOCKED 2 |
||
396 | //#define PAGER_WRITER_CACHEMOD 3 |
||
397 | //#define PAGER_WRITER_DBMOD 4 |
||
398 | //#define PAGER_WRITER_FINISHED 5 |
||
399 | //#define PAGER_ERROR 6 |
||
400 | const int PAGER_OPEN = 0; |
||
401 | const int PAGER_READER = 1; |
||
402 | const int PAGER_WRITER_LOCKED = 2; |
||
403 | const int PAGER_WRITER_CACHEMOD = 3; |
||
404 | const int PAGER_WRITER_DBMOD = 4; |
||
405 | const int PAGER_WRITER_FINISHED = 5; |
||
406 | const int PAGER_ERROR = 6; |
||
407 | |||
408 | /* |
||
409 | ** The Pager.eLock variable is almost always set to one of the |
||
410 | ** following locking-states, according to the lock currently held on |
||
411 | ** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. |
||
412 | ** This variable is kept up to date as locks are taken and released by |
||
413 | ** the pagerLockDb() and pagerUnlockDb() wrappers. |
||
414 | ** |
||
415 | ** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY |
||
416 | ** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not |
||
417 | ** the operation was successful. In these circumstances pagerLockDb() and |
||
418 | ** pagerUnlockDb() take a conservative approach - eLock is always updated |
||
419 | ** when unlocking the file, and only updated when locking the file if the |
||
420 | ** VFS call is successful. This way, the Pager.eLock variable may be set |
||
421 | ** to a less exclusive (lower) value than the lock that is actually held |
||
422 | ** at the system level, but it is never set to a more exclusive value. |
||
423 | ** |
||
424 | ** This is usually safe. If an xUnlock fails or appears to fail, there may |
||
425 | ** be a few redundant xLock() calls or a lock may be held for longer than |
||
426 | ** required, but nothing really goes wrong. |
||
427 | ** |
||
428 | ** The exception is when the database file is unlocked as the pager moves |
||
429 | ** from ERROR to OPEN state. At this point there may be a hot-journal file |
||
430 | ** in the file-system that needs to be rolled back (as part of a OPEN->SHARED |
||
431 | ** transition, by the same pager or any other). If the call to xUnlock() |
||
432 | ** fails at this point and the pager is left holding an EXCLUSIVE lock, this |
||
433 | ** can confuse the call to xCheckReservedLock() call made later as part |
||
434 | ** of hot-journal detection. |
||
435 | ** |
||
436 | ** xCheckReservedLock() is defined as returning true "if there is a RESERVED |
||
437 | ** lock held by this process or any others". So xCheckReservedLock may |
||
438 | ** return true because the caller itself is holding an EXCLUSIVE lock (but |
||
439 | ** doesn't know it because of a previous error in xUnlock). If this happens |
||
440 | ** a hot-journal may be mistaken for a journal being created by an active |
||
441 | ** transaction in another process, causing SQLite to read from the database |
||
442 | ** without rolling it back. |
||
443 | ** |
||
444 | ** To work around this, if a call to xUnlock() fails when unlocking the |
||
445 | ** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It |
||
446 | ** is only changed back to a real locking state after a successful call |
||
447 | ** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition |
||
448 | ** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK |
||
449 | ** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE |
||
450 | ** lock on the database file before attempting to roll it back. See function |
||
451 | ** PagerSharedLock() for more detail. |
||
452 | ** |
||
453 | ** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in |
||
454 | ** PAGER_OPEN state. |
||
455 | */ |
||
456 | //#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) |
||
457 | const int UNKNOWN_LOCK = ( EXCLUSIVE_LOCK + 1 ); |
||
458 | |||
459 | /* |
||
460 | ** A macro used for invoking the codec if there is one |
||
461 | */ |
||
462 | |||
463 | // The E parameter is what executes when there is an error, |
||
464 | // cannot implement here, since this is not really a macro |
||
465 | // calling code must be modified to call E when truen |
||
466 | |||
467 | #if SQLITE_HAS_CODEC |
||
468 | //# define CODEC1(P,D,N,X,E) \ |
||
469 | //if( P.xCodec && P.xCodec(P.pCodec,D,N,X)==0 ){ E; } |
||
470 | static bool CODEC1( Pager P, byte[] D, uint N /* page number */, int X /* E (moved to caller */) |
||
471 | { |
||
472 | return ( ( P.xCodec != null ) && ( P.xCodec( P.pCodec, D, N, X ) == null ) ); |
||
473 | } |
||
474 | |||
475 | // The E parameter is what executes when there is an error, |
||
476 | // cannot implement here, since this is not really a macro |
||
477 | // calling code must be modified to call E when truen |
||
478 | |||
479 | //# define CODEC2(P,D,N,X,E,O) \ |
||
480 | //if( P.xCodec==0 ){ O=(char*)D; }else \ |
||
481 | //if( (O=(char*)(P.xCodec(P.pCodec,D,N,X)))==0 ){ E; } |
||
482 | static bool CODEC2( Pager P, byte[] D, uint N, int X, ref byte[] O ) |
||
483 | { |
||
484 | if ( P.xCodec == null ) |
||
485 | { |
||
486 | O = D; // do nothing |
||
487 | return false; |
||
488 | } |
||
489 | else |
||
490 | { |
||
491 | return ( ( O = P.xCodec( P.pCodec, D, N, X ) ) == null ); |
||
492 | } |
||
493 | } |
||
494 | #else |
||
495 | //# define CODEC1(P,D,N,X,E) /* NO-OP */ |
||
496 | static bool CODEC1 (Pager P, byte[] D, uint N /* page number */, int X /* E (moved to caller */) { return false; } |
||
497 | //# define CODEC2(P,D,N,X,E,O) O=(char*)D |
||
498 | static bool CODEC2( Pager P, byte[] D, uint N, int X, ref byte[] O ) { O = D; return false; } |
||
499 | #endif |
||
500 | |||
501 | /* |
||
502 | ** The maximum allowed sector size. 64KiB. If the xSectorsize() method |
||
503 | ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. |
||
504 | ** This could conceivably cause corruption following a power failure on |
||
505 | ** such a system. This is currently an undocumented limit. |
||
506 | */ |
||
507 | //#define MAX_SECTOR_SIZE 0x10000 |
||
508 | const int MAX_SECTOR_SIZE = 0x10000; |
||
509 | |||
510 | /* |
||
511 | ** An instance of the following structure is allocated for each active |
||
512 | ** savepoint and statement transaction in the system. All such structures |
||
513 | ** are stored in the Pager.aSavepoint[] array, which is allocated and |
||
514 | ** resized using sqlite3Realloc(). |
||
515 | ** |
||
516 | ** When a savepoint is created, the PagerSavepoint.iHdrOffset field is |
||
517 | ** set to 0. If a journal-header is written into the main journal while |
||
518 | ** the savepoint is active, then iHdrOffset is set to the byte offset |
||
519 | ** immediately following the last journal record written into the main |
||
520 | ** journal before the journal-header. This is required during savepoint |
||
521 | ** rollback (see pagerPlaybackSavepoint()). |
||
522 | */ |
||
523 | //typedef struct PagerSavepoint PagerSavepoint; |
||
524 | public class PagerSavepoint |
||
525 | { |
||
526 | public i64 iOffset; /* Starting offset in main journal */ |
||
527 | public i64 iHdrOffset; /* See above */ |
||
528 | public Bitvec pInSavepoint; /* Set of pages in this savepoint */ |
||
529 | public Pgno nOrig; /* Original number of pages in file */ |
||
530 | public Pgno iSubRec; /* Index of first record in sub-journal */ |
||
531 | #if !SQLITE_OMIT_WAL |
||
532 | public u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ |
||
533 | #else |
||
534 | public object aWalData = null; /* Used for C# convenience */ |
||
535 | #endif |
||
536 | public static implicit operator bool( PagerSavepoint b ) |
||
537 | { |
||
538 | return ( b != null ); |
||
539 | } |
||
540 | }; |
||
541 | |||
542 | |||
543 | /* |
||
544 | ** A open page cache is an instance of struct Pager. A description of |
||
545 | ** some of the more important member variables follows: |
||
546 | ** |
||
547 | ** eState |
||
548 | ** |
||
549 | ** The current 'state' of the pager object. See the comment and state |
||
550 | ** diagram above for a description of the pager state. |
||
551 | ** |
||
552 | ** eLock |
||
553 | ** |
||
554 | ** For a real on-disk database, the current lock held on the database file - |
||
555 | ** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. |
||
556 | ** |
||
557 | ** For a temporary or in-memory database (neither of which require any |
||
558 | ** locks), this variable is always set to EXCLUSIVE_LOCK. Since such |
||
559 | ** databases always have Pager.exclusiveMode==1, this tricks the pager |
||
560 | ** logic into thinking that it already has all the locks it will ever |
||
561 | ** need (and no reason to release them). |
||
562 | ** |
||
563 | ** In some (obscure) circumstances, this variable may also be set to |
||
564 | ** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for |
||
565 | ** details. |
||
566 | ** |
||
567 | ** changeCountDone |
||
568 | ** |
||
569 | ** This boolean variable is used to make sure that the change-counter |
||
570 | ** (the 4-byte header field at byte offset 24 of the database file) is |
||
571 | ** not updated more often than necessary. |
||
572 | ** |
||
573 | ** It is set to true when the change-counter field is updated, which |
||
574 | ** can only happen if an exclusive lock is held on the database file. |
||
575 | ** It is cleared (set to false) whenever an exclusive lock is |
||
576 | ** relinquished on the database file. Each time a transaction is committed, |
||
577 | ** The changeCountDone flag is inspected. If it is true, the work of |
||
578 | ** updating the change-counter is omitted for the current transaction. |
||
579 | ** |
||
580 | ** This mechanism means that when running in exclusive mode, a connection |
||
581 | ** need only update the change-counter once, for the first transaction |
||
582 | ** committed. |
||
583 | ** |
||
584 | ** setMaster |
||
585 | ** |
||
586 | ** When PagerCommitPhaseOne() is called to commit a transaction, it may |
||
587 | ** (or may not) specify a master-journal name to be written into the |
||
588 | ** journal file before it is synced to disk. |
||
589 | ** |
||
590 | ** Whether or not a journal file contains a master-journal pointer affects |
||
591 | ** the way in which the journal file is finalized after the transaction is |
||
592 | ** committed or rolled back when running in "journal_mode=PERSIST" mode. |
||
593 | ** If a journal file does not contain a master-journal pointer, it is |
||
594 | ** finalized by overwriting the first journal header with zeroes. If |
||
595 | ** it does contain a master-journal pointer the journal file is finalized |
||
596 | ** by truncating it to zero bytes, just as if the connection were |
||
597 | ** running in "journal_mode=truncate" mode. |
||
598 | ** |
||
599 | ** Journal files that contain master journal pointers cannot be finalized |
||
600 | ** simply by overwriting the first journal-header with zeroes, as the |
||
601 | ** master journal pointer could interfere with hot-journal rollback of any |
||
602 | ** subsequently interrupted transaction that reuses the journal file. |
||
603 | ** |
||
604 | ** The flag is cleared as soon as the journal file is finalized (either |
||
605 | ** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the |
||
606 | ** journal file from being successfully finalized, the setMaster flag |
||
607 | ** is cleared anyway (and the pager will move to ERROR state). |
||
608 | ** |
||
609 | ** doNotSpill, doNotSyncSpill |
||
610 | ** |
||
611 | ** These two boolean variables control the behaviour of cache-spills |
||
612 | ** (calls made by the pcache module to the pagerStress() routine to |
||
613 | ** write cached data to the file-system in order to free up memory). |
||
614 | ** |
||
615 | ** When doNotSpill is non-zero, writing to the database from pagerStress() |
||
616 | ** is disabled altogether. This is done in a very obscure case that |
||
617 | ** comes up during savepoint rollback that requires the pcache module |
||
618 | ** to allocate a new page to prevent the journal file from being written |
||
619 | ** while it is being traversed by code in pager_playback(). |
||
620 | ** |
||
621 | ** If doNotSyncSpill is non-zero, writing to the database from pagerStress() |
||
622 | ** is permitted, but syncing the journal file is not. This flag is set |
||
623 | ** by sqlite3PagerWrite() when the file-system sector-size is larger than |
||
624 | ** the database page-size in order to prevent a journal sync from happening |
||
625 | ** in between the journalling of two pages on the same sector. |
||
626 | ** |
||
627 | ** subjInMemory |
||
628 | ** |
||
629 | ** This is a boolean variable. If true, then any required sub-journal |
||
630 | ** is opened as an in-memory journal file. If false, then in-memory |
||
631 | ** sub-journals are only used for in-memory pager files. |
||
632 | ** |
||
633 | ** This variable is updated by the upper layer each time a new |
||
634 | ** write-transaction is opened. |
||
635 | ** |
||
636 | ** dbSize, dbOrigSize, dbFileSize |
||
637 | ** |
||
638 | ** Variable dbSize is set to the number of pages in the database file. |
||
639 | ** It is valid in PAGER_READER and higher states (all states except for |
||
640 | ** OPEN and ERROR). |
||
641 | ** |
||
642 | ** dbSize is set based on the size of the database file, which may be |
||
643 | ** larger than the size of the database (the value stored at offset |
||
644 | ** 28 of the database header by the btree). If the size of the file |
||
645 | ** is not an integer multiple of the page-size, the value stored in |
||
646 | ** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). |
||
647 | ** Except, any file that is greater than 0 bytes in size is considered |
||
648 | ** to have at least one page. (i.e. a 1KB file with 2K page-size leads |
||
649 | ** to dbSize==1). |
||
650 | ** |
||
651 | ** During a write-transaction, if pages with page-numbers greater than |
||
652 | ** dbSize are modified in the cache, dbSize is updated accordingly. |
||
653 | ** Similarly, if the database is truncated using PagerTruncateImage(), |
||
654 | ** dbSize is updated. |
||
655 | ** |
||
656 | ** Variables dbOrigSize and dbFileSize are valid in states |
||
657 | ** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize |
||
658 | ** variable at the start of the transaction. It is used during rollback, |
||
659 | ** and to determine whether or not pages need to be journalled before |
||
660 | ** being modified. |
||
661 | ** |
||
662 | ** Throughout a write-transaction, dbFileSize contains the size of |
||
663 | ** the file on disk in pages. It is set to a copy of dbSize when the |
||
664 | ** write-transaction is first opened, and updated when VFS calls are made |
||
665 | ** to write or truncate the database file on disk. |
||
666 | ** |
||
667 | ** The only reason the dbFileSize variable is required is to suppress |
||
668 | ** unnecessary calls to xTruncate() after committing a transaction. If, |
||
669 | ** when a transaction is committed, the dbFileSize variable indicates |
||
670 | ** that the database file is larger than the database image (Pager.dbSize), |
||
671 | ** pager_truncate() is called. The pager_truncate() call uses xFilesize() |
||
672 | ** to measure the database file on disk, and then truncates it if required. |
||
673 | ** dbFileSize is not used when rolling back a transaction. In this case |
||
674 | ** pager_truncate() is called unconditionally (which means there may be |
||
675 | ** a call to xFilesize() that is not strictly required). In either case, |
||
676 | ** pager_truncate() may cause the file to become smaller or larger. |
||
677 | ** |
||
678 | ** dbHintSize |
||
679 | ** |
||
680 | ** The dbHintSize variable is used to limit the number of calls made to |
||
681 | ** the VFS xFileControl(FCNTL_SIZE_HINT) method. |
||
682 | ** |
||
683 | ** dbHintSize is set to a copy of the dbSize variable when a |
||
684 | ** write-transaction is opened (at the same time as dbFileSize and |
||
685 | ** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, |
||
686 | ** dbHintSize is increased to the number of pages that correspond to the |
||
687 | ** size-hint passed to the method call. See pager_write_pagelist() for |
||
688 | ** details. |
||
689 | ** |
||
690 | ** errCode |
||
691 | ** |
||
692 | ** The Pager.errCode variable is only ever used in PAGER_ERROR state. It |
||
693 | ** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode |
||
694 | ** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX |
||
695 | ** sub-codes. |
||
696 | */ |
||
697 | public class Pager |
||
698 | { |
||
699 | public sqlite3_vfs pVfs; /* OS functions to use for IO */ |
||
700 | public bool exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ |
||
701 | public u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
||
702 | public u8 useJournal; /* Use a rollback journal on this file */ |
||
703 | public u8 noReadlock; /* Do not bother to obtain readlocks */ |
||
704 | public bool noSync; /* Do not sync the journal if true */ |
||
705 | public bool fullSync; /* Do extra syncs of the journal for robustness */ |
||
706 | public u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
||
707 | public u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
||
708 | public bool tempFile; /* zFilename is a temporary file */ |
||
709 | public bool readOnly; /* True for a read-only database */ |
||
710 | public bool alwaysRollback; /* Disable DontRollback() for all pages */ |
||
711 | public u8 memDb; /* True to inhibit all file I/O */ |
||
712 | /************************************************************************** |
||
713 | ** The following block contains those class members that change during |
||
714 | ** routine opertion. Class members not in this block are either fixed |
||
715 | ** when the pager is first created or else only change when there is a |
||
716 | ** significant mode change (such as changing the page_size, locking_mode, |
||
717 | ** or the journal_mode). From another view, these class members describe |
||
718 | ** the "state" of the pager, while other class members describe the |
||
719 | ** "configuration" of the pager. |
||
720 | */ |
||
721 | public u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ |
||
722 | public u8 eLock; /* Current lock held on database file */ |
||
723 | public bool changeCountDone; /* Set after incrementing the change-counter */ |
||
724 | public int setMaster; /* True if a m-j name has been written to jrnl */ |
||
725 | public u8 doNotSpill; /* Do not spill the cache when non-zero */ |
||
726 | public u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */ |
||
727 | public u8 subjInMemory; /* True to use in-memory sub-journals */ |
||
728 | public Pgno dbSize; /* Number of pages in the database */ |
||
729 | public Pgno dbOrigSize; /* dbSize before the current transaction */ |
||
730 | public Pgno dbFileSize; /* Number of pages in the database file */ |
||
731 | public Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
||
732 | public int errCode; /* One of several kinds of errors */ |
||
733 | public int nRec; /* Pages journalled since last j-header written */ |
||
734 | public u32 cksumInit; /* Quasi-random value added to every checksum */ |
||
735 | public u32 nSubRec; /* Number of records written to sub-journal */ |
||
736 | public Bitvec pInJournal; /* One bit for each page in the database file */ |
||
737 | public sqlite3_file fd; /* File descriptor for database */ |
||
738 | public sqlite3_file jfd; /* File descriptor for main journal */ |
||
739 | public sqlite3_file sjfd; /* File descriptor for sub-journal */ |
||
740 | public i64 journalOff; /* Current write offset in the journal file */ |
||
741 | public i64 journalHdr; /* Byte offset to previous journal header */ |
||
742 | public sqlite3_backup pBackup; /* Pointer to list of ongoing backup processes */ |
||
743 | public PagerSavepoint[] aSavepoint;/* Array of active savepoints */ |
||
744 | public int nSavepoint; /* Number of elements in aSavepoint[] */ |
||
745 | public u8[] dbFileVers = new u8[16];/* Changes whenever database file changes */ |
||
746 | /* |
||
747 | ** End of the routinely-changing class members |
||
748 | ***************************************************************************/ |
||
749 | |||
750 | public u16 nExtra; /* Add this many bytes to each in-memory page */ |
||
751 | public i16 nReserve; /* Number of unused bytes at end of each page */ |
||
752 | public u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ |
||
753 | public u32 sectorSize; /* Assumed sector size during rollback */ |
||
754 | public int pageSize; /* Number of bytes in a page */ |
||
755 | public Pgno mxPgno; /* Maximum allowed size of the database */ |
||
756 | public i64 journalSizeLimit; /* Size limit for persistent journal files */ |
||
757 | public string zFilename; /* Name of the database file */ |
||
758 | public string zJournal; /* Name of the journal file */ |
||
759 | public dxBusyHandler xBusyHandler; /* Function to call when busy */ |
||
760 | public object pBusyHandlerArg; /* Context argument for xBusyHandler */ |
||
761 | #if SQLITE_TEST || DEBUG |
||
762 | public int nHit, nMiss; /* Cache hits and missing */ |
||
763 | public int nRead, nWrite; /* Database pages read/written */ |
||
764 | #else |
||
765 | public int nHit; |
||
766 | #endif |
||
767 | public dxReiniter xReiniter; //(DbPage*,int);/* Call this routine when reloading pages */ |
||
768 | #if SQLITE_HAS_CODEC |
||
769 | //void *(*xCodec)(void*,void*,Pgno,int); |
||
770 | public dxCodec xCodec; /* Routine for en/decoding data */ |
||
771 | //void (*xCodecSizeChng)(void*,int,int); |
||
772 | public dxCodecSizeChng xCodecSizeChng; /* Notify of page size changes */ |
||
773 | //void (*xCodecFree)(void*); |
||
774 | public dxCodecFree xCodecFree; /* Destructor for the codec */ |
||
775 | public codec_ctx pCodec; /* First argument to xCodec... methods */ |
||
776 | #endif |
||
777 | public byte[] pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ |
||
778 | public PCache pPCache; /* Pointer to page cache object */ |
||
779 | #if !SQLITE_OMIT_WAL |
||
780 | public Wal pWal; /* Write-ahead log used by "journal_mode=wal" */ |
||
781 | public string zWal; /* File name for write-ahead log */ |
||
782 | #else |
||
783 | public sqlite3_vfs pWal = null; /* Having this dummy here makes C# easier */ |
||
784 | #endif |
||
785 | }; |
||
786 | |||
787 | /* |
||
788 | ** The following global variables hold counters used for |
||
789 | ** testing purposes only. These variables do not exist in |
||
790 | ** a non-testing build. These variables are not thread-safe. |
||
791 | */ |
||
792 | #if SQLITE_TEST |
||
793 | #if !TCLSH |
||
794 | static int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ |
||
795 | static int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ |
||
796 | static int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ |
||
797 | #else |
||
798 | static tcl.lang.Var.SQLITE3_GETSET sqlite3_pager_readdb_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_pager_readdb_count" ); |
||
799 | static tcl.lang.Var.SQLITE3_GETSET sqlite3_pager_writedb_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_pager_writedb_count" ); |
||
800 | static tcl.lang.Var.SQLITE3_GETSET sqlite3_pager_writej_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_pager_writej_count" ); |
||
801 | #endif |
||
802 | static void PAGER_INCR( ref int v ) |
||
803 | { |
||
804 | v++; |
||
805 | } |
||
806 | #else |
||
807 | //# define PAGER_INCR(v) |
||
808 | static void PAGER_INCR(ref int v) {} |
||
809 | #endif |
||
810 | |||
811 | /* |
||
812 | ** Journal files begin with the following magic string. The data |
||
813 | ** was obtained from /dev/random. It is used only as a sanity check. |
||
814 | ** |
||
815 | ** Since version 2.8.0, the journal format contains additional sanity |
||
816 | ** checking information. If the power fails while the journal is being |
||
817 | ** written, semi-random garbage data might appear in the journal |
||
818 | ** file after power is restored. If an attempt is then made |
||
819 | ** to roll the journal back, the database could be corrupted. The additional |
||
820 | ** sanity checking data is an attempt to discover the garbage in the |
||
821 | ** journal and ignore it. |
||
822 | ** |
||
823 | ** The sanity checking information for the new journal format consists |
||
824 | ** of a 32-bit checksum on each page of data. The checksum covers both |
||
825 | ** the page number and the pPager.pageSize bytes of data for the page. |
||
826 | ** This cksum is initialized to a 32-bit random value that appears in the |
||
827 | ** journal file right after the header. The random initializer is important, |
||
828 | ** because garbage data that appears at the end of a journal is likely |
||
829 | ** data that was once in other files that have now been deleted. If the |
||
830 | ** garbage data came from an obsolete journal file, the checksums might |
||
831 | ** be correct. But by initializing the checksum to random value which |
||
832 | ** is different for every journal, we minimize that risk. |
||
833 | */ |
||
834 | static byte[] aJournalMagic = new byte[] { |
||
835 | 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, |
||
836 | }; |
||
837 | /* |
||
838 | ** The size of the of each page record in the journal is given by |
||
839 | ** the following macro. |
||
840 | */ |
||
841 | //#define JOURNAL_PG_SZ(pPager) ((pPager.pageSize) + 8) |
||
842 | static int JOURNAL_PG_SZ( Pager pPager ) |
||
843 | { |
||
844 | return ( pPager.pageSize + 8 ); |
||
845 | } |
||
846 | |||
847 | /* |
||
848 | ** The journal header size for this pager. This is usually the same |
||
849 | ** size as a single disk sector. See also setSectorSize(). |
||
850 | */ |
||
851 | //#define JOURNAL_HDR_SZ(pPager) (pPager.sectorSize) |
||
852 | static u32 JOURNAL_HDR_SZ( Pager pPager ) |
||
853 | { |
||
854 | return ( pPager.sectorSize ); |
||
855 | } |
||
856 | |||
857 | /* |
||
858 | ** The macro MEMDB is true if we are dealing with an in-memory database. |
||
859 | ** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, |
||
860 | ** the value of MEMDB will be a constant and the compiler will optimize |
||
861 | ** out code that would never execute. |
||
862 | */ |
||
863 | #if SQLITE_OMIT_MEMORYDB |
||
864 | //# define MEMDB 0 |
||
865 | const int MEMDB = 0; |
||
866 | #else |
||
867 | //# define MEMDB pPager.memDb |
||
868 | #endif |
||
869 | |||
870 | /* |
||
871 | ** The maximum legal page number is (2^31 - 1). |
||
872 | */ |
||
873 | //#define PAGER_MAX_PGNO 2147483647 |
||
874 | const int PAGER_MAX_PGNO = 2147483647; |
||
875 | |||
876 | /* |
||
877 | ** The argument to this macro is a file descriptor (type sqlite3_file*). |
||
878 | ** Return 0 if it is not open, or non-zero (but not 1) if it is. |
||
879 | ** |
||
880 | ** This is so that expressions can be written as: |
||
881 | ** |
||
882 | ** if( isOpen(pPager.jfd) ){ ... |
||
883 | ** |
||
884 | ** instead of |
||
885 | ** |
||
886 | ** if( pPager.jfd->pMethods ){ ... |
||
887 | */ |
||
888 | //#define isOpen(pFd) ((pFd)->pMethods) |
||
889 | static bool isOpen( sqlite3_file pFd ) |
||
890 | { |
||
891 | return pFd.pMethods != null; |
||
892 | } |
||
893 | |||
894 | /* |
||
895 | ** Return true if this pager uses a write-ahead log instead of the usual |
||
896 | ** rollback journal. Otherwise false. |
||
897 | */ |
||
898 | #if !SQLITE_OMIT_WAL |
||
899 | static int pagerUseWal(Pager *pPager){ |
||
900 | return (pPager->pWal!=0); |
||
901 | } |
||
902 | #else |
||
903 | //# define pagerUseWal(x) 0 |
||
904 | static bool pagerUseWal( Pager x ) |
||
905 | { |
||
906 | return false; |
||
907 | } |
||
908 | //# define pagerRollbackWal(x) 0 |
||
909 | static int pagerRollbackWal( Pager x ) |
||
910 | { |
||
911 | return 0; |
||
912 | } |
||
913 | //# define pagerWalFrames(v,w,x,y,z) 0 |
||
914 | static int pagerWalFrames( Pager v, PgHdr w, Pgno x, int y, int z ) |
||
915 | { |
||
916 | return 0; |
||
917 | } |
||
918 | //# define pagerOpenWalIfPresent(z) SQLITE_OK |
||
919 | static int pagerOpenWalIfPresent( Pager z ) |
||
920 | { |
||
921 | return SQLITE_OK; |
||
922 | } |
||
923 | //# define pagerBeginReadTransaction(z) SQLITE_OK |
||
924 | static int pagerBeginReadTransaction( Pager z ) |
||
925 | { |
||
926 | return SQLITE_OK; |
||
927 | } |
||
928 | #endif |
||
929 | |||
930 | #if NDEBUG |
||
931 | /* |
||
932 | ** Usage: |
||
933 | ** |
||
934 | ** Debug.Assert( assert_pager_state(pPager) ); |
||
935 | ** |
||
936 | ** This function runs many Debug.Asserts to try to find inconsistencies in |
||
937 | ** the internal state of the Pager object. |
||
938 | */ |
||
939 | static bool assert_pager_state( Pager p ) |
||
940 | { |
||
941 | Pager pPager = p; |
||
942 | |||
943 | /* State must be valid. */ |
||
944 | Debug.Assert( p.eState == PAGER_OPEN |
||
945 | || p.eState == PAGER_READER |
||
946 | || p.eState == PAGER_WRITER_LOCKED |
||
947 | || p.eState == PAGER_WRITER_CACHEMOD |
||
948 | || p.eState == PAGER_WRITER_DBMOD |
||
949 | || p.eState == PAGER_WRITER_FINISHED |
||
950 | || p.eState == PAGER_ERROR |
||
951 | ); |
||
952 | |||
953 | /* Regardless of the current state, a temp-file connection always behaves |
||
954 | ** as if it has an exclusive lock on the database file. It never updates |
||
955 | ** the change-counter field, so the changeCountDone flag is always set. |
||
956 | */ |
||
957 | Debug.Assert( p.tempFile == false || p.eLock == EXCLUSIVE_LOCK ); |
||
958 | Debug.Assert( p.tempFile == false || pPager.changeCountDone ); |
||
959 | |||
960 | /* If the useJournal flag is clear, the journal-mode must be "OFF". |
||
961 | ** And if the journal-mode is "OFF", the journal file must not be open. |
||
962 | */ |
||
963 | Debug.Assert( p.journalMode == PAGER_JOURNALMODE_OFF || p.useJournal != 0 ); |
||
964 | Debug.Assert( p.journalMode != PAGER_JOURNALMODE_OFF || !isOpen( p.jfd ) ); |
||
965 | |||
966 | /* Check that MEMDB implies noSync. And an in-memory journal. Since |
||
967 | ** this means an in-memory pager performs no IO at all, it cannot encounter |
||
968 | ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing |
||
969 | ** a journal file. (although the in-memory journal implementation may |
||
970 | ** return SQLITE_IOERR_NOMEM while the journal file is being written). It |
||
971 | ** is therefore not possible for an in-memory pager to enter the ERROR |
||
972 | ** state. |
||
973 | */ |
||
974 | if ( |
||
975 | #if SQLITE_OMIT_MEMORYDB |
||
976 | 0!=MEMDB |
||
977 | #else |
||
978 | |||
979 | #endif |
||
980 | ) |
||
981 | { |
||
982 | Debug.Assert( p.noSync ); |
||
983 | Debug.Assert( p.journalMode == PAGER_JOURNALMODE_OFF |
||
984 | || p.journalMode == PAGER_JOURNALMODE_MEMORY |
||
985 | ); |
||
986 | Debug.Assert( p.eState != PAGER_ERROR && p.eState != PAGER_OPEN ); |
||
987 | Debug.Assert( pagerUseWal( p ) == false ); |
||
988 | } |
||
989 | |||
990 | /* If changeCountDone is set, a RESERVED lock or greater must be held |
||
991 | ** on the file. |
||
992 | */ |
||
993 | Debug.Assert( pPager.changeCountDone == false || pPager.eLock >= RESERVED_LOCK ); |
||
994 | Debug.Assert( p.eLock != PENDING_LOCK ); |
||
995 | |||
996 | switch ( p.eState ) |
||
997 | { |
||
998 | case PAGER_OPEN: |
||
999 | Debug.Assert( |
||
1000 | #if SQLITE_OMIT_MEMORYDB |
||
1001 | 0==MEMDB |
||
1002 | #else |
||
1003 | |||
1004 | #endif |
||
1005 | ); |
||
1006 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1007 | Debug.Assert( sqlite3PcacheRefCount( pPager.pPCache ) == 0 || pPager.tempFile ); |
||
1008 | break; |
||
1009 | |||
1010 | case PAGER_READER: |
||
1011 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1012 | Debug.Assert( p.eLock != UNKNOWN_LOCK ); |
||
1013 | Debug.Assert( p.eLock >= SHARED_LOCK || p.noReadlock != 0 ); |
||
1014 | break; |
||
1015 | |||
1016 | case PAGER_WRITER_LOCKED: |
||
1017 | Debug.Assert( p.eLock != UNKNOWN_LOCK ); |
||
1018 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1019 | if ( !pagerUseWal( pPager ) ) |
||
1020 | { |
||
1021 | Debug.Assert( p.eLock >= RESERVED_LOCK ); |
||
1022 | } |
||
1023 | Debug.Assert( pPager.dbSize == pPager.dbOrigSize ); |
||
1024 | Debug.Assert( pPager.dbOrigSize == pPager.dbFileSize ); |
||
1025 | Debug.Assert( pPager.dbOrigSize == pPager.dbHintSize ); |
||
1026 | Debug.Assert( pPager.setMaster == 0 ); |
||
1027 | break; |
||
1028 | |||
1029 | case PAGER_WRITER_CACHEMOD: |
||
1030 | Debug.Assert( p.eLock != UNKNOWN_LOCK ); |
||
1031 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1032 | if ( !pagerUseWal( pPager ) ) |
||
1033 | { |
||
1034 | /* It is possible that if journal_mode=wal here that neither the |
||
1035 | ** journal file nor the WAL file are open. This happens during |
||
1036 | ** a rollback transaction that switches from journal_mode=off |
||
1037 | ** to journal_mode=wal. |
||
1038 | */ |
||
1039 | Debug.Assert( p.eLock >= RESERVED_LOCK ); |
||
1040 | Debug.Assert( isOpen( p.jfd ) |
||
1041 | || p.journalMode == PAGER_JOURNALMODE_OFF |
||
1042 | || p.journalMode == PAGER_JOURNALMODE_WAL |
||
1043 | ); |
||
1044 | } |
||
1045 | Debug.Assert( pPager.dbOrigSize == pPager.dbFileSize ); |
||
1046 | Debug.Assert( pPager.dbOrigSize == pPager.dbHintSize ); |
||
1047 | break; |
||
1048 | |||
1049 | case PAGER_WRITER_DBMOD: |
||
1050 | Debug.Assert( p.eLock == EXCLUSIVE_LOCK ); |
||
1051 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1052 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
1053 | Debug.Assert( p.eLock >= EXCLUSIVE_LOCK ); |
||
1054 | Debug.Assert( isOpen( p.jfd ) |
||
1055 | || p.journalMode == PAGER_JOURNALMODE_OFF |
||
1056 | || p.journalMode == PAGER_JOURNALMODE_WAL |
||
1057 | ); |
||
1058 | Debug.Assert( pPager.dbOrigSize <= pPager.dbHintSize ); |
||
1059 | break; |
||
1060 | |||
1061 | case PAGER_WRITER_FINISHED: |
||
1062 | Debug.Assert( p.eLock == EXCLUSIVE_LOCK ); |
||
1063 | Debug.Assert( pPager.errCode == SQLITE_OK ); |
||
1064 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
1065 | Debug.Assert( isOpen( p.jfd ) |
||
1066 | || p.journalMode == PAGER_JOURNALMODE_OFF |
||
1067 | || p.journalMode == PAGER_JOURNALMODE_WAL |
||
1068 | ); |
||
1069 | break; |
||
1070 | |||
1071 | case PAGER_ERROR: |
||
1072 | /* There must be at least one outstanding reference to the pager if |
||
1073 | ** in ERROR state. Otherwise the pager should have already dropped |
||
1074 | ** back to OPEN state. |
||
1075 | */ |
||
1076 | Debug.Assert( pPager.errCode != SQLITE_OK ); |
||
1077 | Debug.Assert( sqlite3PcacheRefCount( pPager.pPCache ) > 0 ); |
||
1078 | break; |
||
1079 | } |
||
1080 | |||
1081 | return true; |
||
1082 | } |
||
1083 | #else |
||
1084 | static bool assert_pager_state( Pager pPager ) |
||
1085 | { |
||
1086 | return true; |
||
1087 | } |
||
1088 | #endif //* ifndef NDEBUG */ |
||
1089 | |||
1090 | #if SQLITE_DEBUG |
||
1091 | /* |
||
1092 | ** Return a pointer to a human readable string in a static buffer |
||
1093 | ** containing the state of the Pager object passed as an argument. This |
||
1094 | ** is intended to be used within debuggers. For example, as an alternative |
||
1095 | ** to "print *pPager" in gdb: |
||
1096 | ** |
||
1097 | ** (gdb) printf "%s", print_pager_state(pPager) |
||
1098 | */ |
||
1099 | static string print_pager_state( Pager p ) |
||
1100 | { |
||
1101 | StringBuilder zRet = new StringBuilder( 1024 ); |
||
1102 | |||
1103 | sqlite3_snprintf( 1024, zRet, |
||
1104 | "Filename: %s\n" + |
||
1105 | "State: %s errCode=%d\n" + |
||
1106 | "Lock: %s\n" + |
||
1107 | "Locking mode: locking_mode=%s\n" + |
||
1108 | "Journal mode: journal_mode=%s\n" + |
||
1109 | "Backing store: tempFile=%d memDb=%d useJournal=%d\n" + |
||
1110 | "Journal: journalOff=%lld journalHdr=%lld\n" + |
||
1111 | "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n" |
||
1112 | , p.zFilename |
||
1113 | , p.eState == PAGER_OPEN ? "OPEN" : |
||
1114 | p.eState == PAGER_READER ? "READER" : |
||
1115 | p.eState == PAGER_WRITER_LOCKED ? "WRITER_LOCKED" : |
||
1116 | p.eState == PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : |
||
1117 | p.eState == PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : |
||
1118 | p.eState == PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : |
||
1119 | p.eState == PAGER_ERROR ? "ERROR" : "?error?" |
||
1120 | , (int)p.errCode |
||
1121 | , p.eLock == NO_LOCK ? "NO_LOCK" : |
||
1122 | p.eLock == RESERVED_LOCK ? "RESERVED" : |
||
1123 | p.eLock == EXCLUSIVE_LOCK ? "EXCLUSIVE" : |
||
1124 | p.eLock == SHARED_LOCK ? "SHARED" : |
||
1125 | p.eLock == UNKNOWN_LOCK ? "UNKNOWN" : "?error?" |
||
1126 | , p.exclusiveMode ? "exclusive" : "normal" |
||
1127 | , p.journalMode == PAGER_JOURNALMODE_MEMORY ? "memory" : |
||
1128 | p.journalMode == PAGER_JOURNALMODE_OFF ? "off" : |
||
1129 | p.journalMode == PAGER_JOURNALMODE_DELETE ? "delete" : |
||
1130 | p.journalMode == PAGER_JOURNALMODE_PERSIST ? "persist" : |
||
1131 | p.journalMode == PAGER_JOURNALMODE_TRUNCATE ? "truncate" : |
||
1132 | p.journalMode == PAGER_JOURNALMODE_WAL ? "wal" : "?error?" |
||
1133 | , p.tempFile ? 1 : 0, (int)p.memDb, (int)p.useJournal |
||
1134 | , p.journalOff, p.journalHdr |
||
1135 | , (int)p.dbSize, (int)p.dbOrigSize, (int)p.dbFileSize |
||
1136 | ); |
||
1137 | |||
1138 | return zRet.ToString(); |
||
1139 | } |
||
1140 | #endif |
||
1141 | |||
1142 | /* |
||
1143 | ** Return true if it is necessary to write page *pPg into the sub-journal. |
||
1144 | ** A page needs to be written into the sub-journal if there exists one |
||
1145 | ** or more open savepoints for which: |
||
1146 | ** |
||
1147 | ** * The page-number is less than or equal to PagerSavepoint.nOrig, and |
||
1148 | ** * The bit corresponding to the page-number is not set in |
||
1149 | ** PagerSavepoint.pInSavepoint. |
||
1150 | */ |
||
1151 | static bool subjRequiresPage( PgHdr pPg ) |
||
1152 | { |
||
1153 | u32 pgno = pPg.pgno; |
||
1154 | Pager pPager = pPg.pPager; |
||
1155 | int i; |
||
1156 | for ( i = 0; i < pPager.nSavepoint; i++ ) |
||
1157 | { |
||
1158 | PagerSavepoint p = pPager.aSavepoint[i]; |
||
1159 | if ( p.nOrig >= pgno && 0 == sqlite3BitvecTest( p.pInSavepoint, pgno ) ) |
||
1160 | { |
||
1161 | return true; |
||
1162 | } |
||
1163 | } |
||
1164 | return false; |
||
1165 | } |
||
1166 | |||
1167 | /* |
||
1168 | ** Return true if the page is already in the journal file. |
||
1169 | */ |
||
1170 | static bool pageInJournal( PgHdr pPg ) |
||
1171 | { |
||
1172 | return sqlite3BitvecTest( pPg.pPager.pInJournal, pPg.pgno ) != 0; |
||
1173 | } |
||
1174 | |||
1175 | /* |
||
1176 | ** Read a 32-bit integer from the given file descriptor. Store the integer |
||
1177 | ** that is read in pRes. Return SQLITE_OK if everything worked, or an |
||
1178 | ** error code is something goes wrong. |
||
1179 | ** |
||
1180 | ** All values are stored on disk as big-endian. |
||
1181 | */ |
||
1182 | static int read32bits( sqlite3_file fd, int offset, ref int pRes ) |
||
1183 | { |
||
1184 | u32 u32_pRes = 0; |
||
1185 | int rc = read32bits( fd, offset, ref u32_pRes ); |
||
1186 | pRes = (int)u32_pRes; |
||
1187 | return rc; |
||
1188 | } |
||
1189 | static int read32bits( sqlite3_file fd, i64 offset, ref u32 pRes ) |
||
1190 | { |
||
1191 | int rc = read32bits( fd, (int)offset, ref pRes ); |
||
1192 | return rc; |
||
1193 | } |
||
1194 | static int read32bits( sqlite3_file fd, int offset, ref u32 pRes ) |
||
1195 | { |
||
1196 | byte[] ac = new byte[4]; |
||
1197 | int rc = sqlite3OsRead( fd, ac, ac.Length, offset ); |
||
1198 | if ( rc == SQLITE_OK ) |
||
1199 | { |
||
1200 | pRes = sqlite3Get4byte( ac ); |
||
1201 | } |
||
1202 | else |
||
1203 | pRes = 0; |
||
1204 | return rc; |
||
1205 | } |
||
1206 | |||
1207 | /* |
||
1208 | ** Write a 32-bit integer into a string buffer in big-endian byte order. |
||
1209 | */ |
||
1210 | //#define put32bits(A,B) sqlite3sqlite3Put4byte((u8*)A,B) |
||
1211 | static void put32bits( string ac, int offset, int val ) |
||
1212 | { |
||
1213 | byte[] A = new byte[4]; |
||
1214 | A[0] = (byte)ac[offset + 0]; |
||
1215 | A[1] = (byte)ac[offset + 1]; |
||
1216 | A[2] = (byte)ac[offset + 2]; |
||
1217 | A[3] = (byte)ac[offset + 3]; |
||
1218 | sqlite3Put4byte( A, 0, val ); |
||
1219 | } |
||
1220 | static void put32bits( byte[] ac, int offset, int val ) |
||
1221 | { |
||
1222 | sqlite3Put4byte( ac, offset, (u32)val ); |
||
1223 | } |
||
1224 | static void put32bits( byte[] ac, u32 val ) |
||
1225 | { |
||
1226 | sqlite3Put4byte( ac, 0U, val ); |
||
1227 | } |
||
1228 | static void put32bits( byte[] ac, int offset, u32 val ) |
||
1229 | { |
||
1230 | sqlite3Put4byte( ac, offset, val ); |
||
1231 | } |
||
1232 | |||
1233 | /* |
||
1234 | ** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK |
||
1235 | ** on success or an error code is something goes wrong. |
||
1236 | */ |
||
1237 | static int write32bits( sqlite3_file fd, i64 offset, u32 val ) |
||
1238 | { |
||
1239 | byte[] ac = new byte[4]; |
||
1240 | put32bits( ac, val ); |
||
1241 | return sqlite3OsWrite( fd, ac, 4, offset ); |
||
1242 | } |
||
1243 | |||
1244 | /* |
||
1245 | ** Unlock the database file to level eLock, which must be either NO_LOCK |
||
1246 | ** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() |
||
1247 | ** succeeds, set the Pager.eLock variable to match the (attempted) new lock. |
||
1248 | ** |
||
1249 | ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is |
||
1250 | ** called, do not modify it. See the comment above the #define of |
||
1251 | ** UNKNOWN_LOCK for an explanation of this. |
||
1252 | */ |
||
1253 | static int pagerUnlockDb( Pager pPager, int eLock ) |
||
1254 | { |
||
1255 | int rc = SQLITE_OK; |
||
1256 | |||
1257 | Debug.Assert( !pPager.exclusiveMode || pPager.eLock == eLock ); |
||
1258 | Debug.Assert( eLock == NO_LOCK || eLock == SHARED_LOCK ); |
||
1259 | Debug.Assert( eLock != NO_LOCK || pagerUseWal( pPager ) == false ); |
||
1260 | if ( isOpen( pPager.fd ) ) |
||
1261 | { |
||
1262 | Debug.Assert( pPager.eLock >= eLock ); |
||
1263 | rc = sqlite3OsUnlock( pPager.fd, eLock ); |
||
1264 | if ( pPager.eLock != UNKNOWN_LOCK ) |
||
1265 | { |
||
1266 | pPager.eLock = (u8)eLock; |
||
1267 | } |
||
1268 | IOTRACE( "UNLOCK %p %d\n", pPager, eLock ); |
||
1269 | } |
||
1270 | return rc; |
||
1271 | } |
||
1272 | |||
1273 | /* |
||
1274 | ** Lock the database file to level eLock, which must be either SHARED_LOCK, |
||
1275 | ** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the |
||
1276 | ** Pager.eLock variable to the new locking state. |
||
1277 | ** |
||
1278 | ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is |
||
1279 | ** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. |
||
1280 | ** See the comment above the #define of UNKNOWN_LOCK for an explanation |
||
1281 | ** of this. |
||
1282 | */ |
||
1283 | static int pagerLockDb( Pager pPager, int eLock ) |
||
1284 | { |
||
1285 | int rc = SQLITE_OK; |
||
1286 | |||
1287 | Debug.Assert( eLock == SHARED_LOCK || eLock == RESERVED_LOCK || eLock == EXCLUSIVE_LOCK ); |
||
1288 | if ( pPager.eLock < eLock || pPager.eLock == UNKNOWN_LOCK ) |
||
1289 | { |
||
1290 | rc = sqlite3OsLock( pPager.fd, eLock ); |
||
1291 | if ( rc == SQLITE_OK && ( pPager.eLock != UNKNOWN_LOCK || eLock == EXCLUSIVE_LOCK ) ) |
||
1292 | { |
||
1293 | pPager.eLock = (u8)eLock; |
||
1294 | IOTRACE( "LOCK %p %d\n", pPager, eLock ); |
||
1295 | } |
||
1296 | } |
||
1297 | return rc; |
||
1298 | } |
||
1299 | |||
1300 | /* |
||
1301 | ** This function determines whether or not the atomic-write optimization |
||
1302 | ** can be used with this pager. The optimization can be used if: |
||
1303 | ** |
||
1304 | ** (a) the value returned by OsDeviceCharacteristics() indicates that |
||
1305 | ** a database page may be written atomically, and |
||
1306 | ** (b) the value returned by OsSectorSize() is less than or equal |
||
1307 | ** to the page size. |
||
1308 | ** |
||
1309 | ** The optimization is also always enabled for temporary files. It is |
||
1310 | ** an error to call this function if pPager is opened on an in-memory |
||
1311 | ** database. |
||
1312 | ** |
||
1313 | ** If the optimization cannot be used, 0 is returned. If it can be used, |
||
1314 | ** then the value returned is the size of the journal file when it |
||
1315 | ** contains rollback data for exactly one page. |
||
1316 | */ |
||
1317 | #if SQLITE_ENABLE_ATOMIC_WRITE |
||
1318 | static int jrnlBufferSize(Pager *pPager){ |
||
1319 | Debug.Assert( 0==MEMDB ); |
||
1320 | if( !pPager.tempFile ){ |
||
1321 | int dc; /* Device characteristics */ |
||
1322 | int nSector; /* Sector size */ |
||
1323 | int szPage; /* Page size */ |
||
1324 | |||
1325 | Debug.Assert( isOpen(pPager.fd) ); |
||
1326 | dc = sqlite3OsDeviceCharacteristics(pPager.fd); |
||
1327 | nSector = pPager.sectorSize; |
||
1328 | szPage = pPager.pageSize; |
||
1329 | |||
1330 | Debug.Assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); |
||
1331 | Debug.Assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); |
||
1332 | if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ |
||
1333 | return 0; |
||
1334 | } |
||
1335 | } |
||
1336 | |||
1337 | return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); |
||
1338 | } |
||
1339 | #endif |
||
1340 | |||
1341 | /* |
||
1342 | ** If SQLITE_CHECK_PAGES is defined then we do some sanity checking |
||
1343 | ** on the cache using a hash function. This is used for testing |
||
1344 | ** and debugging only. |
||
1345 | */ |
||
1346 | #if SQLITE_CHECK_PAGES |
||
1347 | /* |
||
1348 | ** Return a 32-bit hash of the page data for pPage. |
||
1349 | */ |
||
1350 | static u32 pager_datahash(int nByte, unsigned char pData){ |
||
1351 | u32 hash = 0; |
||
1352 | int i; |
||
1353 | for(i=0; i<nByte; i++){ |
||
1354 | hash = (hash*1039) + pData[i]; |
||
1355 | } |
||
1356 | return hash; |
||
1357 | } |
||
1358 | static void pager_pagehash(PgHdr pPage){ |
||
1359 | return pager_datahash(pPage.pPager.pageSize, (unsigned char *)pPage.pData); |
||
1360 | } |
||
1361 | static u32 pager_set_pagehash(PgHdr pPage){ |
||
1362 | pPage.pageHash = pager_pagehash(pPage); |
||
1363 | } |
||
1364 | |||
1365 | /* |
||
1366 | ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES |
||
1367 | ** is defined, and NDEBUG is not defined, an Debug.Assert() statement checks |
||
1368 | ** that the page is either dirty or still matches the calculated page-hash. |
||
1369 | */ |
||
1370 | //#define CHECK_PAGE(x) checkPage(x) |
||
1371 | static void checkPage(PgHdr pPg){ |
||
1372 | Pager pPager = pPg.pPager; |
||
1373 | assert( pPager->eState!=PAGER_ERROR ); |
||
1374 | assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); |
||
1375 | } |
||
1376 | |||
1377 | #else |
||
1378 | //#define pager_datahash(X,Y) 0 |
||
1379 | static int pager_datahash( int X, byte[] Y ) |
||
1380 | { |
||
1381 | return 0; |
||
1382 | } |
||
1383 | |||
1384 | //#define pager_pagehash(X) 0 |
||
1385 | static int pager_pagehash( PgHdr X ) |
||
1386 | { |
||
1387 | return 0; |
||
1388 | } |
||
1389 | |||
1390 | //#define pager_set_pagehash(X) |
||
1391 | static void pager_set_pagehash( PgHdr X ) |
||
1392 | { |
||
1393 | } |
||
1394 | |||
1395 | //#define CHECK_PAGE(x) |
||
1396 | #endif //* SQLITE_CHECK_PAGES */ |
||
1397 | |||
1398 | |||
1399 | /* |
||
1400 | ** When this is called the journal file for pager pPager must be open. |
||
1401 | ** This function attempts to read a master journal file name from the |
||
1402 | ** end of the file and, if successful, copies it into memory supplied |
||
1403 | ** by the caller. See comments above writeMasterJournal() for the format |
||
1404 | ** used to store a master journal file name at the end of a journal file. |
||
1405 | ** |
||
1406 | ** zMaster must point to a buffer of at least nMaster bytes allocated by |
||
1407 | ** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is |
||
1408 | ** enough space to write the master journal name). If the master journal |
||
1409 | ** name in the journal is longer than nMaster bytes (including a |
||
1410 | ** nul-terminator), then this is handled as if no master journal name |
||
1411 | ** were present in the journal. |
||
1412 | ** |
||
1413 | ** If a master journal file name is present at the end of the journal |
||
1414 | ** file, then it is copied into the buffer pointed to by zMaster. A |
||
1415 | ** nul-terminator byte is appended to the buffer following the master |
||
1416 | ** journal file name. |
||
1417 | ** |
||
1418 | ** If it is determined that no master journal file name is present |
||
1419 | ** zMaster[0] is set to 0 and SQLITE_OK returned. |
||
1420 | ** |
||
1421 | ** If an error occurs while reading from the journal file, an SQLite |
||
1422 | ** error code is returned. |
||
1423 | */ |
||
1424 | static int readMasterJournal( sqlite3_file pJrnl, byte[] zMaster, u32 nMaster ) |
||
1425 | { |
||
1426 | int rc; /* Return code */ |
||
1427 | int len = 0; /* Length in bytes of master journal name */ |
||
1428 | i64 szJ = 0; /* Total size in bytes of journal file pJrnl */ |
||
1429 | u32 cksum = 0; /* MJ checksum value read from journal */ |
||
1430 | int u; /* Unsigned loop counter */ |
||
1431 | byte[] aMagic = new byte[8]; /* A buffer to hold the magic header */ |
||
1432 | |||
1433 | zMaster[0] = 0; |
||
1434 | |||
1435 | if ( SQLITE_OK != ( rc = sqlite3OsFileSize( pJrnl, ref szJ ) ) |
||
1436 | || szJ < 16 |
||
1437 | || SQLITE_OK != ( rc = read32bits( pJrnl, (int)( szJ - 16 ), ref len ) ) |
||
1438 | || len >= nMaster |
||
1439 | || SQLITE_OK != ( rc = read32bits( pJrnl, szJ - 12, ref cksum ) ) |
||
1440 | || SQLITE_OK != ( rc = sqlite3OsRead( pJrnl, aMagic, 8, szJ - 8 ) ) |
||
1441 | || memcmp( aMagic, aJournalMagic, 8 ) != 0 |
||
1442 | || SQLITE_OK != ( rc = sqlite3OsRead( pJrnl, zMaster, len, (long)( szJ - 16 - len ) ) ) |
||
1443 | ) |
||
1444 | { |
||
1445 | return rc; |
||
1446 | } |
||
1447 | |||
1448 | /* See if the checksum matches the master journal name */ |
||
1449 | for ( u = 0; u < len; u++ ) |
||
1450 | { |
||
1451 | cksum -= zMaster[u]; |
||
1452 | } |
||
1453 | if ( cksum != 0 ) |
||
1454 | { |
||
1455 | /* If the checksum doesn't add up, then one or more of the disk sectors |
||
1456 | ** containing the master journal filename is corrupted. This means |
||
1457 | ** definitely roll back, so just return SQLITE_OK and report a (nul) |
||
1458 | ** master-journal filename. |
||
1459 | */ |
||
1460 | len = 0; |
||
1461 | } |
||
1462 | if ( len == 0 ) |
||
1463 | zMaster[0] = 0; |
||
1464 | |||
1465 | return SQLITE_OK; |
||
1466 | } |
||
1467 | |||
1468 | /* |
||
1469 | ** Return the offset of the sector boundary at or immediately |
||
1470 | ** following the value in pPager.journalOff, assuming a sector |
||
1471 | ** size of pPager.sectorSize bytes. |
||
1472 | ** |
||
1473 | ** i.e for a sector size of 512: |
||
1474 | ** |
||
1475 | ** Pager.journalOff Return value |
||
1476 | ** --------------------------------------- |
||
1477 | ** 0 0 |
||
1478 | ** 512 512 |
||
1479 | ** 100 512 |
||
1480 | ** 2000 2048 |
||
1481 | ** |
||
1482 | */ |
||
1483 | static i64 journalHdrOffset( Pager pPager ) |
||
1484 | { |
||
1485 | i64 offset = 0; |
||
1486 | i64 c = pPager.journalOff; |
||
1487 | if ( c != 0 ) |
||
1488 | { |
||
1489 | offset = (int)( ( ( c - 1 ) / pPager.sectorSize + 1 ) * pPager.sectorSize );//offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); |
||
1490 | } |
||
1491 | Debug.Assert( offset % pPager.sectorSize == 0 ); //Debug.Assert(offset % JOURNAL_HDR_SZ(pPager) == 0); |
||
1492 | Debug.Assert( offset >= c ); |
||
1493 | Debug.Assert( ( offset - c ) < pPager.sectorSize );//Debug.Assert( (offset-c)<JOURNAL_HDR_SZ(pPager) ); |
||
1494 | return offset; |
||
1495 | } |
||
1496 | static void seekJournalHdr( Pager pPager ) |
||
1497 | { |
||
1498 | pPager.journalOff = journalHdrOffset( pPager ); |
||
1499 | } |
||
1500 | |||
1501 | /* |
||
1502 | ** The journal file must be open when this function is called. |
||
1503 | ** |
||
1504 | ** This function is a no-op if the journal file has not been written to |
||
1505 | ** within the current transaction (i.e. if Pager.journalOff==0). |
||
1506 | ** |
||
1507 | ** If doTruncate is non-zero or the Pager.journalSizeLimit variable is |
||
1508 | ** set to 0, then truncate the journal file to zero bytes in size. Otherwise, |
||
1509 | ** zero the 28-byte header at the start of the journal file. In either case, |
||
1510 | ** if the pager is not in no-sync mode, sync the journal file immediately |
||
1511 | ** after writing or truncating it. |
||
1512 | ** |
||
1513 | ** If Pager.journalSizeLimit is set to a positive, non-zero value, and |
||
1514 | ** following the truncation or zeroing described above the size of the |
||
1515 | ** journal file in bytes is larger than this value, then truncate the |
||
1516 | ** journal file to Pager.journalSizeLimit bytes. The journal file does |
||
1517 | ** not need to be synced following this operation. |
||
1518 | ** |
||
1519 | ** If an IO error occurs, abandon processing and return the IO error code. |
||
1520 | ** Otherwise, return SQLITE_OK. |
||
1521 | */ |
||
1522 | static int zeroJournalHdr( Pager pPager, int doTruncate ) |
||
1523 | { |
||
1524 | int rc = SQLITE_OK; /* Return code */ |
||
1525 | Debug.Assert( isOpen( pPager.jfd ) ); |
||
1526 | |||
1527 | if ( pPager.journalOff != 0 ) |
||
1528 | { |
||
1529 | i64 iLimit = pPager.journalSizeLimit; /* Local cache of jsl */ |
||
1530 | IOTRACE( "JZEROHDR %p\n", pPager ); |
||
1531 | if ( doTruncate != 0 || iLimit == 0 ) |
||
1532 | { |
||
1533 | rc = sqlite3OsTruncate( pPager.jfd, 0 ); |
||
1534 | } |
||
1535 | else |
||
1536 | { |
||
1537 | byte[] zeroHdr = new byte[28];// = {0}; |
||
1538 | rc = sqlite3OsWrite( pPager.jfd, zeroHdr, zeroHdr.Length, 0 ); |
||
1539 | } |
||
1540 | if ( rc == SQLITE_OK && !pPager.noSync ) |
||
1541 | { |
||
1542 | rc = sqlite3OsSync( pPager.jfd, SQLITE_SYNC_DATAONLY | pPager.syncFlags ); |
||
1543 | } |
||
1544 | |||
1545 | /* At this point the transaction is committed but the write lock |
||
1546 | ** is still held on the file. If there is a size limit configured for |
||
1547 | ** the persistent journal and the journal file currently consumes more |
||
1548 | ** space than that limit allows for, truncate it now. There is no need |
||
1549 | ** to sync the file following this operation. |
||
1550 | */ |
||
1551 | if ( rc == SQLITE_OK && iLimit > 0 ) |
||
1552 | { |
||
1553 | i64 sz = 0; |
||
1554 | rc = sqlite3OsFileSize( pPager.jfd, ref sz ); |
||
1555 | if ( rc == SQLITE_OK && sz > iLimit ) |
||
1556 | { |
||
1557 | rc = sqlite3OsTruncate( pPager.jfd, iLimit ); |
||
1558 | } |
||
1559 | } |
||
1560 | } |
||
1561 | return rc; |
||
1562 | } |
||
1563 | |||
1564 | /* |
||
1565 | ** The journal file must be open when this routine is called. A journal |
||
1566 | ** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the |
||
1567 | ** current location. |
||
1568 | ** |
||
1569 | ** The format for the journal header is as follows: |
||
1570 | ** - 8 bytes: Magic identifying journal format. |
||
1571 | ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. |
||
1572 | ** - 4 bytes: Random number used for page hash. |
||
1573 | ** - 4 bytes: Initial database page count. |
||
1574 | ** - 4 bytes: Sector size used by the process that wrote this journal. |
||
1575 | ** - 4 bytes: Database page size. |
||
1576 | ** |
||
1577 | ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. |
||
1578 | */ |
||
1579 | static int writeJournalHdr( Pager pPager ) |
||
1580 | { |
||
1581 | |||
1582 | int rc = SQLITE_OK; /* Return code */ |
||
1583 | byte[] zHeader = pPager.pTmpSpace; /* Temporary space used to build header */ |
||
1584 | u32 nHeader = (u32)pPager.pageSize; /* Size of buffer pointed to by zHeader */ |
||
1585 | u32 nWrite; /* Bytes of header sector written */ |
||
1586 | int ii; /* Loop counter */ |
||
1587 | |||
1588 | Debug.Assert( isOpen( pPager.jfd ) ); /* Journal file must be open. */ |
||
1589 | |||
1590 | if ( nHeader > JOURNAL_HDR_SZ( pPager ) ) |
||
1591 | { |
||
1592 | nHeader = JOURNAL_HDR_SZ( pPager ); |
||
1593 | } |
||
1594 | /* If there are active savepoints and any of them were created |
||
1595 | ** since the most recent journal header was written, update the |
||
1596 | ** PagerSavepoint.iHdrOffset fields now. |
||
1597 | */ |
||
1598 | for ( ii = 0; ii < pPager.nSavepoint; ii++ ) |
||
1599 | { |
||
1600 | if ( pPager.aSavepoint[ii].iHdrOffset == 0 ) |
||
1601 | { |
||
1602 | pPager.aSavepoint[ii].iHdrOffset = pPager.journalOff; |
||
1603 | } |
||
1604 | } |
||
1605 | pPager.journalHdr = pPager.journalOff = journalHdrOffset( pPager ); |
||
1606 | |||
1607 | /* |
||
1608 | ** Write the nRec Field - the number of page records that follow this |
||
1609 | ** journal header. Normally, zero is written to this value at this time. |
||
1610 | ** After the records are added to the journal (and the journal synced, |
||
1611 | ** if in full-sync mode), the zero is overwritten with the true number |
||
1612 | ** of records (see syncJournal()). |
||
1613 | ** |
||
1614 | ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When |
||
1615 | ** reading the journal this value tells SQLite to assume that the |
||
1616 | ** rest of the journal file contains valid page records. This assumption |
||
1617 | ** is dangerous, as if a failure occurred whilst writing to the journal |
||
1618 | ** file it may contain some garbage data. There are two scenarios |
||
1619 | ** where this risk can be ignored: |
||
1620 | ** |
||
1621 | ** * When the pager is in no-sync mode. Corruption can follow a |
||
1622 | ** power failure in this case anyway. |
||
1623 | ** |
||
1624 | ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees |
||
1625 | ** that garbage data is never appended to the journal file. |
||
1626 | */ |
||
1627 | Debug.Assert( isOpen( pPager.fd ) || pPager.noSync ); |
||
1628 | if ( pPager.noSync || ( pPager.journalMode == PAGER_JOURNALMODE_MEMORY ) |
||
1629 | || ( sqlite3OsDeviceCharacteristics( pPager.fd ) & SQLITE_IOCAP_SAFE_APPEND ) != 0 |
||
1630 | ) |
||
1631 | { |
||
1632 | aJournalMagic.CopyTo( zHeader, 0 );// memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); |
||
1633 | put32bits( zHeader, aJournalMagic.Length, 0xffffffff ); |
||
1634 | } |
||
1635 | else |
||
1636 | { |
||
1637 | Array.Clear( zHeader, 0, aJournalMagic.Length + 4 );//memset(zHeader, 0, sizeof(aJournalMagic)+4); |
||
1638 | } |
||
1639 | |||
1640 | /* The random check-hash initialiser */ |
||
1641 | i64 i64Temp = 0; |
||
1642 | sqlite3_randomness( sizeof( i64 ), ref i64Temp ); |
||
1643 | pPager.cksumInit = (u32)i64Temp; |
||
1644 | put32bits( zHeader, aJournalMagic.Length + 4, pPager.cksumInit ); |
||
1645 | /* The initial database size */ |
||
1646 | put32bits( zHeader, aJournalMagic.Length + 8, pPager.dbOrigSize ); |
||
1647 | /* The assumed sector size for this process */ |
||
1648 | put32bits( zHeader, aJournalMagic.Length + 12, pPager.sectorSize ); |
||
1649 | /* The page size */ |
||
1650 | put32bits( zHeader, aJournalMagic.Length + 16, (u32)pPager.pageSize ); |
||
1651 | |||
1652 | /* Initializing the tail of the buffer is not necessary. Everything |
||
1653 | ** works find if the following memset() is omitted. But initializing |
||
1654 | ** the memory prevents valgrind from complaining, so we are willing to |
||
1655 | ** take the performance hit. |
||
1656 | */ |
||
1657 | // memset(&zHeader[sizeof(aJournalMagic)+20], 0, |
||
1658 | // nHeader-(sizeof(aJournalMagic)+20)); |
||
1659 | Array.Clear( zHeader, aJournalMagic.Length + 20, (int)nHeader - ( aJournalMagic.Length + 20 ) ); |
||
1660 | |||
1661 | /* In theory, it is only necessary to write the 28 bytes that the |
||
1662 | ** journal header consumes to the journal file here. Then increment the |
||
1663 | ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next |
||
1664 | ** record is written to the following sector (leaving a gap in the file |
||
1665 | ** that will be implicitly filled in by the OS). |
||
1666 | ** |
||
1667 | ** However it has been discovered that on some systems this pattern can |
||
1668 | ** be significantly slower than contiguously writing data to the file, |
||
1669 | ** even if that means explicitly writing data to the block of |
||
1670 | ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what |
||
1671 | ** is done. |
||
1672 | ** |
||
1673 | ** The loop is required here in case the sector-size is larger than the |
||
1674 | ** database page size. Since the zHeader buffer is only Pager.pageSize |
||
1675 | ** bytes in size, more than one call to sqlite3OsWrite() may be required |
||
1676 | ** to populate the entire journal header sector. |
||
1677 | */ |
||
1678 | for ( nWrite = 0; rc == SQLITE_OK && nWrite < JOURNAL_HDR_SZ( pPager ); nWrite += nHeader ) |
||
1679 | { |
||
1680 | IOTRACE( "JHDR %p %lld %d\n", pPager, pPager.journalHdr, nHeader ); |
||
1681 | rc = sqlite3OsWrite( pPager.jfd, zHeader, (int)nHeader, pPager.journalOff ); |
||
1682 | Debug.Assert( pPager.journalHdr <= pPager.journalOff ); |
||
1683 | pPager.journalOff += (int)nHeader; |
||
1684 | } |
||
1685 | return rc; |
||
1686 | } |
||
1687 | |||
1688 | /* |
||
1689 | ** The journal file must be open when this is called. A journal header file |
||
1690 | ** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal |
||
1691 | ** file. The current location in the journal file is given by |
||
1692 | ** pPager.journalOff. See comments above function writeJournalHdr() for |
||
1693 | ** a description of the journal header format. |
||
1694 | ** |
||
1695 | ** If the header is read successfully, *pNRec is set to the number of |
||
1696 | ** page records following this header and *pDbSize is set to the size of the |
||
1697 | ** database before the transaction began, in pages. Also, pPager.cksumInit |
||
1698 | ** is set to the value read from the journal header. SQLITE_OK is returned |
||
1699 | ** in this case. |
||
1700 | ** |
||
1701 | ** If the journal header file appears to be corrupted, SQLITE_DONE is |
||
1702 | ** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes |
||
1703 | ** cannot be read from the journal file an error code is returned. |
||
1704 | */ |
||
1705 | static int readJournalHdr( |
||
1706 | Pager pPager, /* Pager object */ |
||
1707 | int isHot, |
||
1708 | i64 journalSize, /* Size of the open journal file in bytes */ |
||
1709 | out u32 pNRec, /* OUT: Value read from the nRec field */ |
||
1710 | out u32 pDbSize /* OUT: Value of original database size field */ |
||
1711 | ) |
||
1712 | { |
||
1713 | int rc; /* Return code */ |
||
1714 | byte[] aMagic = new byte[8]; /* A buffer to hold the magic header */ |
||
1715 | i64 iHdrOff; /* Offset of journal header being read */ |
||
1716 | |||
1717 | Debug.Assert( isOpen( pPager.jfd ) ); /* Journal file must be open. */ |
||
1718 | |||
1719 | pNRec = 0; |
||
1720 | pDbSize = 0; |
||
1721 | |||
1722 | /* Advance Pager.journalOff to the start of the next sector. If the |
||
1723 | ** journal file is too small for there to be a header stored at this |
||
1724 | ** point, return SQLITE_DONE. |
||
1725 | */ |
||
1726 | pPager.journalOff = journalHdrOffset( pPager ); |
||
1727 | if ( pPager.journalOff + JOURNAL_HDR_SZ( pPager ) > journalSize ) |
||
1728 | { |
||
1729 | return SQLITE_DONE; |
||
1730 | } |
||
1731 | iHdrOff = pPager.journalOff; |
||
1732 | |||
1733 | /* Read in the first 8 bytes of the journal header. If they do not match |
||
1734 | ** the magic string found at the start of each journal header, return |
||
1735 | ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, |
||
1736 | ** proceed. |
||
1737 | */ |
||
1738 | if ( isHot != 0 || iHdrOff != pPager.journalHdr ) |
||
1739 | { |
||
1740 | rc = sqlite3OsRead( pPager.jfd, aMagic, aMagic.Length, iHdrOff ); |
||
1741 | if ( rc != 0 ) |
||
1742 | { |
||
1743 | return rc; |
||
1744 | } |
||
1745 | if ( memcmp( aMagic, aJournalMagic, aMagic.Length ) != 0 ) |
||
1746 | { |
||
1747 | return SQLITE_DONE; |
||
1748 | } |
||
1749 | } |
||
1750 | /* Read the first three 32-bit fields of the journal header: The nRec |
||
1751 | ** field, the checksum-initializer and the database size at the start |
||
1752 | ** of the transaction. Return an error code if anything goes wrong. |
||
1753 | */ |
||
1754 | if ( SQLITE_OK != ( rc = read32bits( pPager.jfd, iHdrOff + 8, ref pNRec ) ) |
||
1755 | || SQLITE_OK != ( rc = read32bits( pPager.jfd, iHdrOff + 12, ref pPager.cksumInit ) ) |
||
1756 | || SQLITE_OK != ( rc = read32bits( pPager.jfd, iHdrOff + 16, ref pDbSize ) ) |
||
1757 | ) |
||
1758 | { |
||
1759 | return rc; |
||
1760 | } |
||
1761 | |||
1762 | if ( pPager.journalOff == 0 ) |
||
1763 | { |
||
1764 | u32 iPageSize = 0; /* Page-size field of journal header */ |
||
1765 | u32 iSectorSize = 0; /* Sector-size field of journal header */ |
||
1766 | |||
1767 | /* Read the page-size and sector-size journal header fields. */ |
||
1768 | if ( SQLITE_OK != ( rc = read32bits( pPager.jfd, iHdrOff + 20, ref iSectorSize ) ) |
||
1769 | || SQLITE_OK != ( rc = read32bits( pPager.jfd, iHdrOff + 24, ref iPageSize ) ) |
||
1770 | ) |
||
1771 | { |
||
1772 | return rc; |
||
1773 | } |
||
1774 | |||
1775 | /* Versions of SQLite prior to 3.5.8 set the page-size field of the |
||
1776 | ** journal header to zero. In this case, assume that the Pager.pageSize |
||
1777 | ** variable is already set to the correct page size. |
||
1778 | */ |
||
1779 | if ( iPageSize == 0 ) |
||
1780 | { |
||
1781 | iPageSize = (u32)pPager.pageSize; |
||
1782 | } |
||
1783 | |||
1784 | /* Check that the values read from the page-size and sector-size fields |
||
1785 | ** are within range. To be 'in range', both values need to be a power |
||
1786 | ** of two greater than or equal to 512 or 32, and not greater than their |
||
1787 | ** respective compile time maximum limits. |
||
1788 | */ |
||
1789 | if ( iPageSize < 512 || iSectorSize < 32 |
||
1790 | || iPageSize > SQLITE_MAX_PAGE_SIZE || iSectorSize > MAX_SECTOR_SIZE |
||
1791 | || ( ( iPageSize - 1 ) & iPageSize ) != 0 || ( ( iSectorSize - 1 ) & iSectorSize ) != 0 |
||
1792 | ) |
||
1793 | { |
||
1794 | /* If the either the page-size or sector-size in the journal-header is |
||
1795 | ** invalid, then the process that wrote the journal-header must have |
||
1796 | ** crashed before the header was synced. In this case stop reading |
||
1797 | ** the journal file here. |
||
1798 | */ |
||
1799 | return SQLITE_DONE; |
||
1800 | } |
||
1801 | |||
1802 | /* Update the page-size to match the value read from the journal. |
||
1803 | ** Use a testcase() macro to make sure that malloc failure within |
||
1804 | ** PagerSetPagesize() is tested. |
||
1805 | */ |
||
1806 | rc = sqlite3PagerSetPagesize( pPager, ref iPageSize, -1 ); |
||
1807 | testcase( rc != SQLITE_OK ); |
||
1808 | |||
1809 | /* Update the assumed sector-size to match the value used by |
||
1810 | ** the process that created this journal. If this journal was |
||
1811 | ** created by a process other than this one, then this routine |
||
1812 | ** is being called from within pager_playback(). The local value |
||
1813 | ** of Pager.sectorSize is restored at the end of that routine. |
||
1814 | */ |
||
1815 | pPager.sectorSize = iSectorSize; |
||
1816 | } |
||
1817 | |||
1818 | pPager.journalOff += (int)JOURNAL_HDR_SZ( pPager ); |
||
1819 | return rc; |
||
1820 | } |
||
1821 | |||
1822 | /* |
||
1823 | ** Write the supplied master journal name into the journal file for pager |
||
1824 | ** pPager at the current location. The master journal name must be the last |
||
1825 | ** thing written to a journal file. If the pager is in full-sync mode, the |
||
1826 | ** journal file descriptor is advanced to the next sector boundary before |
||
1827 | ** anything is written. The format is: |
||
1828 | ** |
||
1829 | ** + 4 bytes: PAGER_MJ_PGNO. |
||
1830 | ** + N bytes: Master journal filename in utf-8. |
||
1831 | ** + 4 bytes: N (length of master journal name in bytes, no nul-terminator). |
||
1832 | ** + 4 bytes: Master journal name checksum. |
||
1833 | ** + 8 bytes: aJournalMagic[]. |
||
1834 | ** |
||
1835 | ** The master journal page checksum is the sum of the bytes in the master |
||
1836 | ** journal name, where each byte is interpreted as a signed 8-bit integer. |
||
1837 | ** |
||
1838 | ** If zMaster is a NULL pointer (occurs for a single database transaction), |
||
1839 | ** this call is a no-op. |
||
1840 | */ |
||
1841 | static int writeMasterJournal( Pager pPager, string zMaster ) |
||
1842 | { |
||
1843 | int rc; /* Return code */ |
||
1844 | int nMaster; /* Length of string zMaster */ |
||
1845 | i64 iHdrOff; /* Offset of header in journal file */ |
||
1846 | i64 jrnlSize = 0; /* Size of journal file on disk */ |
||
1847 | u32 cksum = 0; /* Checksum of string zMaster */ |
||
1848 | |||
1849 | Debug.Assert( pPager.setMaster == 0 ); |
||
1850 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
1851 | if ( null == zMaster |
||
1852 | || pPager.journalMode == PAGER_JOURNALMODE_MEMORY |
||
1853 | || pPager.journalMode == PAGER_JOURNALMODE_OFF |
||
1854 | ) |
||
1855 | { |
||
1856 | return SQLITE_OK; |
||
1857 | } |
||
1858 | |||
1859 | pPager.setMaster = 1; |
||
1860 | Debug.Assert( isOpen( pPager.jfd ) ); |
||
1861 | Debug.Assert( pPager.journalHdr <= pPager.journalOff ); |
||
1862 | |||
1863 | /* Calculate the length in bytes and the checksum of zMaster */ |
||
1864 | for ( nMaster = 0; nMaster < zMaster.Length && zMaster[nMaster] != 0; nMaster++ ) |
||
1865 | { |
||
1866 | cksum += zMaster[nMaster]; |
||
1867 | } |
||
1868 | |||
1869 | /* If in full-sync mode, advance to the next disk sector before writing |
||
1870 | ** the master journal name. This is in case the previous page written to |
||
1871 | ** the journal has already been synced. |
||
1872 | */ |
||
1873 | if ( pPager.fullSync ) |
||
1874 | { |
||
1875 | pPager.journalOff = journalHdrOffset( pPager ); |
||
1876 | } |
||
1877 | iHdrOff = pPager.journalOff; |
||
1878 | /* Write the master journal data to the end of the journal file. If |
||
1879 | ** an error occurs, return the error code to the caller. |
||
1880 | */ |
||
1881 | if ( ( 0 != ( rc = write32bits( pPager.jfd, iHdrOff, (u32)PAGER_MJ_PGNO( pPager ) ) ) ) |
||
1882 | || ( 0 != ( rc = sqlite3OsWrite( pPager.jfd, Encoding.UTF8.GetBytes( zMaster ), nMaster, iHdrOff + 4 ) ) ) |
||
1883 | || ( 0 != ( rc = write32bits( pPager.jfd, iHdrOff + 4 + nMaster, (u32)nMaster ) ) ) |
||
1884 | || ( 0 != ( rc = write32bits( pPager.jfd, iHdrOff + 4 + nMaster + 4, cksum ) ) ) |
||
1885 | || ( 0 != ( rc = sqlite3OsWrite( pPager.jfd, aJournalMagic, 8, iHdrOff + 4 + nMaster + 8 ) ) ) |
||
1886 | ) |
||
1887 | { |
||
1888 | return rc; |
||
1889 | } |
||
1890 | pPager.journalOff += ( nMaster + 20 ); |
||
1891 | |||
1892 | /* If the pager is in peristent-journal mode, then the physical |
||
1893 | ** journal-file may extend past the end of the master-journal name |
||
1894 | ** and 8 bytes of magic data just written to the file. This is |
||
1895 | ** dangerous because the code to rollback a hot-journal file |
||
1896 | ** will not be able to find the master-journal name to determine |
||
1897 | ** whether or not the journal is hot. |
||
1898 | ** |
||
1899 | ** Easiest thing to do in this scenario is to truncate the journal |
||
1900 | ** file to the required size. |
||
1901 | */ |
||
1902 | if ( SQLITE_OK == ( rc = sqlite3OsFileSize( pPager.jfd, ref jrnlSize ) ) |
||
1903 | && jrnlSize > pPager.journalOff |
||
1904 | ) |
||
1905 | { |
||
1906 | rc = sqlite3OsTruncate( pPager.jfd, pPager.journalOff ); |
||
1907 | } |
||
1908 | |||
1909 | return rc; |
||
1910 | } |
||
1911 | |||
1912 | /* |
||
1913 | ** Find a page in the hash table given its page number. Return |
||
1914 | ** a pointer to the page or NULL if the requested page is not |
||
1915 | ** already in memory. |
||
1916 | */ |
||
1917 | static PgHdr pager_lookup( Pager pPager, u32 pgno ) |
||
1918 | { |
||
1919 | PgHdr p = null; /* Return value */ |
||
1920 | /* It is not possible for a call to PcacheFetch() with createFlag==0 to |
||
1921 | ** fail, since no attempt to allocate dynamic memory will be made. |
||
1922 | */ |
||
1923 | sqlite3PcacheFetch( pPager.pPCache, pgno, 0, ref p ); |
||
1924 | return p; |
||
1925 | } |
||
1926 | |||
1927 | /* |
||
1928 | ** Discard the entire contents of the in-memory page-cache. |
||
1929 | */ |
||
1930 | static void pager_reset( Pager pPager ) |
||
1931 | { |
||
1932 | sqlite3BackupRestart( pPager.pBackup ); |
||
1933 | sqlite3PcacheClear( pPager.pPCache ); |
||
1934 | } |
||
1935 | |||
1936 | /* |
||
1937 | ** Free all structures in the Pager.aSavepoint[] array and set both |
||
1938 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
||
1939 | ** if it is open and the pager is not in exclusive mode. |
||
1940 | */ |
||
1941 | static void releaseAllSavepoints( Pager pPager ) |
||
1942 | { |
||
1943 | int ii; /* Iterator for looping through Pager.aSavepoint */ |
||
1944 | for ( ii = 0; ii < pPager.nSavepoint; ii++ ) |
||
1945 | { |
||
1946 | sqlite3BitvecDestroy( ref pPager.aSavepoint[ii].pInSavepoint ); |
||
1947 | } |
||
1948 | if ( !pPager.exclusiveMode || sqlite3IsMemJournal( pPager.sjfd ) ) |
||
1949 | { |
||
1950 | sqlite3OsClose( pPager.sjfd ); |
||
1951 | } |
||
1952 | //sqlite3_free( ref pPager.aSavepoint ); |
||
1953 | pPager.aSavepoint = null; |
||
1954 | pPager.nSavepoint = 0; |
||
1955 | pPager.nSubRec = 0; |
||
1956 | } |
||
1957 | |||
1958 | /* |
||
1959 | ** Set the bit number pgno in the PagerSavepoint.pInSavepoint |
||
1960 | ** bitvecs of all open savepoints. Return SQLITE_OK if successful |
||
1961 | ** or SQLITE_NOMEM if a malloc failure occurs. |
||
1962 | */ |
||
1963 | static int addToSavepointBitvecs( Pager pPager, u32 pgno ) |
||
1964 | { |
||
1965 | int ii; /* Loop counter */ |
||
1966 | int rc = SQLITE_OK; /* Result code */ |
||
1967 | |||
1968 | for ( ii = 0; ii < pPager.nSavepoint; ii++ ) |
||
1969 | { |
||
1970 | PagerSavepoint p = pPager.aSavepoint[ii]; |
||
1971 | if ( pgno <= p.nOrig ) |
||
1972 | { |
||
1973 | rc |= sqlite3BitvecSet( p.pInSavepoint, pgno ); |
||
1974 | testcase( rc == SQLITE_NOMEM ); |
||
1975 | Debug.Assert( rc == SQLITE_OK || rc == SQLITE_NOMEM ); |
||
1976 | } |
||
1977 | } |
||
1978 | return rc; |
||
1979 | } |
||
1980 | |||
1981 | /* |
||
1982 | ** This function is a no-op if the pager is in exclusive mode and not |
||
1983 | ** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN |
||
1984 | ** state. |
||
1985 | ** |
||
1986 | ** If the pager is not in exclusive-access mode, the database file is |
||
1987 | ** completely unlocked. If the file is unlocked and the file-system does |
||
1988 | ** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is |
||
1989 | ** closed (if it is open). |
||
1990 | ** |
||
1991 | ** If the pager is in ERROR state when this function is called, the |
||
1992 | ** contents of the pager cache are discarded before switching back to |
||
1993 | ** the OPEN state. Regardless of whether the pager is in exclusive-mode |
||
1994 | ** or not, any journal file left in the file-system will be treated |
||
1995 | ** as a hot-journal and rolled back the next time a read-transaction |
||
1996 | ** is opened (by this or by any other connection). |
||
1997 | */ |
||
1998 | static void pager_unlock( Pager pPager ) |
||
1999 | { |
||
2000 | |||
2001 | Debug.Assert( pPager.eState == PAGER_READER |
||
2002 | || pPager.eState == PAGER_OPEN |
||
2003 | || pPager.eState == PAGER_ERROR |
||
2004 | ); |
||
2005 | |||
2006 | sqlite3BitvecDestroy( ref pPager.pInJournal ); |
||
2007 | pPager.pInJournal = null; |
||
2008 | releaseAllSavepoints( pPager ); |
||
2009 | |||
2010 | if ( pagerUseWal( pPager ) ) |
||
2011 | { |
||
2012 | Debug.Assert( !isOpen( pPager.jfd ) ); |
||
2013 | sqlite3WalEndReadTransaction( pPager.pWal ); |
||
2014 | pPager.eState = PAGER_OPEN; |
||
2015 | } |
||
2016 | else if ( !pPager.exclusiveMode ) |
||
2017 | { |
||
2018 | int rc; /* Error code returned by pagerUnlockDb() */ |
||
2019 | int iDc = isOpen( pPager.fd ) ? sqlite3OsDeviceCharacteristics( pPager.fd ) : 0; |
||
2020 | |||
2021 | /* If the operating system support deletion of open files, then |
||
2022 | ** close the journal file when dropping the database lock. Otherwise |
||
2023 | ** another connection with journal_mode=delete might delete the file |
||
2024 | ** out from under us. |
||
2025 | */ |
||
2026 | Debug.Assert( ( PAGER_JOURNALMODE_MEMORY & 5 ) != 1 ); |
||
2027 | Debug.Assert( ( PAGER_JOURNALMODE_OFF & 5 ) != 1 ); |
||
2028 | Debug.Assert( ( PAGER_JOURNALMODE_WAL & 5 ) != 1 ); |
||
2029 | Debug.Assert( ( PAGER_JOURNALMODE_DELETE & 5 ) != 1 ); |
||
2030 | Debug.Assert( ( PAGER_JOURNALMODE_TRUNCATE & 5 ) == 1 ); |
||
2031 | Debug.Assert( ( PAGER_JOURNALMODE_PERSIST & 5 ) == 1 ); |
||
2032 | if ( 0 == ( iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ) |
||
2033 | || 1 != ( pPager.journalMode & 5 ) |
||
2034 | ) |
||
2035 | { |
||
2036 | sqlite3OsClose( pPager.jfd ); |
||
2037 | } |
||
2038 | |||
2039 | |||
2040 | /* If the pager is in the ERROR state and the call to unlock the database |
||
2041 | ** file fails, set the current lock to UNKNOWN_LOCK. See the comment |
||
2042 | ** above the #define for UNKNOWN_LOCK for an explanation of why this |
||
2043 | ** is necessary. |
||
2044 | */ |
||
2045 | rc = pagerUnlockDb( pPager, NO_LOCK ); |
||
2046 | if ( rc != SQLITE_OK && pPager.eState == PAGER_ERROR ) |
||
2047 | { |
||
2048 | pPager.eLock = UNKNOWN_LOCK; |
||
2049 | } |
||
2050 | |||
2051 | /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here |
||
2052 | ** without clearing the error code. This is intentional - the error |
||
2053 | ** code is cleared and the cache reset in the block below. |
||
2054 | */ |
||
2055 | Debug.Assert( pPager.errCode != 0 || pPager.eState != PAGER_ERROR ); |
||
2056 | pPager.changeCountDone = false; |
||
2057 | pPager.eState = PAGER_OPEN; |
||
2058 | } |
||
2059 | |||
2060 | /* If Pager.errCode is set, the contents of the pager cache cannot be |
||
2061 | ** trusted. Now that there are no outstanding references to the pager, |
||
2062 | ** it can safely move back to PAGER_OPEN state. This happens in both |
||
2063 | ** normal and exclusive-locking mode. |
||
2064 | */ |
||
2065 | if ( pPager.errCode != 0 ) |
||
2066 | { |
||
2067 | Debug.Assert( |
||
2068 | #if SQLITE_OMIT_MEMORYDB |
||
2069 | 0==MEMDB |
||
2070 | #else |
||
2071 | |||
2072 | #endif |
||
2073 | ); |
||
2074 | pager_reset( pPager ); |
||
2075 | pPager.changeCountDone = pPager.tempFile; |
||
2076 | pPager.eState = PAGER_OPEN; |
||
2077 | pPager.errCode = SQLITE_OK; |
||
2078 | } |
||
2079 | |||
2080 | pPager.journalOff = 0; |
||
2081 | pPager.journalHdr = 0; |
||
2082 | pPager.setMaster = 0; |
||
2083 | } |
||
2084 | |||
2085 | /* |
||
2086 | ** This function is called whenever an IOERR or FULL error that requires |
||
2087 | ** the pager to transition into the ERROR state may ahve occurred. |
||
2088 | ** The first argument is a pointer to the pager structure, the second |
||
2089 | ** the error-code about to be returned by a pager API function. The |
||
2090 | ** value returned is a copy of the second argument to this function. |
||
2091 | ** |
||
2092 | ** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the |
||
2093 | ** IOERR sub-codes, the pager enters the ERROR state and the error code |
||
2094 | ** is stored in Pager.errCode. While the pager remains in the ERROR state, |
||
2095 | ** all major API calls on the Pager will immediately return Pager.errCode. |
||
2096 | ** |
||
2097 | ** The ERROR state indicates that the contents of the pager-cache |
||
2098 | ** cannot be trusted. This state can be cleared by completely discarding |
||
2099 | ** the contents of the pager-cache. If a transaction was active when |
||
2100 | ** the persistent error occurred, then the rollback journal may need |
||
2101 | ** to be replayed to restore the contents of the database file (as if |
||
2102 | ** it were a hot-journal). |
||
2103 | */ |
||
2104 | static int pager_error( Pager pPager, int rc ) |
||
2105 | { |
||
2106 | int rc2 = rc & 0xff; |
||
2107 | Debug.Assert( rc == SQLITE_OK || |
||
2108 | #if SQLITE_OMIT_MEMORYDB |
||
2109 | 0==MEMDB |
||
2110 | #else |
||
2111 | |||
2112 | #endif |
||
2113 | ); |
||
2114 | Debug.Assert( |
||
2115 | pPager.errCode == SQLITE_FULL || |
||
2116 | pPager.errCode == SQLITE_OK || |
||
2117 | ( pPager.errCode & 0xff ) == SQLITE_IOERR |
||
2118 | ); |
||
2119 | if ( |
||
2120 | rc2 == SQLITE_FULL || rc2 == SQLITE_IOERR ) |
||
2121 | { |
||
2122 | pPager.errCode = rc; |
||
2123 | pPager.eState = PAGER_ERROR; |
||
2124 | } |
||
2125 | return rc; |
||
2126 | } |
||
2127 | |||
2128 | /* |
||
2129 | ** This routine ends a transaction. A transaction is usually ended by |
||
2130 | ** either a COMMIT or a ROLLBACK operation. This routine may be called |
||
2131 | ** after rollback of a hot-journal, or if an error occurs while opening |
||
2132 | ** the journal file or writing the very first journal-header of a |
||
2133 | ** database transaction. |
||
2134 | ** |
||
2135 | ** This routine is never called in PAGER_ERROR state. If it is called |
||
2136 | ** in PAGER_NONE or PAGER_SHARED state and the lock held is less |
||
2137 | ** exclusive than a RESERVED lock, it is a no-op. |
||
2138 | ** |
||
2139 | ** Otherwise, any active savepoints are released. |
||
2140 | ** |
||
2141 | ** If the journal file is open, then it is "finalized". Once a journal |
||
2142 | ** file has been finalized it is not possible to use it to roll back a |
||
2143 | ** transaction. Nor will it be considered to be a hot-journal by this |
||
2144 | ** or any other database connection. Exactly how a journal is finalized |
||
2145 | ** depends on whether or not the pager is running in exclusive mode and |
||
2146 | ** the current journal-mode (Pager.journalMode value), as follows: |
||
2147 | ** |
||
2148 | ** journalMode==MEMORY |
||
2149 | ** Journal file descriptor is simply closed. This destroys an |
||
2150 | ** in-memory journal. |
||
2151 | ** |
||
2152 | ** journalMode==TRUNCATE |
||
2153 | ** Journal file is truncated to zero bytes in size. |
||
2154 | ** |
||
2155 | ** journalMode==PERSIST |
||
2156 | ** The first 28 bytes of the journal file are zeroed. This invalidates |
||
2157 | ** the first journal header in the file, and hence the entire journal |
||
2158 | ** file. An invalid journal file cannot be rolled back. |
||
2159 | ** |
||
2160 | ** journalMode==DELETE |
||
2161 | ** The journal file is closed and deleted using sqlite3OsDelete(). |
||
2162 | ** |
||
2163 | ** If the pager is running in exclusive mode, this method of finalizing |
||
2164 | ** the journal file is never used. Instead, if the journalMode is |
||
2165 | ** DELETE and the pager is in exclusive mode, the method described under |
||
2166 | ** journalMode==PERSIST is used instead. |
||
2167 | ** |
||
2168 | ** After the journal is finalized, the pager moves to PAGER_READER state. |
||
2169 | ** If running in non-exclusive rollback mode, the lock on the file is |
||
2170 | ** downgraded to a SHARED_LOCK. |
||
2171 | ** |
||
2172 | ** SQLITE_OK is returned if no error occurs. If an error occurs during |
||
2173 | ** any of the IO operations to finalize the journal file or unlock the |
||
2174 | ** database then the IO error code is returned to the user. If the |
||
2175 | ** operation to finalize the journal file fails, then the code still |
||
2176 | ** tries to unlock the database file if not in exclusive mode. If the |
||
2177 | ** unlock operation fails as well, then the first error code related |
||
2178 | ** to the first error encountered (the journal finalization one) is |
||
2179 | ** returned. |
||
2180 | */ |
||
2181 | static int pager_end_transaction( Pager pPager, int hasMaster ) |
||
2182 | { |
||
2183 | int rc = SQLITE_OK; /* Error code from journal finalization operation */ |
||
2184 | int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ |
||
2185 | /* Do nothing if the pager does not have an open write transaction |
||
2186 | ** or at least a RESERVED lock. This function may be called when there |
||
2187 | ** is no write-transaction active but a RESERVED or greater lock is |
||
2188 | ** held under two circumstances: |
||
2189 | ** |
||
2190 | ** 1. After a successful hot-journal rollback, it is called with |
||
2191 | ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. |
||
2192 | ** |
||
2193 | ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE |
||
2194 | ** lock switches back to locking_mode=normal and then executes a |
||
2195 | ** read-transaction, this function is called with eState==PAGER_READER |
||
2196 | ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. |
||
2197 | */ |
||
2198 | Debug.Assert( assert_pager_state( pPager ) ); |
||
2199 | Debug.Assert( pPager.eState != PAGER_ERROR ); |
||
2200 | if ( pPager.eState < PAGER_WRITER_LOCKED && pPager.eLock < RESERVED_LOCK ) |
||
2201 | { |
||
2202 | return SQLITE_OK; |
||
2203 | } |
||
2204 | |||
2205 | releaseAllSavepoints( pPager ); |
||
2206 | Debug.Assert( isOpen( pPager.jfd ) || pPager.pInJournal == null ); |
||
2207 | if ( isOpen( pPager.jfd ) ) |
||
2208 | { |
||
2209 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
2210 | |||
2211 | /* Finalize the journal file. */ |
||
2212 | if ( sqlite3IsMemJournal( pPager.jfd ) ) |
||
2213 | { |
||
2214 | Debug.Assert( pPager.journalMode == PAGER_JOURNALMODE_MEMORY ); |
||
2215 | sqlite3OsClose( pPager.jfd ); |
||
2216 | } |
||
2217 | else if ( pPager.journalMode == PAGER_JOURNALMODE_TRUNCATE ) |
||
2218 | { |
||
2219 | if ( pPager.journalOff == 0 ) |
||
2220 | { |
||
2221 | rc = SQLITE_OK; |
||
2222 | } |
||
2223 | else |
||
2224 | { |
||
2225 | rc = sqlite3OsTruncate( pPager.jfd, 0 ); |
||
2226 | } |
||
2227 | pPager.journalOff = 0; |
||
2228 | } |
||
2229 | else if ( pPager.journalMode == PAGER_JOURNALMODE_PERSIST |
||
2230 | || ( pPager.exclusiveMode && pPager.journalMode != PAGER_JOURNALMODE_WAL ) |
||
2231 | ) |
||
2232 | { |
||
2233 | rc = zeroJournalHdr( pPager, hasMaster ); |
||
2234 | pPager.journalOff = 0; |
||
2235 | } |
||
2236 | else |
||
2237 | { |
||
2238 | /* This branch may be executed with Pager.journalMode==MEMORY if |
||
2239 | ** a hot-journal was just rolled back. In this case the journal |
||
2240 | ** file should be closed and deleted. If this connection writes to |
||
2241 | ** the database file, it will do so using an in-memory journal. |
||
2242 | */ |
||
2243 | Debug.Assert( pPager.journalMode == PAGER_JOURNALMODE_DELETE |
||
2244 | || pPager.journalMode == PAGER_JOURNALMODE_MEMORY |
||
2245 | || pPager.journalMode == PAGER_JOURNALMODE_WAL |
||
2246 | ); |
||
2247 | sqlite3OsClose( pPager.jfd ); |
||
2248 | if ( !pPager.tempFile ) |
||
2249 | { |
||
2250 | rc = sqlite3OsDelete( pPager.pVfs, pPager.zJournal, 0 ); |
||
2251 | } |
||
2252 | } |
||
2253 | } |
||
2254 | #if SQLITE_CHECK_PAGES |
||
2255 | sqlite3PcacheIterateDirty(pPager.pPCache, pager_set_pagehash); |
||
2256 | if( pPager.dbSize==0 && sqlite3PcacheRefCount(pPager.pPCache)>0 ){ |
||
2257 | PgHdr p = pager_lookup(pPager, 1); |
||
2258 | if( p != null ){ |
||
2259 | p.pageHash = null; |
||
2260 | sqlite3PagerUnref(p); |
||
2261 | } |
||
2262 | } |
||
2263 | #endif |
||
2264 | sqlite3BitvecDestroy( ref pPager.pInJournal ); |
||
2265 | pPager.pInJournal = null; |
||
2266 | pPager.nRec = 0; |
||
2267 | sqlite3PcacheCleanAll( pPager.pPCache ); |
||
2268 | sqlite3PcacheTruncate( pPager.pPCache, pPager.dbSize ); |
||
2269 | |||
2270 | if ( pagerUseWal( pPager ) ) |
||
2271 | { |
||
2272 | /* Drop the WAL write-lock, if any. Also, if the connection was in |
||
2273 | ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE |
||
2274 | ** lock held on the database file. |
||
2275 | */ |
||
2276 | rc2 = sqlite3WalEndWriteTransaction( pPager.pWal ); |
||
2277 | Debug.Assert( rc2 == SQLITE_OK ); |
||
2278 | } |
||
2279 | if ( !pPager.exclusiveMode |
||
2280 | && ( !pagerUseWal( pPager ) || sqlite3WalExclusiveMode( pPager.pWal, 0 ) ) |
||
2281 | ) |
||
2282 | { |
||
2283 | rc2 = pagerUnlockDb( pPager, SHARED_LOCK ); |
||
2284 | pPager.changeCountDone = false; |
||
2285 | } |
||
2286 | pPager.eState = PAGER_READER; |
||
2287 | pPager.setMaster = 0; |
||
2288 | |||
2289 | return ( rc == SQLITE_OK ? rc2 : rc ); |
||
2290 | } |
||
2291 | |||
2292 | /* |
||
2293 | ** Execute a rollback if a transaction is active and unlock the |
||
2294 | ** database file. |
||
2295 | ** |
||
2296 | ** If the pager has already entered the ERROR state, do not attempt |
||
2297 | ** the rollback at this time. Instead, pager_unlock() is called. The |
||
2298 | ** call to pager_unlock() will discard all in-memory pages, unlock |
||
2299 | ** the database file and move the pager back to OPEN state. If this |
||
2300 | ** means that there is a hot-journal left in the file-system, the next |
||
2301 | ** connection to obtain a shared lock on the pager (which may be this one) |
||
2302 | ** will roll it back. |
||
2303 | ** |
||
2304 | ** If the pager has not already entered the ERROR state, but an IO or |
||
2305 | ** malloc error occurs during a rollback, then this will itself cause |
||
2306 | ** the pager to enter the ERROR state. Which will be cleared by the |
||
2307 | ** call to pager_unlock(), as described above. |
||
2308 | */ |
||
2309 | static void pagerUnlockAndRollback( Pager pPager ) |
||
2310 | { |
||
2311 | if ( pPager.eState != PAGER_ERROR && pPager.eState != PAGER_OPEN ) |
||
2312 | { |
||
2313 | Debug.Assert( assert_pager_state( pPager ) ); |
||
2314 | if ( pPager.eState >= PAGER_WRITER_LOCKED ) |
||
2315 | { |
||
2316 | sqlite3BeginBenignMalloc(); |
||
2317 | sqlite3PagerRollback( pPager ); |
||
2318 | sqlite3EndBenignMalloc(); |
||
2319 | } |
||
2320 | else if ( !pPager.exclusiveMode ) |
||
2321 | { |
||
2322 | Debug.Assert( pPager.eState == PAGER_READER ); |
||
2323 | pager_end_transaction( pPager, 0 ); |
||
2324 | } |
||
2325 | } |
||
2326 | pager_unlock( pPager ); |
||
2327 | } |
||
2328 | |||
2329 | /* |
||
2330 | ** Parameter aData must point to a buffer of pPager.pageSize bytes |
||
2331 | ** of data. Compute and return a checksum based ont the contents of the |
||
2332 | ** page of data and the current value of pPager.cksumInit. |
||
2333 | ** |
||
2334 | ** This is not a real checksum. It is really just the sum of the |
||
2335 | ** random initial value (pPager.cksumInit) and every 200th byte |
||
2336 | ** of the page data, starting with byte offset (pPager.pageSize%200). |
||
2337 | ** Each byte is interpreted as an 8-bit unsigned integer. |
||
2338 | ** |
||
2339 | ** Changing the formula used to compute this checksum results in an |
||
2340 | ** incompatible journal file format. |
||
2341 | ** |
||
2342 | ** If journal corruption occurs due to a power failure, the most likely |
||
2343 | ** scenario is that one end or the other of the record will be changed. |
||
2344 | ** It is much less likely that the two ends of the journal record will be |
||
2345 | ** correct and the middle be corrupt. Thus, this "checksum" scheme, |
||
2346 | ** though fast and simple, catches the mostly likely kind of corruption. |
||
2347 | */ |
||
2348 | static u32 pager_cksum( Pager pPager, byte[] aData ) |
||
2349 | { |
||
2350 | u32 cksum = pPager.cksumInit; /* Checksum value to return */ |
||
2351 | int i = pPager.pageSize - 200; /* Loop counter */ |
||
2352 | while ( i > 0 ) |
||
2353 | { |
||
2354 | cksum += aData[i]; |
||
2355 | i -= 200; |
||
2356 | } |
||
2357 | return cksum; |
||
2358 | } |
||
2359 | |||
2360 | /* |
||
2361 | ** Report the current page size and number of reserved bytes back |
||
2362 | ** to the codec. |
||
2363 | */ |
||
2364 | #if SQLITE_HAS_CODEC |
||
2365 | static void pagerReportSize( Pager pPager ) |
||
2366 | { |
||
2367 | if ( pPager.xCodecSizeChng != null ) |
||
2368 | { |
||
2369 | pPager.xCodecSizeChng( pPager.pCodec, pPager.pageSize, |
||
2370 | pPager.nReserve ); |
||
2371 | } |
||
2372 | } |
||
2373 | #else |
||
2374 | //# define pagerReportSize(X) /* No-op if we do not support a codec */ |
||
2375 | static void pagerReportSize(Pager X){} |
||
2376 | #endif |
||
2377 | |||
2378 | /* |
||
2379 | ** Read a single page from either the journal file (if isMainJrnl==1) or |
||
2380 | ** from the sub-journal (if isMainJrnl==0) and playback that page. |
||
2381 | ** The page begins at offset *pOffset into the file. The *pOffset |
||
2382 | ** value is increased to the start of the next page in the journal. |
||
2383 | ** |
||
2384 | ** The main rollback journal uses checksums - the statement journal does |
||
2385 | ** not. |
||
2386 | ** |
||
2387 | ** If the page number of the page record read from the (sub-)journal file |
||
2388 | ** is greater than the current value of Pager.dbSize, then playback is |
||
2389 | ** skipped and SQLITE_OK is returned. |
||
2390 | ** |
||
2391 | ** If pDone is not NULL, then it is a record of pages that have already |
||
2392 | ** been played back. If the page at *pOffset has already been played back |
||
2393 | ** (if the corresponding pDone bit is set) then skip the playback. |
||
2394 | ** Make sure the pDone bit corresponding to the *pOffset page is set |
||
2395 | ** prior to returning. |
||
2396 | ** |
||
2397 | ** If the page record is successfully read from the (sub-)journal file |
||
2398 | ** and played back, then SQLITE_OK is returned. If an IO error occurs |
||
2399 | ** while reading the record from the (sub-)journal file or while writing |
||
2400 | ** to the database file, then the IO error code is returned. If data |
||
2401 | ** is successfully read from the (sub-)journal file but appears to be |
||
2402 | ** corrupted, SQLITE_DONE is returned. Data is considered corrupted in |
||
2403 | ** two circumstances: |
||
2404 | ** |
||
2405 | ** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or |
||
2406 | ** * If the record is being rolled back from the main journal file |
||
2407 | ** and the checksum field does not match the record content. |
||
2408 | ** |
||
2409 | ** Neither of these two scenarios are possible during a savepoint rollback. |
||
2410 | ** |
||
2411 | ** If this is a savepoint rollback, then memory may have to be dynamically |
||
2412 | ** allocated by this function. If this is the case and an allocation fails, |
||
2413 | ** SQLITE_NOMEM is returned. |
||
2414 | */ |
||
2415 | static int pager_playback_one_page( |
||
2416 | Pager pPager, /* The pager being played back */ |
||
2417 | ref i64 pOffset, /* Offset of record to playback */ |
||
2418 | Bitvec pDone, /* Bitvec of pages already played back */ |
||
2419 | int isMainJrnl, /* True for main rollback journal. False for Stmt jrnl */ |
||
2420 | int isSavepnt /* True for a savepoint rollback */ |
||
2421 | ) |
||
2422 | { |
||
2423 | int rc; |
||
2424 | PgHdr pPg; /* An existing page in the cache */ |
||
2425 | Pgno pgno = 0; /* The page number of a page in journal */ |
||
2426 | u32 cksum = 0; /* Checksum used for sanity checking */ |
||
2427 | byte[] aData; /* Temporary storage for the page */ |
||
2428 | sqlite3_file jfd; /* The file descriptor for the journal file */ |
||
2429 | bool isSynced; /* True if journal page is synced */ |
||
2430 | |||
2431 | Debug.Assert( ( isMainJrnl & ~1 ) == 0 ); /* isMainJrnl is 0 or 1 */ |
||
2432 | Debug.Assert( ( isSavepnt & ~1 ) == 0 ); /* isSavepnt is 0 or 1 */ |
||
2433 | Debug.Assert( isMainJrnl != 0 || pDone != null ); /* pDone always used on sub-journals */ |
||
2434 | Debug.Assert( isSavepnt != 0 || pDone == null ); /* pDone never used on non-savepoint */ |
||
2435 | |||
2436 | aData = pPager.pTmpSpace; |
||
2437 | Debug.Assert( aData != null ); /* Temp storage must have already been allocated */ |
||
2438 | Debug.Assert( pagerUseWal( pPager ) == false || ( 0 == isMainJrnl && isSavepnt != 0 ) ); |
||
2439 | |||
2440 | /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction |
||
2441 | ** or savepoint rollback done at the request of the caller) or this is |
||
2442 | ** a hot-journal rollback. If it is a hot-journal rollback, the pager |
||
2443 | ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback |
||
2444 | ** only reads from the main journal, not the sub-journal. |
||
2445 | */ |
||
2446 | Debug.Assert( pPager.eState >= PAGER_WRITER_CACHEMOD |
||
2447 | || ( pPager.eState == PAGER_OPEN && pPager.eLock == EXCLUSIVE_LOCK ) |
||
2448 | ); |
||
2449 | Debug.Assert( pPager.eState >= PAGER_WRITER_CACHEMOD || isMainJrnl != 0 ); |
||
2450 | |||
2451 | /* Read the page number and page data from the journal or sub-journal |
||
2452 | ** file. Return an error code to the caller if an IO error occurs. |
||
2453 | */ |
||
2454 | jfd = isMainJrnl != 0 ? pPager.jfd : pPager.sjfd; |
||
2455 | |||
2456 | rc = read32bits( jfd, pOffset, ref pgno ); |
||
2457 | if ( rc != SQLITE_OK ) |
||
2458 | return rc; |
||
2459 | rc = sqlite3OsRead( jfd, aData, pPager.pageSize, ( pOffset ) + 4 ); |
||
2460 | if ( rc != SQLITE_OK ) |
||
2461 | return rc; |
||
2462 | pOffset += pPager.pageSize + 4 + isMainJrnl * 4; |
||
2463 | |||
2464 | /* Sanity checking on the page. This is more important that I originally |
||
2465 | ** thought. If a power failure occurs while the journal is being written, |
||
2466 | ** it could cause invalid data to be written into the journal. We need to |
||
2467 | ** detect this invalid data (with high probability) and ignore it. |
||
2468 | */ |
||
2469 | if ( pgno == 0 || pgno == PAGER_MJ_PGNO( pPager ) ) |
||
2470 | { |
||
2471 | Debug.Assert( 0 == isSavepnt ); |
||
2472 | return SQLITE_DONE; |
||
2473 | } |
||
2474 | if ( pgno > pPager.dbSize || sqlite3BitvecTest( pDone, pgno ) != 0 ) |
||
2475 | { |
||
2476 | return SQLITE_OK; |
||
2477 | } |
||
2478 | if ( isMainJrnl != 0 ) |
||
2479 | { |
||
2480 | rc = read32bits( jfd, ( pOffset ) - 4, ref cksum ); |
||
2481 | if ( rc != 0 ) |
||
2482 | return rc; |
||
2483 | if ( 0 == isSavepnt && pager_cksum( pPager, aData ) != cksum ) |
||
2484 | { |
||
2485 | return SQLITE_DONE; |
||
2486 | } |
||
2487 | } |
||
2488 | |||
2489 | /* If this page has already been played by before during the current |
||
2490 | ** rollback, then don't bother to play it back again. |
||
2491 | */ |
||
2492 | if ( pDone != null && ( rc = sqlite3BitvecSet( pDone, pgno ) ) != SQLITE_OK ) |
||
2493 | { |
||
2494 | return rc; |
||
2495 | } |
||
2496 | |||
2497 | /* When playing back page 1, restore the nReserve setting |
||
2498 | */ |
||
2499 | if ( pgno == 1 && pPager.nReserve != ( aData )[20] ) |
||
2500 | { |
||
2501 | pPager.nReserve = ( aData )[20]; |
||
2502 | pagerReportSize( pPager ); |
||
2503 | } |
||
2504 | |||
2505 | /* If the pager is in CACHEMOD state, then there must be a copy of this |
||
2506 | ** page in the pager cache. In this case just update the pager cache, |
||
2507 | ** not the database file. The page is left marked dirty in this case. |
||
2508 | ** |
||
2509 | ** An exception to the above rule: If the database is in no-sync mode |
||
2510 | ** and a page is moved during an incremental vacuum then the page may |
||
2511 | ** not be in the pager cache. Later: if a malloc() or IO error occurs |
||
2512 | ** during a Movepage() call, then the page may not be in the cache |
||
2513 | ** either. So the condition described in the above paragraph is not |
||
2514 | ** assert()able. |
||
2515 | ** |
||
2516 | ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the |
||
2517 | ** pager cache if it exists and the main file. The page is then marked |
||
2518 | ** not dirty. Since this code is only executed in PAGER_OPEN state for |
||
2519 | ** a hot-journal rollback, it is guaranteed that the page-cache is empty |
||
2520 | ** if the pager is in OPEN state. |
||
2521 | ** |
||
2522 | ** Ticket #1171: The statement journal might contain page content that is |
||
2523 | ** different from the page content at the start of the transaction. |
||
2524 | ** This occurs when a page is changed prior to the start of a statement |
||
2525 | ** then changed again within the statement. When rolling back such a |
||
2526 | ** statement we must not write to the original database unless we know |
||
2527 | ** for certain that original page contents are synced into the main rollback |
||
2528 | ** journal. Otherwise, a power loss might leave modified data in the |
||
2529 | ** database file without an entry in the rollback journal that can |
||
2530 | ** restore the database to its original form. Two conditions must be |
||
2531 | ** met before writing to the database files. (1) the database must be |
||
2532 | ** locked. (2) we know that the original page content is fully synced |
||
2533 | ** in the main journal either because the page is not in cache or else |
||
2534 | ** the page is marked as needSync==0. |
||
2535 | ** |
||
2536 | ** 2008-04-14: When attempting to vacuum a corrupt database file, it |
||
2537 | ** is possible to fail a statement on a database that does not yet exist. |
||
2538 | ** Do not attempt to write if database file has never been opened. |
||
2539 | */ |
||
2540 | if ( pagerUseWal( pPager ) ) |
||
2541 | { |
||
2542 | pPg = null; |
||
2543 | } |
||
2544 | else |
||
2545 | { |
||
2546 | pPg = pager_lookup( pPager, pgno ); |
||
2547 | } |
||
2548 | Debug.Assert( pPg != null || |
||
2549 | #if SQLITE_OMIT_MEMORYDB |
||
2550 | 0==MEMDB |
||
2551 | #else |
||
2552 | pPager.memDb == 0 |
||
2553 | #endif |
||
2554 | ); |
||
2555 | Debug.Assert( pPager.eState != PAGER_OPEN || pPg == null ); |
||
2556 | |||
2557 | PAGERTRACE( "PLAYBACK %d page %d hash(%08x) %s\n", |
||
2558 | PAGERID( pPager ), pgno, pager_datahash( pPager.pageSize, aData ), |
||
2559 | ( isMainJrnl != 0 ? "main-journal" : "sub-journal" ) |
||
2560 | ); |
||
2561 | if ( isMainJrnl != 0 ) |
||
2562 | { |
||
2563 | isSynced = pPager.noSync || ( pOffset <= pPager.journalHdr ); |
||
2564 | } |
||
2565 | else |
||
2566 | { |
||
2567 | isSynced = ( pPg == null || 0 == ( pPg.flags & PGHDR_NEED_SYNC ) ); |
||
2568 | } |
||
2569 | if ( isOpen( pPager.fd ) |
||
2570 | && ( pPager.eState >= PAGER_WRITER_DBMOD || pPager.eState == PAGER_OPEN ) |
||
2571 | && isSynced |
||
2572 | ) |
||
2573 | { |
||
2574 | i64 ofst = ( pgno - 1 ) * pPager.pageSize; |
||
2575 | testcase( 0 == isSavepnt && pPg != null && ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ); |
||
2576 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
2577 | rc = sqlite3OsWrite( pPager.fd, aData, pPager.pageSize, ofst ); |
||
2578 | if ( pgno > pPager.dbFileSize ) |
||
2579 | { |
||
2580 | pPager.dbFileSize = pgno; |
||
2581 | } |
||
2582 | if ( pPager.pBackup != null ) |
||
2583 | { |
||
2584 | if ( CODEC1( pPager, aData, pgno, SQLITE_DECRYPT ) ) |
||
2585 | rc = SQLITE_NOMEM; // CODEC1( pPager, aData, pgno, 3, rc = SQLITE_NOMEM ); |
||
2586 | sqlite3BackupUpdate( pPager.pBackup, pgno, (u8[])aData ); |
||
2587 | if ( CODEC2( pPager, aData, pgno, SQLITE_ENCRYPT_READ_CTX, ref aData ) ) |
||
2588 | rc = SQLITE_NOMEM;//CODEC2( pPager, aData, pgno, 7, rc = SQLITE_NOMEM, aData); |
||
2589 | } |
||
2590 | } |
||
2591 | else if ( 0 == isMainJrnl && pPg == null ) |
||
2592 | { |
||
2593 | /* If this is a rollback of a savepoint and data was not written to |
||
2594 | ** the database and the page is not in-memory, there is a potential |
||
2595 | ** problem. When the page is next fetched by the b-tree layer, it |
||
2596 | ** will be read from the database file, which may or may not be |
||
2597 | ** current. |
||
2598 | ** |
||
2599 | ** There are a couple of different ways this can happen. All are quite |
||
2600 | ** obscure. When running in synchronous mode, this can only happen |
||
2601 | ** if the page is on the free-list at the start of the transaction, then |
||
2602 | ** populated, then moved using sqlite3PagerMovepage(). |
||
2603 | ** |
||
2604 | ** The solution is to add an in-memory page to the cache containing |
||
2605 | ** the data just read from the sub-journal. Mark the page as dirty |
||
2606 | ** and if the pager requires a journal-sync, then mark the page as |
||
2607 | ** requiring a journal-sync before it is written. |
||
2608 | */ |
||
2609 | Debug.Assert( isSavepnt != 0 ); |
||
2610 | Debug.Assert( pPager.doNotSpill == 0 ); |
||
2611 | pPager.doNotSpill++; |
||
2612 | rc = sqlite3PagerAcquire( pPager, pgno, ref pPg, 1 ); |
||
2613 | Debug.Assert( pPager.doNotSpill == 1 ); |
||
2614 | pPager.doNotSpill--; |
||
2615 | if ( rc != SQLITE_OK ) |
||
2616 | return rc; |
||
2617 | pPg.flags &= ~PGHDR_NEED_READ; |
||
2618 | sqlite3PcacheMakeDirty( pPg ); |
||
2619 | } |
||
2620 | if ( pPg != null ) |
||
2621 | { |
||
2622 | /* No page should ever be explicitly rolled back that is in use, except |
||
2623 | ** for page 1 which is held in use in order to keep the lock on the |
||
2624 | ** database active. However such a page may be rolled back as a result |
||
2625 | ** of an internal error resulting in an automatic call to |
||
2626 | ** sqlite3PagerRollback(). |
||
2627 | */ |
||
2628 | byte[] pData = pPg.pData; |
||
2629 | Buffer.BlockCopy( aData, 0, pData, 0, pPager.pageSize );// memcpy(pData, (u8[])aData, pPager.pageSize); |
||
2630 | pPager.xReiniter( pPg ); |
||
2631 | if ( isMainJrnl != 0 && ( 0 == isSavepnt || pOffset <= pPager.journalHdr ) ) |
||
2632 | { |
||
2633 | /* If the contents of this page were just restored from the main |
||
2634 | ** journal file, then its content must be as they were when the |
||
2635 | ** transaction was first opened. In this case we can mark the page |
||
2636 | ** as clean, since there will be no need to write it out to the |
||
2637 | ** database. |
||
2638 | ** |
||
2639 | ** There is one exception to this rule. If the page is being rolled |
||
2640 | ** back as part of a savepoint (or statement) rollback from an |
||
2641 | ** unsynced portion of the main journal file, then it is not safe |
||
2642 | ** to mark the page as clean. This is because marking the page as |
||
2643 | ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is |
||
2644 | ** already in the journal file (recorded in Pager.pInJournal) and |
||
2645 | ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to |
||
2646 | ** again within this transaction, it will be marked as dirty but |
||
2647 | ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially |
||
2648 | ** be written out into the database file before its journal file |
||
2649 | ** segment is synced. If a crash occurs during or following this, |
||
2650 | ** database corruption may ensue. |
||
2651 | */ |
||
2652 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
2653 | sqlite3PcacheMakeClean( pPg ); |
||
2654 | } |
||
2655 | pager_set_pagehash( pPg ); |
||
2656 | /* If this was page 1, then restore the value of Pager.dbFileVers. |
||
2657 | ** Do this before any decoding. */ |
||
2658 | if ( pgno == 1 ) |
||
2659 | { |
||
2660 | Buffer.BlockCopy( pData, 24, pPager.dbFileVers, 0, pPager.dbFileVers.Length ); //memcpy(pPager.dbFileVers, ((u8*)pData)[24], sizeof(pPager.dbFileVers)); |
||
2661 | } |
||
2662 | |||
2663 | /* Decode the page just read from disk */ |
||
2664 | if ( CODEC1( pPager, pData, pPg.pgno, SQLITE_DECRYPT ) ) |
||
2665 | rc = SQLITE_NOMEM; //CODEC1(pPager, pData, pPg.pgno, 3, rc=SQLITE_NOMEM); |
||
2666 | sqlite3PcacheRelease( pPg ); |
||
2667 | } |
||
2668 | return rc; |
||
2669 | } |
||
2670 | |||
2671 | /* |
||
2672 | ** Parameter zMaster is the name of a master journal file. A single journal |
||
2673 | ** file that referred to the master journal file has just been rolled back. |
||
2674 | ** This routine checks if it is possible to delete the master journal file, |
||
2675 | ** and does so if it is. |
||
2676 | ** |
||
2677 | ** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not |
||
2678 | ** available for use within this function. |
||
2679 | ** |
||
2680 | ** When a master journal file is created, it is populated with the names |
||
2681 | ** of all of its child journals, one after another, formatted as utf-8 |
||
2682 | ** encoded text. The end of each child journal file is marked with a |
||
2683 | ** nul-terminator byte (0x00). i.e. the entire contents of a master journal |
||
2684 | ** file for a transaction involving two databases might be: |
||
2685 | ** |
||
2686 | ** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00" |
||
2687 | ** |
||
2688 | ** A master journal file may only be deleted once all of its child |
||
2689 | ** journals have been rolled back. |
||
2690 | ** |
||
2691 | ** This function reads the contents of the master-journal file into |
||
2692 | ** memory and loops through each of the child journal names. For |
||
2693 | ** each child journal, it checks if: |
||
2694 | ** |
||
2695 | ** * if the child journal exists, and if so |
||
2696 | ** * if the child journal contains a reference to master journal |
||
2697 | ** file zMaster |
||
2698 | ** |
||
2699 | ** If a child journal can be found that matches both of the criteria |
||
2700 | ** above, this function returns without doing anything. Otherwise, if |
||
2701 | ** no such child journal can be found, file zMaster is deleted from |
||
2702 | ** the file-system using sqlite3OsDelete(). |
||
2703 | ** |
||
2704 | ** If an IO error within this function, an error code is returned. This |
||
2705 | ** function allocates memory by calling sqlite3Malloc(). If an allocation |
||
2706 | ** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors |
||
2707 | ** occur, SQLITE_OK is returned. |
||
2708 | ** |
||
2709 | ** TODO: This function allocates a single block of memory to load |
||
2710 | ** the entire contents of the master journal file. This could be |
||
2711 | ** a couple of kilobytes or so - potentially larger than the page |
||
2712 | ** size. |
||
2713 | */ |
||
2714 | static int pager_delmaster( Pager pPager, string zMaster ) |
||
2715 | { |
||
2716 | sqlite3_vfs pVfs = pPager.pVfs; |
||
2717 | int rc; /* Return code */ |
||
2718 | sqlite3_file pMaster; /* Malloc'd master-journal file descriptor */ |
||
2719 | sqlite3_file pJournal; /* Malloc'd child-journal file descriptor */ |
||
2720 | //string zMasterJournal = null; /* Contents of master journal file */ |
||
2721 | i64 nMasterJournal; /* Size of master journal file */ |
||
2722 | string zJournal; /* Pointer to one journal within MJ file */ |
||
2723 | string zMasterPtr; /* Space to hold MJ filename from a journal file */ |
||
2724 | int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */ |
||
2725 | |||
2726 | /* Allocate space for both the pJournal and pMaster file descriptors. |
||
2727 | ** If successful, open the master journal file for reading. |
||
2728 | */ |
||
2729 | pMaster = new sqlite3_file();// (sqlite3_file*)sqlite3MallocZero( pVfs.szOsFile * 2 ); |
||
2730 | pJournal = new sqlite3_file();// (sqlite3_file*)( ( (u8*)pMaster ) + pVfs.szOsFile ); |
||
2731 | //if ( null == pMaster ) |
||
2732 | //{ |
||
2733 | // rc = SQLITE_NOMEM; |
||
2734 | //} |
||
2735 | //else |
||
2736 | { |
||
2737 | const int flags = ( SQLITE_OPEN_READONLY | SQLITE_OPEN_MASTER_JOURNAL ); |
||
2738 | int iDummy = 0; |
||
2739 | rc = sqlite3OsOpen( pVfs, zMaster, pMaster, flags, ref iDummy ); |
||
2740 | } |
||
2741 | if ( rc != SQLITE_OK ) |
||
2742 | goto delmaster_out; |
||
2743 | |||
2744 | Debugger.Break(); //TODO -- |
||
2745 | |||
2746 | /* Load the entire master journal file into space obtained from |
||
2747 | ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain |
||
2748 | ** sufficient space (in zMasterPtr) to hold the names of master |
||
2749 | ** journal files extracted from regular rollback-journals. |
||
2750 | */ |
||
2751 | //rc = sqlite3OsFileSize(pMaster, &nMasterJournal); |
||
2752 | //if (rc != SQLITE_OK) goto delmaster_out; |
||
2753 | //nMasterPtr = pVfs.mxPathname + 1; |
||
2754 | // zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1); |
||
2755 | // if ( !zMasterJournal ) |
||
2756 | // { |
||
2757 | // rc = SQLITE_NOMEM; |
||
2758 | // goto delmaster_out; |
||
2759 | // } |
||
2760 | // zMasterPtr = &zMasterJournal[nMasterJournal+1]; |
||
2761 | // rc = sqlite3OsRead( pMaster, zMasterJournal, (int)nMasterJournal, 0 ); |
||
2762 | // if ( rc != SQLITE_OK ) goto delmaster_out; |
||
2763 | // zMasterJournal[nMasterJournal] = 0; |
||
2764 | |||
2765 | |||
2766 | // zJournal = zMasterJournal; |
||
2767 | // while ( ( zJournal - zMasterJournal ) < nMasterJournal ) |
||
2768 | // { |
||
2769 | // int exists; |
||
2770 | // rc = sqlite3OsAccess( pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists ); |
||
2771 | // if ( rc != SQLITE_OK ) |
||
2772 | // { |
||
2773 | // goto delmaster_out; |
||
2774 | // } |
||
2775 | // if ( exists ) |
||
2776 | // { |
||
2777 | // /* One of the journals pointed to by the master journal exists. |
||
2778 | // ** Open it and check if it points at the master journal. If |
||
2779 | // ** so, return without deleting the master journal file. |
||
2780 | // */ |
||
2781 | // int c; |
||
2782 | // int flags = ( SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_JOURNAL ); |
||
2783 | // rc = sqlite3OsOpen( pVfs, zJournal, pJournal, flags, 0 ); |
||
2784 | // if ( rc != SQLITE_OK ) |
||
2785 | // { |
||
2786 | // goto delmaster_out; |
||
2787 | // } |
||
2788 | |||
2789 | // rc = readMasterJournal( pJournal, zMasterPtr, nMasterPtr ); |
||
2790 | // sqlite3OsClose( pJournal ); |
||
2791 | // if ( rc != SQLITE_OK ) |
||
2792 | // { |
||
2793 | // goto delmaster_out; |
||
2794 | // } |
||
2795 | |||
2796 | // c = zMasterPtr[0] != 0 && strcmp( zMasterPtr, zMaster ) == 0; |
||
2797 | // if ( c ) |
||
2798 | // { |
||
2799 | // /* We have a match. Do not delete the master journal file. */ |
||
2800 | // goto delmaster_out; |
||
2801 | // } |
||
2802 | // } |
||
2803 | // zJournal += ( sqlite3Strlen30( zJournal ) + 1 ); |
||
2804 | // } |
||
2805 | // |
||
2806 | //sqlite3OsClose(pMaster); |
||
2807 | //rc = sqlite3OsDelete( pVfs, zMaster, 0 ); |
||
2808 | |||
2809 | |||
2810 | goto delmaster_out; |
||
2811 | delmaster_out: |
||
2812 | //sqlite3_free( ref zMasterJournal ); |
||
2813 | if ( pMaster != null ) |
||
2814 | { |
||
2815 | sqlite3OsClose( pMaster ); |
||
2816 | Debug.Assert( !isOpen( pJournal ) ); |
||
2817 | //sqlite3_free( ref pMaster ); |
||
2818 | } |
||
2819 | return rc; |
||
2820 | } |
||
2821 | |||
2822 | |||
2823 | |||
2824 | /* |
||
2825 | ** This function is used to change the actual size of the database |
||
2826 | ** file in the file-system. This only happens when committing a transaction, |
||
2827 | ** or rolling back a transaction (including rolling back a hot-journal). |
||
2828 | ** |
||
2829 | ** If the main database file is not open, or the pager is not in either |
||
2830 | ** DBMOD or OPEN state, this function is a no-op. Otherwise, the size |
||
2831 | ** of the file is changed to nPage pages (nPage*pPager.pageSize bytes). |
||
2832 | ** If the file on disk is currently larger than nPage pages, then use the VFS |
||
2833 | ** xTruncate() method to truncate it. |
||
2834 | ** |
||
2835 | ** Or, it might might be the case that the file on disk is smaller than |
||
2836 | ** nPage pages. Some operating system implementations can get confused if |
||
2837 | ** you try to truncate a file to some size that is larger than it |
||
2838 | ** currently is, so detect this case and write a single zero byte to |
||
2839 | ** the end of the new file instead. |
||
2840 | ** |
||
2841 | ** If successful, return SQLITE_OK. If an IO error occurs while modifying |
||
2842 | ** the database file, return the error code to the caller. |
||
2843 | */ |
||
2844 | static int pager_truncate( Pager pPager, u32 nPage ) |
||
2845 | { |
||
2846 | int rc = SQLITE_OK; |
||
2847 | Debug.Assert( pPager.eState != PAGER_ERROR ); |
||
2848 | Debug.Assert( pPager.eState != PAGER_READER ); |
||
2849 | |||
2850 | if ( isOpen( pPager.fd ) |
||
2851 | && ( pPager.eState >= PAGER_WRITER_DBMOD || pPager.eState == PAGER_OPEN ) |
||
2852 | ) |
||
2853 | { |
||
2854 | i64 currentSize = 0, newSize; |
||
2855 | int szPage = pPager.pageSize; |
||
2856 | Debug.Assert( pPager.eLock == EXCLUSIVE_LOCK ); |
||
2857 | /* TODO: Is it safe to use Pager.dbFileSize here? */ |
||
2858 | rc = sqlite3OsFileSize( pPager.fd, ref currentSize ); |
||
2859 | newSize = szPage * nPage; |
||
2860 | if ( rc == SQLITE_OK && currentSize != newSize ) |
||
2861 | { |
||
2862 | if ( currentSize > newSize ) |
||
2863 | { |
||
2864 | rc = sqlite3OsTruncate( pPager.fd, newSize ); |
||
2865 | } |
||
2866 | else |
||
2867 | { |
||
2868 | byte[] pTmp = pPager.pTmpSpace; |
||
2869 | Array.Clear( pTmp, 0, szPage );//memset( pTmp, 0, szPage ); |
||
2870 | testcase( ( newSize - szPage ) < currentSize ); |
||
2871 | testcase( ( newSize - szPage ) == currentSize ); |
||
2872 | testcase( ( newSize - szPage ) > currentSize ); |
||
2873 | rc = sqlite3OsWrite( pPager.fd, pTmp, szPage, newSize - szPage ); |
||
2874 | } |
||
2875 | if ( rc == SQLITE_OK ) |
||
2876 | { |
||
2877 | pPager.dbSize = nPage; |
||
2878 | } |
||
2879 | } |
||
2880 | } |
||
2881 | return rc; |
||
2882 | } |
||
2883 | |||
2884 | /* |
||
2885 | ** Set the value of the Pager.sectorSize variable for the given |
||
2886 | ** pager based on the value returned by the xSectorSize method |
||
2887 | ** of the open database file. The sector size will be used used |
||
2888 | ** to determine the size and alignment of journal header and |
||
2889 | ** master journal pointers within created journal files. |
||
2890 | ** |
||
2891 | ** For temporary files the effective sector size is always 512 bytes. |
||
2892 | ** |
||
2893 | ** Otherwise, for non-temporary files, the effective sector size is |
||
2894 | ** the value returned by the xSectorSize() method rounded up to 512 if |
||
2895 | ** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it |
||
2896 | ** is greater than MAX_SECTOR_SIZE. |
||
2897 | */ |
||
2898 | static void setSectorSize( Pager pPager ) |
||
2899 | { |
||
2900 | Debug.Assert( isOpen( pPager.fd ) || pPager.tempFile ); |
||
2901 | if ( !pPager.tempFile ) |
||
2902 | { |
||
2903 | /* Sector size doesn't matter for temporary files. Also, the file |
||
2904 | ** may not have been opened yet, in which case the OsSectorSize() |
||
2905 | ** call will segfault. |
||
2906 | */ |
||
2907 | pPager.sectorSize = (u32)sqlite3OsSectorSize( pPager.fd ); |
||
2908 | } |
||
2909 | if ( pPager.sectorSize < 32 ) |
||
2910 | { |
||
2911 | Debug.Assert( MAX_SECTOR_SIZE >= 4096 ); |
||
2912 | pPager.sectorSize = 4096; |
||
2913 | } |
||
2914 | if ( pPager.sectorSize > MAX_SECTOR_SIZE ) |
||
2915 | { |
||
2916 | pPager.sectorSize = MAX_SECTOR_SIZE; |
||
2917 | } |
||
2918 | } |
||
2919 | |||
2920 | |||
2921 | /* |
||
2922 | ** Playback the journal and thus restore the database file to |
||
2923 | ** the state it was in before we started making changes. |
||
2924 | ** |
||
2925 | ** The journal file format is as follows: |
||
2926 | ** |
||
2927 | ** (1) 8 byte prefix. A copy of aJournalMagic[]. |
||
2928 | ** (2) 4 byte big-endian integer which is the number of valid page records |
||
2929 | ** in the journal. If this value is 0xffffffff, then compute the |
||
2930 | ** number of page records from the journal size. |
||
2931 | ** (3) 4 byte big-endian integer which is the initial value for the |
||
2932 | ** sanity checksum. |
||
2933 | ** (4) 4 byte integer which is the number of pages to truncate the |
||
2934 | ** database to during a rollback. |
||
2935 | ** (5) 4 byte big-endian integer which is the sector size. The header |
||
2936 | ** is this many bytes in size. |
||
2937 | ** (6) 4 byte big-endian integer which is the page size. |
||
2938 | ** (7) zero padding out to the next sector size. |
||
2939 | ** (8) Zero or more pages instances, each as follows: |
||
2940 | ** |
||
2941 | ** When we speak of the journal header, we mean the first 7 items above. |
||
2942 | ** Each entry in the journal is an instance of the 8th item. |
||
2943 | ** |
||
2944 | ** Call the value from the second bullet "nRec". nRec is the number of |
||
2945 | ** valid page entries in the journal. In most cases, you can compute the |
||
2946 | ** value of nRec from the size of the journal file. But if a power |
||
2947 | ** failure occurred while the journal was being written, it could be the |
||
2948 | ** case that the size of the journal file had already been increased but |
||
2949 | ** the extra entries had not yet made it safely to disk. In such a case, |
||
2950 | ** the value of nRec computed from the file size would be too large. For |
||
2951 | ** that reason, we always use the nRec value in the header. |
||
2952 | ** |
||
2953 | ** If the nRec value is 0xffffffff it means that nRec should be computed |
||
2954 | ** from the file size. This value is used when the user selects the |
||
2955 | ** no-sync option for the journal. A power failure could lead to corruption |
||
2956 | ** in this case. But for things like temporary table (which will be |
||
2957 | ** deleted when the power is restored) we don't care. |
||
2958 | ** |
||
2959 | ** If the file opened as the journal file is not a well-formed |
||
2960 | ** journal file then all pages up to the first corrupted page are rolled |
||
2961 | ** back (or no pages if the journal header is corrupted). The journal file |
||
2962 | ** is then deleted and SQLITE_OK returned, just as if no corruption had |
||
2963 | ** been encountered. |
||
2964 | ** |
||
2965 | ** If an I/O or malloc() error occurs, the journal-file is not deleted |
||
2966 | ** and an error code is returned. |
||
2967 | ** |
||
2968 | ** The isHot parameter indicates that we are trying to rollback a journal |
||
2969 | ** that might be a hot journal. Or, it could be that the journal is |
||
2970 | ** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE. |
||
2971 | ** If the journal really is hot, reset the pager cache prior rolling |
||
2972 | ** back any content. If the journal is merely persistent, no reset is |
||
2973 | ** needed. |
||
2974 | */ |
||
2975 | static int pager_playback( Pager pPager, int isHot ) |
||
2976 | { |
||
2977 | sqlite3_vfs pVfs = pPager.pVfs; |
||
2978 | i64 szJ = 0; /* Size of the journal file in bytes */ |
||
2979 | u32 nRec = 0; /* Number of Records in the journal */ |
||
2980 | u32 u; /* Unsigned loop counter */ |
||
2981 | u32 mxPg = 0; /* Size of the original file in pages */ |
||
2982 | int rc; /* Result code of a subroutine */ |
||
2983 | int res = 1; /* Value returned by sqlite3OsAccess() */ |
||
2984 | byte[] zMaster = null; /* Name of master journal file if any */ |
||
2985 | int needPagerReset; /* True to reset page prior to first page rollback */ |
||
2986 | |||
2987 | /* Figure out how many records are in the journal. Abort early if |
||
2988 | ** the journal is empty. |
||
2989 | */ |
||
2990 | Debug.Assert( isOpen( pPager.jfd ) ); |
||
2991 | rc = sqlite3OsFileSize( pPager.jfd, ref szJ ); |
||
2992 | if ( rc != SQLITE_OK ) |
||
2993 | { |
||
2994 | goto end_playback; |
||
2995 | } |
||
2996 | |||
2997 | /* Read the master journal name from the journal, if it is present. |
||
2998 | ** If a master journal file name is specified, but the file is not |
||
2999 | ** present on disk, then the journal is not hot and does not need to be |
||
3000 | ** played back. |
||
3001 | ** |
||
3002 | ** TODO: Technically the following is an error because it assumes that |
||
3003 | ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that |
||
3004 | ** (pPager.pageSize >= pPager.pVfs.mxPathname+1). Using os_unix.c, |
||
3005 | ** mxPathname is 512, which is the same as the minimum allowable value |
||
3006 | ** for pageSize. |
||
3007 | */ |
||
3008 | zMaster = new byte[pPager.pVfs.mxPathname + 1];// pPager.pTmpSpace ); |
||
3009 | rc = readMasterJournal( pPager.jfd, zMaster, (u32)pPager.pVfs.mxPathname + 1 ); |
||
3010 | if ( rc == SQLITE_OK && zMaster[0] != 0 ) |
||
3011 | { |
||
3012 | rc = sqlite3OsAccess( pVfs, Encoding.UTF8.GetString( zMaster, 0, zMaster.Length ), SQLITE_ACCESS_EXISTS, ref res ); |
||
3013 | } |
||
3014 | zMaster = null; |
||
3015 | if ( rc != SQLITE_OK || res == 0 ) |
||
3016 | { |
||
3017 | goto end_playback; |
||
3018 | } |
||
3019 | pPager.journalOff = 0; |
||
3020 | needPagerReset = isHot; |
||
3021 | |||
3022 | /* This loop terminates either when a readJournalHdr() or |
||
3023 | ** pager_playback_one_page() call returns SQLITE_DONE or an IO error |
||
3024 | ** occurs. |
||
3025 | */ |
||
3026 | while ( true ) |
||
3027 | { |
||
3028 | |||
3029 | /* Read the next journal header from the journal file. If there are |
||
3030 | ** not enough bytes left in the journal file for a complete header, or |
||
3031 | ** it is corrupted, then a process must have failed while writing it. |
||
3032 | ** This indicates nothing more needs to be rolled back. |
||
3033 | */ |
||
3034 | rc = readJournalHdr( pPager, isHot, szJ, out nRec, out mxPg ); |
||
3035 | if ( rc != SQLITE_OK ) |
||
3036 | { |
||
3037 | if ( rc == SQLITE_DONE ) |
||
3038 | { |
||
3039 | rc = SQLITE_OK; |
||
3040 | } |
||
3041 | goto end_playback; |
||
3042 | } |
||
3043 | |||
3044 | /* If nRec is 0xffffffff, then this journal was created by a process |
||
3045 | ** working in no-sync mode. This means that the rest of the journal |
||
3046 | ** file consists of pages, there are no more journal headers. Compute |
||
3047 | ** the value of nRec based on this assumption. |
||
3048 | */ |
||
3049 | if ( nRec == 0xffffffff ) |
||
3050 | { |
||
3051 | Debug.Assert( pPager.journalOff == JOURNAL_HDR_SZ( pPager ) ); |
||
3052 | nRec = (u32)( ( szJ - JOURNAL_HDR_SZ( pPager ) ) / JOURNAL_PG_SZ( pPager ) ); |
||
3053 | } |
||
3054 | |||
3055 | /* If nRec is 0 and this rollback is of a transaction created by this |
||
3056 | ** process and if this is the final header in the journal, then it means |
||
3057 | ** that this part of the journal was being filled but has not yet been |
||
3058 | ** synced to disk. Compute the number of pages based on the remaining |
||
3059 | ** size of the file. |
||
3060 | ** |
||
3061 | ** The third term of the test was added to fix ticket #2565. |
||
3062 | ** When rolling back a hot journal, nRec==0 always means that the next |
||
3063 | ** chunk of the journal contains zero pages to be rolled back. But |
||
3064 | ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in |
||
3065 | ** the journal, it means that the journal might contain additional |
||
3066 | ** pages that need to be rolled back and that the number of pages |
||
3067 | ** should be computed based on the journal file size. |
||
3068 | */ |
||
3069 | if ( nRec == 0 && 0 == isHot && |
||
3070 | pPager.journalHdr + JOURNAL_HDR_SZ( pPager ) == pPager.journalOff ) |
||
3071 | { |
||
3072 | nRec = (u32)( ( szJ - pPager.journalOff ) / JOURNAL_PG_SZ( pPager ) ); |
||
3073 | } |
||
3074 | |||
3075 | /* If this is the first header read from the journal, truncate the |
||
3076 | ** database file back to its original size. |
||
3077 | */ |
||
3078 | if ( pPager.journalOff == JOURNAL_HDR_SZ( pPager ) ) |
||
3079 | { |
||
3080 | rc = pager_truncate( pPager, mxPg ); |
||
3081 | if ( rc != SQLITE_OK ) |
||
3082 | { |
||
3083 | goto end_playback; |
||
3084 | } |
||
3085 | pPager.dbSize = mxPg; |
||
3086 | } |
||
3087 | |||
3088 | /* Copy original pages out of the journal and back into the |
||
3089 | ** database file and/or page cache. |
||
3090 | */ |
||
3091 | for ( u = 0; u < nRec; u++ ) |
||
3092 | { |
||
3093 | if ( needPagerReset != 0 ) |
||
3094 | { |
||
3095 | pager_reset( pPager ); |
||
3096 | needPagerReset = 0; |
||
3097 | } |
||
3098 | rc = pager_playback_one_page( pPager, ref pPager.journalOff, null, 1, 0 ); |
||
3099 | if ( rc != SQLITE_OK ) |
||
3100 | { |
||
3101 | if ( rc == SQLITE_DONE ) |
||
3102 | { |
||
3103 | rc = SQLITE_OK; |
||
3104 | pPager.journalOff = szJ; |
||
3105 | break; |
||
3106 | } |
||
3107 | else if ( rc == SQLITE_IOERR_SHORT_READ ) |
||
3108 | { |
||
3109 | /* If the journal has been truncated, simply stop reading and |
||
3110 | ** processing the journal. This might happen if the journal was |
||
3111 | ** not completely written and synced prior to a crash. In that |
||
3112 | ** case, the database should have never been written in the |
||
3113 | ** first place so it is OK to simply abandon the rollback. */ |
||
3114 | rc = SQLITE_OK; |
||
3115 | goto end_playback; |
||
3116 | } |
||
3117 | else |
||
3118 | { |
||
3119 | /* If we are unable to rollback, quit and return the error |
||
3120 | ** code. This will cause the pager to enter the error state |
||
3121 | ** so that no further harm will be done. Perhaps the next |
||
3122 | ** process to come along will be able to rollback the database. |
||
3123 | */ |
||
3124 | goto end_playback; |
||
3125 | } |
||
3126 | } |
||
3127 | } |
||
3128 | } |
||
3129 | /*NOTREACHED*/ |
||
3130 | |||
3131 | end_playback: |
||
3132 | /* Following a rollback, the database file should be back in its original |
||
3133 | ** state prior to the start of the transaction, so invoke the |
||
3134 | ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the |
||
3135 | ** assertion that the transaction counter was modified. |
||
3136 | */ |
||
3137 | sqlite3_int64 iDummy = 0; |
||
3138 | Debug.Assert( |
||
3139 | pPager.fd.pMethods == null || |
||
3140 | sqlite3OsFileControl( pPager.fd, SQLITE_FCNTL_DB_UNCHANGED, ref iDummy ) >= SQLITE_OK |
||
3141 | ); |
||
3142 | |||
3143 | /* If this playback is happening automatically as a result of an IO or |
||
3144 | ** malloc error that occurred after the change-counter was updated but |
||
3145 | ** before the transaction was committed, then the change-counter |
||
3146 | ** modification may just have been reverted. If this happens in exclusive |
||
3147 | ** mode, then subsequent transactions performed by the connection will not |
||
3148 | ** update the change-counter at all. This may lead to cache inconsistency |
||
3149 | ** problems for other processes at some point in the future. So, just |
||
3150 | ** in case this has happened, clear the changeCountDone flag now. |
||
3151 | */ |
||
3152 | pPager.changeCountDone = pPager.tempFile; |
||
3153 | |||
3154 | if ( rc == SQLITE_OK ) |
||
3155 | { |
||
3156 | zMaster = new byte[pPager.pVfs.mxPathname + 1];//pPager.pTmpSpace ); |
||
3157 | rc = readMasterJournal( pPager.jfd, zMaster, (u32)pPager.pVfs.mxPathname + 1 ); |
||
3158 | testcase( rc != SQLITE_OK ); |
||
3159 | } |
||
3160 | if ( rc == SQLITE_OK |
||
3161 | && ( pPager.eState >= PAGER_WRITER_DBMOD || pPager.eState == PAGER_OPEN ) |
||
3162 | ) |
||
3163 | { |
||
3164 | rc = sqlite3PagerSync( pPager ); |
||
3165 | } |
||
3166 | if ( rc == SQLITE_OK ) |
||
3167 | { |
||
3168 | rc = pager_end_transaction( pPager, zMaster[0] != '\0' ? 1 : 0 ); |
||
3169 | testcase( rc != SQLITE_OK ); |
||
3170 | } |
||
3171 | if ( rc == SQLITE_OK && zMaster[0] != '\0' && res != 0 ) |
||
3172 | { |
||
3173 | /* If there was a master journal and this routine will return success, |
||
3174 | ** see if it is possible to delete the master journal. |
||
3175 | */ |
||
3176 | rc = pager_delmaster( pPager, Encoding.UTF8.GetString( zMaster, 0, zMaster.Length ) ); |
||
3177 | testcase( rc != SQLITE_OK ); |
||
3178 | } |
||
3179 | |||
3180 | /* The Pager.sectorSize variable may have been updated while rolling |
||
3181 | ** back a journal created by a process with a different sector size |
||
3182 | ** value. Reset it to the correct value for this process. |
||
3183 | */ |
||
3184 | setSectorSize( pPager ); |
||
3185 | return rc; |
||
3186 | } |
||
3187 | |||
3188 | |||
3189 | /* |
||
3190 | ** Read the content for page pPg out of the database file and into |
||
3191 | ** pPg.pData. A shared lock or greater must be held on the database |
||
3192 | ** file before this function is called. |
||
3193 | ** |
||
3194 | ** If page 1 is read, then the value of Pager.dbFileVers[] is set to |
||
3195 | ** the value read from the database file. |
||
3196 | ** |
||
3197 | ** If an IO error occurs, then the IO error is returned to the caller. |
||
3198 | ** Otherwise, SQLITE_OK is returned. |
||
3199 | */ |
||
3200 | static int readDbPage( PgHdr pPg ) |
||
3201 | { |
||
3202 | Pager pPager = pPg.pPager; /* Pager object associated with page pPg */ |
||
3203 | Pgno pgno = pPg.pgno; /* Page number to read */ |
||
3204 | int rc = SQLITE_OK; /* Return code */ |
||
3205 | int isInWal = 0; /* True if page is in log file */ |
||
3206 | int pgsz = pPager.pageSize; /* Number of bytes to read */ |
||
3207 | |||
3208 | Debug.Assert( pPager.eState >= PAGER_READER && |
||
3209 | #if SQLITE_OMIT_MEMORYDB |
||
3210 | |||
3211 | #else |
||
3212 | |||
3213 | #endif |
||
3214 | ); |
||
3215 | Debug.Assert( isOpen( pPager.fd ) ); |
||
3216 | |||
3217 | if ( NEVER( !isOpen( pPager.fd ) ) ) |
||
3218 | { |
||
3219 | Debug.Assert( pPager.tempFile ); |
||
3220 | Array.Clear( pPg.pData, 0, pPager.pageSize );// memset(pPg.pData, 0, pPager.pageSize); |
||
3221 | return SQLITE_OK; |
||
3222 | } |
||
3223 | |||
3224 | if ( pagerUseWal( pPager ) ) |
||
3225 | { |
||
3226 | /* Try to pull the page from the write-ahead log. */ |
||
3227 | rc = sqlite3WalRead( pPager.pWal, pgno, ref isInWal, pgsz, pPg.pData ); |
||
3228 | } |
||
3229 | if ( rc == SQLITE_OK && 0 == isInWal ) |
||
3230 | { |
||
3231 | i64 iOffset = ( pgno - 1 ) * (i64)pPager.pageSize; |
||
3232 | rc = sqlite3OsRead( pPager.fd, pPg.pData, pgsz, iOffset ); |
||
3233 | if ( rc == SQLITE_IOERR_SHORT_READ ) |
||
3234 | { |
||
3235 | rc = SQLITE_OK; |
||
3236 | } |
||
3237 | } |
||
3238 | |||
3239 | if ( pgno == 1 ) |
||
3240 | { |
||
3241 | if ( rc != 0 ) |
||
3242 | { |
||
3243 | /* If the read is unsuccessful, set the dbFileVers[] to something |
||
3244 | ** that will never be a valid file version. dbFileVers[] is a copy |
||
3245 | ** of bytes 24..39 of the database. Bytes 28..31 should always be |
||
3246 | ** zero or the size of the database in page. Bytes 32..35 and 35..39 |
||
3247 | ** should be page numbers which are never 0xffffffff. So filling |
||
3248 | ** pPager.dbFileVers[] with all 0xff bytes should suffice. |
||
3249 | ** |
||
3250 | ** For an encrypted database, the situation is more complex: bytes |
||
3251 | ** 24..39 of the database are white noise. But the probability of |
||
3252 | ** white noising equaling 16 bytes of 0xff is vanishingly small so |
||
3253 | ** we should still be ok. |
||
3254 | */ |
||
3255 | for ( int i = 0; i < pPager.dbFileVers.Length; pPager.dbFileVers[i++] = 0xff ) |
||
3256 | ; // memset(pPager.dbFileVers, 0xff, sizeof(pPager.dbFileVers)); |
||
3257 | } |
||
3258 | else |
||
3259 | { |
||
3260 | //u8[] dbFileVers = pPg.pData[24]; |
||
3261 | Buffer.BlockCopy( pPg.pData, 24, pPager.dbFileVers, 0, pPager.dbFileVers.Length ); //memcpy(&pPager.dbFileVers, dbFileVers, sizeof(pPager.dbFileVers)); |
||
3262 | } |
||
3263 | } |
||
3264 | if ( CODEC1( pPager, pPg.pData, pgno, SQLITE_DECRYPT ) ) |
||
3265 | rc = SQLITE_NOMEM;//CODEC1(pPager, pPg.pData, pgno, 3, rc = SQLITE_NOMEM); |
||
3266 | |||
3267 | #if SQLITE_TEST |
||
3268 | // PAGER_INCR(ref sqlite3_pager_readdb_count); |
||
3269 | #if !TCLSH |
||
3270 | PAGER_INCR( ref sqlite3_pager_readdb_count ); |
||
3271 | #else |
||
3272 | int iValue; |
||
3273 | iValue = sqlite3_pager_readdb_count.iValue; |
||
3274 | PAGER_INCR( ref iValue ); |
||
3275 | sqlite3_pager_readdb_count.iValue = iValue; |
||
3276 | #endif |
||
3277 | |||
3278 | PAGER_INCR( ref pPager.nRead ); |
||
3279 | #endif |
||
3280 | IOTRACE( "PGIN %p %d\n", pPager, pgno ); |
||
3281 | PAGERTRACE( "FETCH %d page %d hash(%08x)\n", |
||
3282 | PAGERID( pPager ), pgno, pager_pagehash( pPg ) ); |
||
3283 | |||
3284 | return rc; |
||
3285 | } |
||
3286 | |||
3287 | /* |
||
3288 | ** Update the value of the change-counter at offsets 24 and 92 in |
||
3289 | ** the header and the sqlite version number at offset 96. |
||
3290 | ** |
||
3291 | ** This is an unconditional update. See also the pager_incr_changecounter() |
||
3292 | ** routine which only updates the change-counter if the update is actually |
||
3293 | ** needed, as determined by the pPager.changeCountDone state variable. |
||
3294 | */ |
||
3295 | static void pager_write_changecounter( PgHdr pPg ) |
||
3296 | { |
||
3297 | u32 change_counter; |
||
3298 | |||
3299 | /* Increment the value just read and write it back to byte 24. */ |
||
3300 | change_counter = sqlite3Get4byte( pPg.pPager.dbFileVers, 0 ) + 1; |
||
3301 | put32bits( pPg.pData, 24, change_counter ); |
||
3302 | |||
3303 | /* Also store the SQLite version number in bytes 96..99 and in |
||
3304 | ** bytes 92..95 store the change counter for which the version number |
||
3305 | ** is valid. */ |
||
3306 | put32bits( pPg.pData, 92, change_counter ); |
||
3307 | put32bits( pPg.pData, 96, SQLITE_VERSION_NUMBER ); |
||
3308 | } |
||
3309 | |||
3310 | #if !SQLITE_OMIT_WAL |
||
3311 | /* |
||
3312 | ** This function is invoked once for each page that has already been |
||
3313 | ** written into the log file when a WAL transaction is rolled back. |
||
3314 | ** Parameter iPg is the page number of said page. The pCtx argument |
||
3315 | ** is actually a pointer to the Pager structure. |
||
3316 | ** |
||
3317 | ** If page iPg is present in the cache, and has no outstanding references, |
||
3318 | ** it is discarded. Otherwise, if there are one or more outstanding |
||
3319 | ** references, the page content is reloaded from the database. If the |
||
3320 | ** attempt to reload content from the database is required and fails, |
||
3321 | ** return an SQLite error code. Otherwise, SQLITE_OK. |
||
3322 | */ |
||
3323 | static int pagerUndoCallback(void *pCtx, Pgno iPg){ |
||
3324 | int rc = SQLITE_OK; |
||
3325 | Pager *pPager = (Pager *)pCtx; |
||
3326 | PgHdr *pPg; |
||
3327 | |||
3328 | pPg = sqlite3PagerLookup(pPager, iPg); |
||
3329 | if( pPg ){ |
||
3330 | if( sqlite3PcachePageRefcount(pPg)==1 ){ |
||
3331 | sqlite3PcacheDrop(pPg); |
||
3332 | }else{ |
||
3333 | rc = readDbPage(pPg); |
||
3334 | if( rc==SQLITE_OK ){ |
||
3335 | pPager.xReiniter(pPg); |
||
3336 | } |
||
3337 | sqlite3PagerUnref(pPg); |
||
3338 | } |
||
3339 | } |
||
3340 | |||
3341 | /* Normally, if a transaction is rolled back, any backup processes are |
||
3342 | ** updated as data is copied out of the rollback journal and into the |
||
3343 | ** database. This is not generally possible with a WAL database, as |
||
3344 | ** rollback involves simply truncating the log file. Therefore, if one |
||
3345 | ** or more frames have already been written to the log (and therefore |
||
3346 | ** also copied into the backup databases) as part of this transaction, |
||
3347 | ** the backups must be restarted. |
||
3348 | */ |
||
3349 | sqlite3BackupRestart(pPager.pBackup); |
||
3350 | |||
3351 | return rc; |
||
3352 | } |
||
3353 | |||
3354 | /* |
||
3355 | ** This function is called to rollback a transaction on a WAL database. |
||
3356 | */ |
||
3357 | static int pagerRollbackWal(Pager *pPager){ |
||
3358 | int rc; /* Return Code */ |
||
3359 | PgHdr *pList; /* List of dirty pages to revert */ |
||
3360 | |||
3361 | /* For all pages in the cache that are currently dirty or have already |
||
3362 | ** been written (but not committed) to the log file, do one of the |
||
3363 | ** following: |
||
3364 | ** |
||
3365 | ** + Discard the cached page (if refcount==0), or |
||
3366 | ** + Reload page content from the database (if refcount>0). |
||
3367 | */ |
||
3368 | pPager.dbSize = pPager.dbOrigSize; |
||
3369 | rc = sqlite3WalUndo(pPager.pWal, pagerUndoCallback, (void *)pPager); |
||
3370 | pList = sqlite3PcacheDirtyList(pPager.pPCache); |
||
3371 | while( pList && rc==SQLITE_OK ){ |
||
3372 | PgHdr *pNext = pList->pDirty; |
||
3373 | rc = pagerUndoCallback((void *)pPager, pList->pgno); |
||
3374 | pList = pNext; |
||
3375 | } |
||
3376 | |||
3377 | return rc; |
||
3378 | } |
||
3379 | |||
3380 | |||
3381 | /* |
||
3382 | ** This function is a wrapper around sqlite3WalFrames(). As well as logging |
||
3383 | ** the contents of the list of pages headed by pList (connected by pDirty), |
||
3384 | ** this function notifies any active backup processes that the pages have |
||
3385 | ** changed. |
||
3386 | ** |
||
3387 | ** The list of pages passed into this routine is always sorted by page number. |
||
3388 | ** Hence, if page 1 appears anywhere on the list, it will be the first page. |
||
3389 | */ |
||
3390 | static int pagerWalFrames( |
||
3391 | Pager *pPager, /* Pager object */ |
||
3392 | PgHdr *pList, /* List of frames to log */ |
||
3393 | Pgno nTruncate, /* Database size after this commit */ |
||
3394 | int isCommit, /* True if this is a commit */ |
||
3395 | int syncFlags /* Flags to pass to OsSync() (or 0) */ |
||
3396 | ){ |
||
3397 | int rc; /* Return code */ |
||
3398 | #if (SQLITE_DEBUG) || (SQLITE_CHECK_PAGES) |
||
3399 | PgHdr *p; /* For looping over pages */ |
||
3400 | #endif |
||
3401 | |||
3402 | assert( pPager.pWal ); |
||
3403 | #if SQLITE_DEBUG |
||
3404 | /* Verify that the page list is in accending order */ |
||
3405 | for(p=pList; p && p->pDirty; p=p->pDirty){ |
||
3406 | assert( p->pgno < p->pDirty->pgno ); |
||
3407 | } |
||
3408 | #endif |
||
3409 | |||
3410 | if( isCommit ){ |
||
3411 | /* If a WAL transaction is being committed, there is no point in writing |
||
3412 | ** any pages with page numbers greater than nTruncate into the WAL file. |
||
3413 | ** They will never be read by any client. So remove them from the pDirty |
||
3414 | ** list here. */ |
||
3415 | PgHdr *p; |
||
3416 | PgHdr **ppNext = &pList; |
||
3417 | for(p=pList; (*ppNext = p); p=p->pDirty){ |
||
3418 | if( p->pgno<=nTruncate ) ppNext = &p->pDirty; |
||
3419 | } |
||
3420 | assert( pList ); |
||
3421 | } |
||
3422 | |||
3423 | |||
3424 | if( pList->pgno==1 ) pager_write_changecounter(pList); |
||
3425 | rc = sqlite3WalFrames(pPager.pWal, |
||
3426 | pPager.pageSize, pList, nTruncate, isCommit, syncFlags |
||
3427 | ); |
||
3428 | if( rc==SQLITE_OK && pPager.pBackup ){ |
||
3429 | PgHdr *p; |
||
3430 | for(p=pList; p; p=p->pDirty){ |
||
3431 | sqlite3BackupUpdate(pPager.pBackup, p->pgno, (u8 *)p->pData); |
||
3432 | } |
||
3433 | } |
||
3434 | |||
3435 | #if SQLITE_CHECK_PAGES |
||
3436 | pList = sqlite3PcacheDirtyList(pPager.pPCache); |
||
3437 | for(p=pList; p; p=p->pDirty){ |
||
3438 | pager_set_pagehash(p); |
||
3439 | } |
||
3440 | #endif |
||
3441 | |||
3442 | return rc; |
||
3443 | } |
||
3444 | |||
3445 | /* |
||
3446 | ** Begin a read transaction on the WAL. |
||
3447 | ** |
||
3448 | ** This routine used to be called "pagerOpenSnapshot()" because it essentially |
||
3449 | ** makes a snapshot of the database at the current point in time and preserves |
||
3450 | ** that snapshot for use by the reader in spite of concurrently changes by |
||
3451 | ** other writers or checkpointers. |
||
3452 | */ |
||
3453 | static int pagerBeginReadTransaction(Pager *pPager){ |
||
3454 | int rc; /* Return code */ |
||
3455 | int changed = 0; /* True if cache must be reset */ |
||
3456 | |||
3457 | assert( pagerUseWal(pPager) ); |
||
3458 | assert( pPager.eState==PAGER_OPEN || pPager.eState==PAGER_READER ); |
||
3459 | |||
3460 | /* sqlite3WalEndReadTransaction() was not called for the previous |
||
3461 | ** transaction in locking_mode=EXCLUSIVE. So call it now. If we |
||
3462 | ** are in locking_mode=NORMAL and EndRead() was previously called, |
||
3463 | ** the duplicate call is harmless. |
||
3464 | */ |
||
3465 | sqlite3WalEndReadTransaction(pPager.pWal); |
||
3466 | |||
3467 | rc = sqlite3WalBeginReadTransaction(pPager.pWal, &changed); |
||
3468 | if( rc!=SQLITE_OK || changed ){ |
||
3469 | pager_reset(pPager); |
||
3470 | } |
||
3471 | |||
3472 | return rc; |
||
3473 | } |
||
3474 | #endif |
||
3475 | |||
3476 | /* |
||
3477 | ** This function is called as part of the transition from PAGER_OPEN |
||
3478 | ** to PAGER_READER state to determine the size of the database file |
||
3479 | ** in pages (assuming the page size currently stored in Pager.pageSize). |
||
3480 | ** |
||
3481 | ** If no error occurs, SQLITE_OK is returned and the size of the database |
||
3482 | ** in pages is stored in *pnPage. Otherwise, an error code (perhaps |
||
3483 | ** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. |
||
3484 | */ |
||
3485 | static int pagerPagecount( Pager pPager, ref Pgno pnPage ) |
||
3486 | { |
||
3487 | Pgno nPage; /* Value to return via *pnPage */ |
||
3488 | |||
3489 | /* Query the WAL sub-system for the database size. The WalDbsize() |
||
3490 | ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or |
||
3491 | ** if the database size is not available. The database size is not |
||
3492 | ** available from the WAL sub-system if the log file is empty or |
||
3493 | ** contains no valid committed transactions. |
||
3494 | */ |
||
3495 | Debug.Assert( pPager.eState == PAGER_OPEN ); |
||
3496 | Debug.Assert( pPager.eLock >= SHARED_LOCK || pPager.noReadlock != 0 ); |
||
3497 | nPage = sqlite3WalDbsize( pPager.pWal ); |
||
3498 | |||
3499 | /* If the database size was not available from the WAL sub-system, |
||
3500 | ** determine it based on the size of the database file. If the size |
||
3501 | ** of the database file is not an integer multiple of the page-size, |
||
3502 | ** round down to the nearest page. Except, any file larger than 0 |
||
3503 | ** bytes in size is considered to contain at least one page. |
||
3504 | */ |
||
3505 | if ( nPage == 0 ) |
||
3506 | { |
||
3507 | i64 n = 0; /* Size of db file in bytes */ |
||
3508 | Debug.Assert( isOpen( pPager.fd ) || pPager.tempFile ); |
||
3509 | if ( isOpen( pPager.fd ) ) |
||
3510 | { |
||
3511 | int rc = sqlite3OsFileSize( pPager.fd, ref n ); |
||
3512 | if ( rc != SQLITE_OK ) |
||
3513 | { |
||
3514 | return rc; |
||
3515 | } |
||
3516 | } |
||
3517 | nPage = (Pgno)( n / pPager.pageSize ); |
||
3518 | if ( nPage == 0 && n > 0 ) |
||
3519 | { |
||
3520 | nPage = 1; |
||
3521 | } |
||
3522 | } |
||
3523 | |||
3524 | /* If the current number of pages in the file is greater than the |
||
3525 | ** configured maximum pager number, increase the allowed limit so |
||
3526 | ** that the file can be read. |
||
3527 | */ |
||
3528 | if ( nPage > pPager.mxPgno ) |
||
3529 | { |
||
3530 | pPager.mxPgno = (Pgno)nPage; |
||
3531 | } |
||
3532 | |||
3533 | pnPage = nPage; |
||
3534 | return SQLITE_OK; |
||
3535 | } |
||
3536 | |||
3537 | |||
3538 | #if !SQLITE_OMIT_WAL |
||
3539 | /* |
||
3540 | ** Check if the *-wal file that corresponds to the database opened by pPager |
||
3541 | ** exists if the database is not empy, or verify that the *-wal file does |
||
3542 | ** not exist (by deleting it) if the database file is empty. |
||
3543 | ** |
||
3544 | ** If the database is not empty and the *-wal file exists, open the pager |
||
3545 | ** in WAL mode. If the database is empty or if no *-wal file exists and |
||
3546 | ** if no error occurs, make sure Pager.journalMode is not set to |
||
3547 | ** PAGER_JOURNALMODE_WAL. |
||
3548 | ** |
||
3549 | ** Return SQLITE_OK or an error code. |
||
3550 | ** |
||
3551 | ** The caller must hold a SHARED lock on the database file to call this |
||
3552 | ** function. Because an EXCLUSIVE lock on the db file is required to delete |
||
3553 | ** a WAL on a none-empty database, this ensures there is no race condition |
||
3554 | ** between the xAccess() below and an xDelete() being executed by some |
||
3555 | ** other connection. |
||
3556 | */ |
||
3557 | static int pagerOpenWalIfPresent(Pager *pPager){ |
||
3558 | int rc = SQLITE_OK; |
||
3559 | Debug.Assert( pPager.eState==PAGER_OPEN ); |
||
3560 | Debug.Assert( pPager.eLock>=SHARED_LOCK || pPager.noReadlock ); |
||
3561 | |||
3562 | if( !pPager.tempFile ){ |
||
3563 | int isWal; /* True if WAL file exists */ |
||
3564 | Pgno nPage; /* Size of the database file */ |
||
3565 | |||
3566 | rc = pagerPagecount(pPager, &nPage); |
||
3567 | if( rc ) return rc; |
||
3568 | if( nPage==0 ){ |
||
3569 | rc = sqlite3OsDelete(pPager.pVfs, pPager.zWal, 0); |
||
3570 | isWal = 0; |
||
3571 | }else{ |
||
3572 | rc = sqlite3OsAccess( |
||
3573 | pPager.pVfs, pPager.zWal, SQLITE_ACCESS_EXISTS, &isWal |
||
3574 | ); |
||
3575 | } |
||
3576 | if( rc==SQLITE_OK ){ |
||
3577 | if( isWal ){ |
||
3578 | testcase( sqlite3PcachePagecount(pPager.pPCache)==0 ); |
||
3579 | rc = sqlite3PagerOpenWal(pPager, 0); |
||
3580 | }else if( pPager.journalMode==PAGER_JOURNALMODE_WAL ){ |
||
3581 | pPager.journalMode = PAGER_JOURNALMODE_DELETE; |
||
3582 | } |
||
3583 | } |
||
3584 | } |
||
3585 | return rc; |
||
3586 | } |
||
3587 | #endif |
||
3588 | |||
3589 | /* |
||
3590 | ** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback |
||
3591 | ** the entire master journal file. The case pSavepoint==NULL occurs when |
||
3592 | ** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction |
||
3593 | ** savepoint. |
||
3594 | ** |
||
3595 | ** When pSavepoint is not NULL (meaning a non-transaction savepoint is |
||
3596 | ** being rolled back), then the rollback consists of up to three stages, |
||
3597 | ** performed in the order specified: |
||
3598 | ** |
||
3599 | ** * Pages are played back from the main journal starting at byte |
||
3600 | ** offset PagerSavepoint.iOffset and continuing to |
||
3601 | ** PagerSavepoint.iHdrOffset, or to the end of the main journal |
||
3602 | ** file if PagerSavepoint.iHdrOffset is zero. |
||
3603 | ** |
||
3604 | ** * If PagerSavepoint.iHdrOffset is not zero, then pages are played |
||
3605 | ** back starting from the journal header immediately following |
||
3606 | ** PagerSavepoint.iHdrOffset to the end of the main journal file. |
||
3607 | ** |
||
3608 | ** * Pages are then played back from the sub-journal file, starting |
||
3609 | ** with the PagerSavepoint.iSubRec and continuing to the end of |
||
3610 | ** the journal file. |
||
3611 | ** |
||
3612 | ** Throughout the rollback process, each time a page is rolled back, the |
||
3613 | ** corresponding bit is set in a bitvec structure (variable pDone in the |
||
3614 | ** implementation below). This is used to ensure that a page is only |
||
3615 | ** rolled back the first time it is encountered in either journal. |
||
3616 | ** |
||
3617 | ** If pSavepoint is NULL, then pages are only played back from the main |
||
3618 | ** journal file. There is no need for a bitvec in this case. |
||
3619 | ** |
||
3620 | ** In either case, before playback commences the Pager.dbSize variable |
||
3621 | ** is reset to the value that it held at the start of the savepoint |
||
3622 | ** (or transaction). No page with a page-number greater than this value |
||
3623 | ** is played back. If one is encountered it is simply skipped. |
||
3624 | */ |
||
3625 | static int pagerPlaybackSavepoint( Pager pPager, PagerSavepoint pSavepoint ) |
||
3626 | { |
||
3627 | i64 szJ; /* Effective size of the main journal */ |
||
3628 | i64 iHdrOff; /* End of first segment of main-journal records */ |
||
3629 | int rc = SQLITE_OK; /* Return code */ |
||
3630 | Bitvec pDone = null; /* Bitvec to ensure pages played back only once */ |
||
3631 | |||
3632 | Debug.Assert( pPager.eState != PAGER_ERROR ); |
||
3633 | Debug.Assert( pPager.eState >= PAGER_WRITER_LOCKED ); |
||
3634 | |||
3635 | |||
3636 | /* Allocate a bitvec to use to store the set of pages rolled back */ |
||
3637 | if ( pSavepoint != null ) |
||
3638 | { |
||
3639 | pDone = sqlite3BitvecCreate( pSavepoint.nOrig ); |
||
3640 | //if ( null == pDone ) |
||
3641 | //{ |
||
3642 | // return SQLITE_NOMEM; |
||
3643 | //} |
||
3644 | } |
||
3645 | |||
3646 | /* Set the database size back to the value it was before the savepoint |
||
3647 | ** being reverted was opened. |
||
3648 | */ |
||
3649 | pPager.dbSize = pSavepoint != null ? pSavepoint.nOrig : pPager.dbOrigSize; |
||
3650 | pPager.changeCountDone = pPager.tempFile; |
||
3651 | |||
3652 | if ( !pSavepoint && pagerUseWal( pPager ) ) |
||
3653 | { |
||
3654 | return pagerRollbackWal( pPager ); |
||
3655 | } |
||
3656 | |||
3657 | /* Use pPager.journalOff as the effective size of the main rollback |
||
3658 | ** journal. The actual file might be larger than this in |
||
3659 | ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything |
||
3660 | ** past pPager.journalOff is off-limits to us. |
||
3661 | */ |
||
3662 | szJ = pPager.journalOff; |
||
3663 | Debug.Assert( pagerUseWal( pPager ) == false || szJ == 0 ); |
||
3664 | |||
3665 | /* Begin by rolling back records from the main journal starting at |
||
3666 | ** PagerSavepoint.iOffset and continuing to the next journal header. |
||
3667 | ** There might be records in the main journal that have a page number |
||
3668 | ** greater than the current database size (pPager.dbSize) but those |
||
3669 | ** will be skipped automatically. Pages are added to pDone as they |
||
3670 | ** are played back. |
||
3671 | */ |
||
3672 | if ( pSavepoint != null && !pagerUseWal( pPager ) ) |
||
3673 | { |
||
3674 | iHdrOff = pSavepoint.iHdrOffset != 0 ? pSavepoint.iHdrOffset : szJ; |
||
3675 | pPager.journalOff = pSavepoint.iOffset; |
||
3676 | while ( rc == SQLITE_OK && pPager.journalOff < iHdrOff ) |
||
3677 | { |
||
3678 | rc = pager_playback_one_page( pPager, ref pPager.journalOff, pDone, 1, 1 ); |
||
3679 | } |
||
3680 | Debug.Assert( rc != SQLITE_DONE ); |
||
3681 | } |
||
3682 | else |
||
3683 | { |
||
3684 | pPager.journalOff = 0; |
||
3685 | } |
||
3686 | |||
3687 | /* Continue rolling back records out of the main journal starting at |
||
3688 | ** the first journal header seen and continuing until the effective end |
||
3689 | ** of the main journal file. Continue to skip out-of-range pages and |
||
3690 | ** continue adding pages rolled back to pDone. |
||
3691 | */ |
||
3692 | while ( rc == SQLITE_OK && pPager.journalOff < szJ ) |
||
3693 | { |
||
3694 | u32 ii; /* Loop counter */ |
||
3695 | u32 nJRec; /* Number of Journal Records */ |
||
3696 | u32 dummy; |
||
3697 | rc = readJournalHdr( pPager, 0, (int)szJ, out nJRec, out dummy ); |
||
3698 | Debug.Assert( rc != SQLITE_DONE ); |
||
3699 | |||
3700 | /* |
||
3701 | ** The "pPager.journalHdr+JOURNAL_HDR_SZ(pPager)==pPager.journalOff" |
||
3702 | ** test is related to ticket #2565. See the discussion in the |
||
3703 | ** pager_playback() function for additional information. |
||
3704 | */ |
||
3705 | if ( nJRec == 0 |
||
3706 | && pPager.journalHdr + JOURNAL_HDR_SZ( pPager ) >= pPager.journalOff |
||
3707 | ) |
||
3708 | { |
||
3709 | nJRec = (u32)( ( szJ - pPager.journalOff ) / JOURNAL_PG_SZ( pPager ) ); |
||
3710 | } |
||
3711 | for ( ii = 0; rc == SQLITE_OK && ii < nJRec && pPager.journalOff < szJ; ii++ ) |
||
3712 | { |
||
3713 | rc = pager_playback_one_page( pPager, ref pPager.journalOff, pDone, 1, 1 ); |
||
3714 | } |
||
3715 | Debug.Assert( rc != SQLITE_DONE ); |
||
3716 | } |
||
3717 | Debug.Assert( rc != SQLITE_OK || pPager.journalOff >= szJ ); |
||
3718 | |||
3719 | /* Finally, rollback pages from the sub-journal. Page that were |
||
3720 | ** previously rolled back out of the main journal (and are hence in pDone) |
||
3721 | ** will be skipped. Out-of-range pages are also skipped. |
||
3722 | */ |
||
3723 | if ( pSavepoint != null ) |
||
3724 | { |
||
3725 | u32 ii; /* Loop counter */ |
||
3726 | i64 offset = pSavepoint.iSubRec * ( 4 + pPager.pageSize ); |
||
3727 | if ( pagerUseWal( pPager ) ) |
||
3728 | { |
||
3729 | rc = sqlite3WalSavepointUndo( pPager.pWal, pSavepoint.aWalData ); |
||
3730 | } |
||
3731 | for ( ii = pSavepoint.iSubRec; rc == SQLITE_OK && ii < pPager.nSubRec; ii++ ) |
||
3732 | { |
||
3733 | Debug.Assert( offset == ii * ( 4 + pPager.pageSize ) ); |
||
3734 | rc = pager_playback_one_page( pPager, ref offset, pDone, 0, 1 ); |
||
3735 | } |
||
3736 | Debug.Assert( rc != SQLITE_DONE ); |
||
3737 | } |
||
3738 | |||
3739 | sqlite3BitvecDestroy( ref pDone ); |
||
3740 | if ( rc == SQLITE_OK ) |
||
3741 | { |
||
3742 | pPager.journalOff = (int)szJ; |
||
3743 | } |
||
3744 | return rc; |
||
3745 | } |
||
3746 | |||
3747 | /* |
||
3748 | ** Change the maximum number of in-memory pages that are allowed. |
||
3749 | */ |
||
3750 | static void sqlite3PagerSetCachesize( Pager pPager, int mxPage ) |
||
3751 | { |
||
3752 | sqlite3PcacheSetCachesize( pPager.pPCache, mxPage ); |
||
3753 | } |
||
3754 | |||
3755 | /* |
||
3756 | ** Adjust the robustness of the database to damage due to OS crashes |
||
3757 | ** or power failures by changing the number of syncs()s when writing |
||
3758 | ** the rollback journal. There are three levels: |
||
3759 | ** |
||
3760 | ** OFF sqlite3OsSync() is never called. This is the default |
||
3761 | ** for temporary and transient files. |
||
3762 | ** |
||
3763 | ** NORMAL The journal is synced once before writes begin on the |
||
3764 | ** database. This is normally adequate protection, but |
||
3765 | ** it is theoretically possible, though very unlikely, |
||
3766 | ** that an inopertune power failure could leave the journal |
||
3767 | ** in a state which would cause damage to the database |
||
3768 | ** when it is rolled back. |
||
3769 | ** |
||
3770 | ** FULL The journal is synced twice before writes begin on the |
||
3771 | ** database (with some additional information - the nRec field |
||
3772 | ** of the journal header - being written in between the two |
||
3773 | ** syncs). If we assume that writing a |
||
3774 | ** single disk sector is atomic, then this mode provides |
||
3775 | ** assurance that the journal will not be corrupted to the |
||
3776 | ** point of causing damage to the database during rollback. |
||
3777 | ** |
||
3778 | ** The above is for a rollback-journal mode. For WAL mode, OFF continues |
||
3779 | ** to mean that no syncs ever occur. NORMAL means that the WAL is synced |
||
3780 | ** prior to the start of checkpoint and that the database file is synced |
||
3781 | ** at the conclusion of the checkpoint if the entire content of the WAL |
||
3782 | ** was written back into the database. But no sync operations occur for |
||
3783 | ** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL |
||
3784 | ** file is synced following each commit operation, in addition to the |
||
3785 | ** syncs associated with NORMAL. |
||
3786 | ** |
||
3787 | ** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The |
||
3788 | ** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync |
||
3789 | ** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an |
||
3790 | ** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL |
||
3791 | ** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the |
||
3792 | ** synchronous=FULL versus synchronous=NORMAL setting determines when |
||
3793 | ** the xSync primitive is called and is relevant to all platforms. |
||
3794 | ** |
||
3795 | ** Numeric values associated with these states are OFF==1, NORMAL=2, |
||
3796 | ** and FULL=3. |
||
3797 | */ |
||
3798 | #if !SQLITE_OMIT_PAGER_PRAGMAS |
||
3799 | static void sqlite3PagerSetSafetyLevel( |
||
3800 | Pager pPager, /* The pager to set safety level for */ |
||
3801 | int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ |
||
3802 | int bFullFsync, /* PRAGMA fullfsync */ |
||
3803 | int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */ |
||
3804 | ) |
||
3805 | { |
||
3806 | Debug.Assert( level >= 1 && level <= 3 ); |
||
3807 | |||
3808 | pPager.noSync = ( level == 1 || pPager.tempFile ); |
||
3809 | pPager.fullSync = ( level == 3 && !pPager.tempFile ); |
||
3810 | if ( pPager.noSync ) |
||
3811 | { |
||
3812 | pPager.syncFlags = 0; |
||
3813 | pPager.ckptSyncFlags = 0; |
||
3814 | } |
||
3815 | else if ( bFullFsync != 0 ) |
||
3816 | { |
||
3817 | pPager.syncFlags = SQLITE_SYNC_FULL; |
||
3818 | pPager.ckptSyncFlags = SQLITE_SYNC_FULL; |
||
3819 | } |
||
3820 | else if ( bCkptFullFsync != 0 ) |
||
3821 | { |
||
3822 | pPager.syncFlags = SQLITE_SYNC_NORMAL; |
||
3823 | pPager.ckptSyncFlags = SQLITE_SYNC_FULL; |
||
3824 | } |
||
3825 | else |
||
3826 | { |
||
3827 | pPager.syncFlags = SQLITE_SYNC_NORMAL; |
||
3828 | pPager.ckptSyncFlags = SQLITE_SYNC_NORMAL; |
||
3829 | } |
||
3830 | } |
||
3831 | #endif |
||
3832 | |||
3833 | /* |
||
3834 | ** The following global variable is incremented whenever the library |
||
3835 | ** attempts to open a temporary file. This information is used for |
||
3836 | ** testing and analysis only. |
||
3837 | */ |
||
3838 | #if SQLITE_TEST |
||
3839 | #if !TCLSH |
||
3840 | static int sqlite3_opentemp_count = 0; |
||
3841 | #else |
||
3842 | static tcl.lang.Var.SQLITE3_GETSET sqlite3_opentemp_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_opentemp_count" ); |
||
3843 | #endif |
||
3844 | #endif |
||
3845 | |||
3846 | /* |
||
3847 | ** Open a temporary file. |
||
3848 | ** |
||
3849 | ** Write the file descriptor into *pFile. Return SQLITE_OK on success |
||
3850 | ** or some other error code if we fail. The OS will automatically |
||
3851 | ** delete the temporary file when it is closed. |
||
3852 | ** |
||
3853 | ** The flags passed to the VFS layer xOpen() call are those specified |
||
3854 | ** by parameter vfsFlags ORed with the following: |
||
3855 | ** |
||
3856 | ** SQLITE_OPEN_READWRITE |
||
3857 | ** SQLITE_OPEN_CREATE |
||
3858 | ** SQLITE_OPEN_EXCLUSIVE |
||
3859 | ** SQLITE_OPEN_DELETEONCLOSE |
||
3860 | */ |
||
3861 | static int pagerOpentemp( |
||
3862 | Pager pPager, /* The pager object */ |
||
3863 | ref sqlite3_file pFile, /* Write the file descriptor here */ |
||
3864 | int vfsFlags /* Flags passed through to the VFS */ |
||
3865 | ) |
||
3866 | { |
||
3867 | int rc; /* Return code */ |
||
3868 | |||
3869 | #if SQLITE_TEST |
||
3870 | #if !TCLSH |
||
3871 | sqlite3_opentemp_count++; /* Used for testing and analysis only */ |
||
3872 | #else |
||
3873 | sqlite3_opentemp_count.iValue++; /* Used for testing and analysis only */ |
||
3874 | #endif |
||
3875 | #endif |
||
3876 | |||
3877 | vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | |
||
3878 | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; |
||
3879 | int dummy = 0; |
||
3880 | rc = sqlite3OsOpen( pPager.pVfs, null, pFile, vfsFlags, ref dummy ); |
||
3881 | Debug.Assert( rc != SQLITE_OK || isOpen( pFile ) ); |
||
3882 | return rc; |
||
3883 | } |
||
3884 | |||
3885 | /* |
||
3886 | ** Set the busy handler function. |
||
3887 | ** |
||
3888 | ** The pager invokes the busy-handler if sqlite3OsLock() returns |
||
3889 | ** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock, |
||
3890 | ** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE |
||
3891 | ** lock. It does *not* invoke the busy handler when upgrading from |
||
3892 | ** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE |
||
3893 | ** (which occurs during hot-journal rollback). Summary: |
||
3894 | ** |
||
3895 | ** Transition | Invokes xBusyHandler |
||
3896 | ** -------------------------------------------------------- |
||
3897 | ** NO_LOCK . SHARED_LOCK | Yes |
||
3898 | ** SHARED_LOCK . RESERVED_LOCK | No |
||
3899 | ** SHARED_LOCK . EXCLUSIVE_LOCK | No |
||
3900 | ** RESERVED_LOCK . EXCLUSIVE_LOCK | Yes |
||
3901 | ** |
||
3902 | ** If the busy-handler callback returns non-zero, the lock is |
||
3903 | ** retried. If it returns zero, then the SQLITE_BUSY error is |
||
3904 | ** returned to the caller of the pager API function. |
||
3905 | */ |
||
3906 | |||
3907 | static void sqlite3PagerSetBusyhandler( |
||
3908 | Pager pPager, /* Pager object */ |
||
3909 | dxBusyHandler xBusyHandler, /* Pointer to busy-handler function */ |
||
3910 | //int (*xBusyHandler)(void *), |
||
3911 | object pBusyHandlerArg /* Argument to pass to xBusyHandler */ |
||
3912 | ) |
||
3913 | { |
||
3914 | pPager.xBusyHandler = xBusyHandler; |
||
3915 | pPager.pBusyHandlerArg = pBusyHandlerArg; |
||
3916 | } |
||
3917 | |||
3918 | |||
3919 | /* |
||
3920 | ** Change the page size used by the Pager object. The new page size |
||
3921 | ** is passed in *pPageSize. |
||
3922 | ** |
||
3923 | ** If the pager is in the error state when this function is called, it |
||
3924 | ** is a no-op. The value returned is the error state error code (i.e. |
||
3925 | ** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). |
||
3926 | ** |
||
3927 | ** Otherwise, if all of the following are true: |
||
3928 | ** |
||
3929 | ** * the new page size (value of *pPageSize) is valid (a power |
||
3930 | ** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and |
||
3931 | ** |
||
3932 | ** * there are no outstanding page references, and |
||
3933 | ** |
||
3934 | ** * the database is either not an in-memory database or it is |
||
3935 | ** an in-memory database that currently consists of zero pages. |
||
3936 | ** |
||
3937 | ** then the pager object page size is set to *pPageSize. |
||
3938 | ** |
||
3939 | ** If the page size is changed, then this function uses sqlite3PagerMalloc() |
||
3940 | ** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt |
||
3941 | ** fails, SQLITE_NOMEM is returned and the page size remains unchanged. |
||
3942 | ** In all other cases, SQLITE_OK is returned. |
||
3943 | ** |
||
3944 | ** If the page size is not changed, either because one of the enumerated |
||
3945 | ** conditions above is not true, the pager was in error state when this |
||
3946 | ** function was called, or because the memory allocation attempt failed, |
||
3947 | ** then *pPageSize is set to the old, retained page size before returning. |
||
3948 | */ |
||
3949 | static int sqlite3PagerSetPagesize( Pager pPager, ref u32 pPageSize, int nReserve ) |
||
3950 | { |
||
3951 | int rc = SQLITE_OK; |
||
3952 | /* It is not possible to do a full assert_pager_state() here, as this |
||
3953 | ** function may be called from within PagerOpen(), before the state |
||
3954 | ** of the Pager object is internally consistent. |
||
3955 | ** |
||
3956 | ** At one point this function returned an error if the pager was in |
||
3957 | ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that |
||
3958 | ** there is at least one outstanding page reference, this function |
||
3959 | ** is a no-op for that case anyhow. |
||
3960 | */ |
||
3961 | |||
3962 | u32 pageSize = pPageSize; |
||
3963 | Debug.Assert( pageSize == 0 || ( pageSize >= 512 && pageSize <= SQLITE_MAX_PAGE_SIZE ) ); |
||
3964 | if ( ( pPager.memDb == 0 || pPager.dbSize == 0 ) |
||
3965 | && sqlite3PcacheRefCount( pPager.pPCache ) == 0 |
||
3966 | && pageSize != 0 && pageSize != (u32)pPager.pageSize |
||
3967 | ) |
||
3968 | { |
||
3969 | //char *pNew = NULL; /* New temp space */ |
||
3970 | i64 nByte = 0; |
||
3971 | |||
3972 | if ( pPager.eState > PAGER_OPEN && isOpen( pPager.fd ) ) |
||
3973 | { |
||
3974 | rc = sqlite3OsFileSize( pPager.fd, ref nByte ); |
||
3975 | } |
||
3976 | //if ( rc == SQLITE_OK ) |
||
3977 | //{ |
||
3978 | //pNew = (char *)sqlite3PageMalloc(pageSize); |
||
3979 | //if( !pNew ) rc = SQLITE_NOMEM; |
||
3980 | //} |
||
3981 | if ( rc == SQLITE_OK ) |
||
3982 | { |
||
3983 | pager_reset( pPager ); |
||
3984 | pPager.dbSize = (Pgno)( nByte / pageSize ); |
||
3985 | pPager.pageSize = (int)pageSize; |
||
3986 | sqlite3PageFree( ref pPager.pTmpSpace ); |
||
3987 | |||
3988 | pPager.pTmpSpace = sqlite3Malloc( pageSize );// pNew; |
||
3989 | sqlite3PcacheSetPageSize( pPager.pPCache, (int)pageSize ); |
||
3990 | } |
||
3991 | } |
||
3992 | pPageSize = (u32)pPager.pageSize; |
||
3993 | if ( rc == SQLITE_OK ) |
||
3994 | { |
||
3995 | if ( nReserve < 0 ) |
||
3996 | nReserve = pPager.nReserve; |
||
3997 | Debug.Assert( nReserve >= 0 && nReserve < 1000 ); |
||
3998 | pPager.nReserve = (i16)nReserve; |
||
3999 | pagerReportSize( pPager ); |
||
4000 | } |
||
4001 | return rc; |
||
4002 | } |
||
4003 | |||
4004 | /* |
||
4005 | ** Return a pointer to the "temporary page" buffer held internally |
||
4006 | ** by the pager. This is a buffer that is big enough to hold the |
||
4007 | ** entire content of a database page. This buffer is used internally |
||
4008 | ** during rollback and will be overwritten whenever a rollback |
||
4009 | ** occurs. But other modules are free to use it too, as long as |
||
4010 | ** no rollbacks are happening. |
||
4011 | */ |
||
4012 | static byte[] sqlite3PagerTempSpace( Pager pPager ) |
||
4013 | { |
||
4014 | return pPager.pTmpSpace; |
||
4015 | } |
||
4016 | |||
4017 | /* |
||
4018 | ** Attempt to set the maximum database page count if mxPage is positive. |
||
4019 | ** Make no changes if mxPage is zero or negative. And never reduce the |
||
4020 | ** maximum page count below the current size of the database. |
||
4021 | ** |
||
4022 | ** Regardless of mxPage, return the current maximum page count. |
||
4023 | */ |
||
4024 | static Pgno sqlite3PagerMaxPageCount( Pager pPager, int mxPage ) |
||
4025 | { |
||
4026 | if ( mxPage > 0 ) |
||
4027 | { |
||
4028 | pPager.mxPgno = (Pgno)mxPage; |
||
4029 | } |
||
4030 | Debug.Assert( pPager.eState != PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ |
||
4031 | Debug.Assert( pPager.mxPgno >= pPager.dbSize ); /* OP_MaxPgcnt enforces this */ |
||
4032 | return pPager.mxPgno; |
||
4033 | } |
||
4034 | |||
4035 | /* |
||
4036 | ** The following set of routines are used to disable the simulated |
||
4037 | ** I/O error mechanism. These routines are used to avoid simulated |
||
4038 | ** errors in places where we do not care about errors. |
||
4039 | ** |
||
4040 | ** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops |
||
4041 | ** and generate no code. |
||
4042 | */ |
||
4043 | #if SQLITE_TEST |
||
4044 | //extern int sqlite3_io_error_pending; |
||
4045 | //extern int sqlite3_io_error_hit; |
||
4046 | static int saved_cnt; |
||
4047 | static void disable_simulated_io_errors() |
||
4048 | { |
||
4049 | #if !TCLSH |
||
4050 | saved_cnt = sqlite3_io_error_pending; |
||
4051 | sqlite3_io_error_pending = -1; |
||
4052 | #else |
||
4053 | saved_cnt = sqlite3_io_error_pending.iValue; |
||
4054 | sqlite3_io_error_pending.iValue = -1; |
||
4055 | #endif |
||
4056 | } |
||
4057 | |||
4058 | static void enable_simulated_io_errors() |
||
4059 | { |
||
4060 | #if !TCLSH |
||
4061 | sqlite3_io_error_pending = saved_cnt; |
||
4062 | #else |
||
4063 | sqlite3_io_error_pending.iValue = saved_cnt; |
||
4064 | #endif |
||
4065 | } |
||
4066 | #else |
||
4067 | //# define disable_simulated_io_errors() |
||
4068 | //# define enable_simulated_io_errors() |
||
4069 | #endif |
||
4070 | |||
4071 | /* |
||
4072 | ** Read the first N bytes from the beginning of the file into memory |
||
4073 | ** that pDest points to. |
||
4074 | ** |
||
4075 | ** If the pager was opened on a transient file (zFilename==""), or |
||
4076 | ** opened on a file less than N bytes in size, the output buffer is |
||
4077 | ** zeroed and SQLITE_OK returned. The rationale for this is that this |
||
4078 | ** function is used to read database headers, and a new transient or |
||
4079 | ** zero sized database has a header than consists entirely of zeroes. |
||
4080 | ** |
||
4081 | ** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered, |
||
4082 | ** the error code is returned to the caller and the contents of the |
||
4083 | ** output buffer undefined. |
||
4084 | */ |
||
4085 | static int sqlite3PagerReadFileheader( Pager pPager, int N, byte[] pDest ) |
||
4086 | { |
||
4087 | int rc = SQLITE_OK; |
||
4088 | Array.Clear( pDest, 0, N ); //memset(pDest, 0, N); |
||
4089 | Debug.Assert( isOpen( pPager.fd ) || pPager.tempFile ); |
||
4090 | |||
4091 | /* This routine is only called by btree immediately after creating |
||
4092 | ** the Pager object. There has not been an opportunity to transition |
||
4093 | ** to WAL mode yet. |
||
4094 | */ |
||
4095 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
4096 | |||
4097 | if ( isOpen( pPager.fd ) ) |
||
4098 | { |
||
4099 | IOTRACE( "DBHDR %p 0 %d\n", pPager, N ); |
||
4100 | rc = sqlite3OsRead( pPager.fd, pDest, N, 0 ); |
||
4101 | if ( rc == SQLITE_IOERR_SHORT_READ ) |
||
4102 | { |
||
4103 | rc = SQLITE_OK; |
||
4104 | } |
||
4105 | } |
||
4106 | return rc; |
||
4107 | } |
||
4108 | |||
4109 | /* |
||
4110 | ** This function may only be called when a read-transaction is open on |
||
4111 | ** the pager. It returns the total number of pages in the database. |
||
4112 | ** |
||
4113 | ** However, if the file is between 1 and <page-size> bytes in size, then |
||
4114 | ** this is considered a 1 page file. |
||
4115 | */ |
||
4116 | static void sqlite3PagerPagecount( Pager pPager, out Pgno pnPage ) |
||
4117 | { |
||
4118 | Debug.Assert( pPager.eState >= PAGER_READER ); |
||
4119 | Debug.Assert( pPager.eState != PAGER_WRITER_FINISHED ); |
||
4120 | pnPage = pPager.dbSize; |
||
4121 | } |
||
4122 | |||
4123 | /* |
||
4124 | ** Try to obtain a lock of type locktype on the database file. If |
||
4125 | ** a similar or greater lock is already held, this function is a no-op |
||
4126 | ** (returning SQLITE_OK immediately). |
||
4127 | ** |
||
4128 | ** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke |
||
4129 | ** the busy callback if the lock is currently not available. Repeat |
||
4130 | ** until the busy callback returns false or until the attempt to |
||
4131 | ** obtain the lock succeeds. |
||
4132 | ** |
||
4133 | ** Return SQLITE_OK on success and an error code if we cannot obtain |
||
4134 | ** the lock. If the lock is obtained successfully, set the Pager.state |
||
4135 | ** variable to locktype before returning. |
||
4136 | */ |
||
4137 | static int pager_wait_on_lock( Pager pPager, int locktype ) |
||
4138 | { |
||
4139 | int rc; /* Return code */ |
||
4140 | |||
4141 | /* Check that this is either a no-op (because the requested lock is |
||
4142 | ** already held, or one of the transistions that the busy-handler |
||
4143 | ** may be invoked during, according to the comment above |
||
4144 | ** sqlite3PagerSetBusyhandler(). |
||
4145 | */ |
||
4146 | Debug.Assert( ( pPager.eLock >= locktype ) |
||
4147 | || ( pPager.eLock == NO_LOCK && locktype == SHARED_LOCK ) |
||
4148 | || ( pPager.eLock == RESERVED_LOCK && locktype == EXCLUSIVE_LOCK ) |
||
4149 | ); |
||
4150 | |||
4151 | do |
||
4152 | { |
||
4153 | rc = pagerLockDb( pPager, locktype ); |
||
4154 | } while ( rc == SQLITE_BUSY && pPager.xBusyHandler( pPager.pBusyHandlerArg ) != 0 ); |
||
4155 | return rc; |
||
4156 | } |
||
4157 | |||
4158 | /* |
||
4159 | ** Function assertTruncateConstraint(pPager) checks that one of the |
||
4160 | ** following is true for all dirty pages currently in the page-cache: |
||
4161 | ** |
||
4162 | ** a) The page number is less than or equal to the size of the |
||
4163 | ** current database image, in pages, OR |
||
4164 | ** |
||
4165 | ** b) if the page content were written at this time, it would not |
||
4166 | ** be necessary to write the current content out to the sub-journal |
||
4167 | ** (as determined by function subjRequiresPage()). |
||
4168 | ** |
||
4169 | ** If the condition asserted by this function were not true, and the |
||
4170 | ** dirty page were to be discarded from the cache via the pagerStress() |
||
4171 | ** routine, pagerStress() would not write the current page content to |
||
4172 | ** the database file. If a savepoint transaction were rolled back after |
||
4173 | ** this happened, the correct behaviour would be to restore the current |
||
4174 | ** content of the page. However, since this content is not present in either |
||
4175 | ** the database file or the portion of the rollback journal and |
||
4176 | ** sub-journal rolled back the content could not be restored and the |
||
4177 | ** database image would become corrupt. It is therefore fortunate that |
||
4178 | ** this circumstance cannot arise. |
||
4179 | */ |
||
4180 | #if SQLITE_DEBUG |
||
4181 | static void assertTruncateConstraintCb( PgHdr pPg ) |
||
4182 | { |
||
4183 | Debug.Assert( ( pPg.flags & PGHDR_DIRTY ) != 0 ); |
||
4184 | Debug.Assert( !subjRequiresPage( pPg ) || pPg.pgno <= pPg.pPager.dbSize ); |
||
4185 | } |
||
4186 | static void assertTruncateConstraint( Pager pPager ) |
||
4187 | { |
||
4188 | sqlite3PcacheIterateDirty( pPager.pPCache, assertTruncateConstraintCb ); |
||
4189 | } |
||
4190 | #else |
||
4191 | //# define assertTruncateConstraint(pPager) |
||
4192 | static void assertTruncateConstraintCb(PgHdr pPg) { } |
||
4193 | static void assertTruncateConstraint(Pager pPager) { } |
||
4194 | #endif |
||
4195 | |||
4196 | /* |
||
4197 | ** Truncate the in-memory database file image to nPage pages. This |
||
4198 | ** function does not actually modify the database file on disk. It |
||
4199 | ** just sets the internal state of the pager object so that the |
||
4200 | ** truncation will be done when the current transaction is committed. |
||
4201 | */ |
||
4202 | static void sqlite3PagerTruncateImage( Pager pPager, u32 nPage ) |
||
4203 | { |
||
4204 | Debug.Assert( pPager.dbSize >= nPage ); |
||
4205 | Debug.Assert( pPager.eState >= PAGER_WRITER_CACHEMOD ); |
||
4206 | pPager.dbSize = nPage; |
||
4207 | assertTruncateConstraint( pPager ); |
||
4208 | } |
||
4209 | |||
4210 | |||
4211 | /* |
||
4212 | ** This function is called before attempting a hot-journal rollback. It |
||
4213 | ** syncs the journal file to disk, then sets pPager.journalHdr to the |
||
4214 | ** size of the journal file so that the pager_playback() routine knows |
||
4215 | ** that the entire journal file has been synced. |
||
4216 | ** |
||
4217 | ** Syncing a hot-journal to disk before attempting to roll it back ensures |
||
4218 | ** that if a power-failure occurs during the rollback, the process that |
||
4219 | ** attempts rollback following system recovery sees the same journal |
||
4220 | ** content as this process. |
||
4221 | ** |
||
4222 | ** If everything goes as planned, SQLITE_OK is returned. Otherwise, |
||
4223 | ** an SQLite error code. |
||
4224 | */ |
||
4225 | static int pagerSyncHotJournal( Pager pPager ) |
||
4226 | { |
||
4227 | int rc = SQLITE_OK; |
||
4228 | if ( !pPager.noSync ) |
||
4229 | { |
||
4230 | rc = sqlite3OsSync( pPager.jfd, SQLITE_SYNC_NORMAL ); |
||
4231 | } |
||
4232 | if ( rc == SQLITE_OK ) |
||
4233 | { |
||
4234 | rc = sqlite3OsFileSize( pPager.jfd, ref pPager.journalHdr ); |
||
4235 | } |
||
4236 | return rc; |
||
4237 | } |
||
4238 | |||
4239 | /* |
||
4240 | ** Shutdown the page cache. Free all memory and close all files. |
||
4241 | ** |
||
4242 | ** If a transaction was in progress when this routine is called, that |
||
4243 | ** transaction is rolled back. All outstanding pages are invalidated |
||
4244 | ** and their memory is freed. Any attempt to use a page associated |
||
4245 | ** with this page cache after this function returns will likely |
||
4246 | ** result in a coredump. |
||
4247 | ** |
||
4248 | ** This function always succeeds. If a transaction is active an attempt |
||
4249 | ** is made to roll it back. If an error occurs during the rollback |
||
4250 | ** a hot journal may be left in the filesystem but no error is returned |
||
4251 | ** to the caller. |
||
4252 | */ |
||
4253 | static int sqlite3PagerClose( Pager pPager ) |
||
4254 | { |
||
4255 | #if SQLITE_TEST |
||
4256 | disable_simulated_io_errors(); |
||
4257 | #endif |
||
4258 | sqlite3BeginBenignMalloc(); |
||
4259 | /* pPager.errCode = 0; */ |
||
4260 | pPager.exclusiveMode = false; |
||
4261 | #if !SQLITE_OMIT_WAL |
||
4262 | u8[] pTmp = pPager.pTmpSpace; |
||
4263 | sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); |
||
4264 | pPager.pWal = 0; |
||
4265 | #endif |
||
4266 | pager_reset( pPager ); |
||
4267 | |||
4268 | #if SQLITE_OMIT_MEMORYDB |
||
4269 | if ( 1 == MEMDB ) |
||
4270 | #else |
||
4271 | if ( 1 == pPager.memDb ) |
||
4272 | #endif |
||
4273 | { |
||
4274 | pager_unlock( pPager ); |
||
4275 | } |
||
4276 | else |
||
4277 | { |
||
4278 | /* If it is open, sync the journal file before calling UnlockAndRollback. |
||
4279 | ** If this is not done, then an unsynced portion of the open journal |
||
4280 | ** file may be played back into the database. If a power failure occurs |
||
4281 | ** while this is happening, the database could become corrupt. |
||
4282 | ** |
||
4283 | ** If an error occurs while trying to sync the journal, shift the pager |
||
4284 | ** into the ERROR state. This causes UnlockAndRollback to unlock the |
||
4285 | ** database and close the journal file without attempting to roll it |
||
4286 | ** back or finalize it. The next database user will have to do hot-journal |
||
4287 | ** rollback before accessing the database file. |
||
4288 | */ |
||
4289 | if ( isOpen( pPager.jfd ) ) |
||
4290 | { |
||
4291 | pager_error( pPager, pagerSyncHotJournal( pPager ) ); |
||
4292 | } |
||
4293 | pagerUnlockAndRollback( pPager ); |
||
4294 | } |
||
4295 | sqlite3EndBenignMalloc(); |
||
4296 | #if SQLITE_TEST |
||
4297 | enable_simulated_io_errors(); |
||
4298 | #endif |
||
4299 | |||
4300 | PAGERTRACE( "CLOSE %d\n", PAGERID( pPager ) ); |
||
4301 | IOTRACE( "CLOSE %p\n", pPager ); |
||
4302 | sqlite3OsClose( pPager.jfd ); |
||
4303 | sqlite3OsClose( pPager.fd ); |
||
4304 | //sqlite3_free( ref pTmp ); |
||
4305 | sqlite3PcacheClose( pPager.pPCache ); |
||
4306 | |||
4307 | #if SQLITE_HAS_CODEC |
||
4308 | if ( pPager.xCodecFree != null ) |
||
4309 | pPager.xCodecFree( ref pPager.pCodec ); |
||
4310 | #endif |
||
4311 | Debug.Assert( null == pPager.aSavepoint && !pPager.pInJournal ); |
||
4312 | Debug.Assert( !isOpen( pPager.jfd ) && !isOpen( pPager.sjfd ) ); |
||
4313 | |||
4314 | //sqlite3_free( ref pPager ); |
||
4315 | return SQLITE_OK; |
||
4316 | } |
||
4317 | |||
4318 | #if !NDEBUG || SQLITE_TEST |
||
4319 | /* |
||
4320 | ** Return the page number for page pPg. |
||
4321 | */ |
||
4322 | static Pgno sqlite3PagerPagenumber( DbPage pPg ) |
||
4323 | { |
||
4324 | return pPg.pgno; |
||
4325 | } |
||
4326 | #else |
||
4327 | static Pgno sqlite3PagerPagenumber( DbPage pPg ) { return pPg.pgno; } |
||
4328 | #endif |
||
4329 | |||
4330 | |||
4331 | /* |
||
4332 | ** Increment the reference count for page pPg. |
||
4333 | */ |
||
4334 | static void sqlite3PagerRef( DbPage pPg ) |
||
4335 | { |
||
4336 | sqlite3PcacheRef( pPg ); |
||
4337 | } |
||
4338 | |||
4339 | /* |
||
4340 | ** Sync the journal. In other words, make sure all the pages that have |
||
4341 | ** been written to the journal have actually reached the surface of the |
||
4342 | ** disk and can be restored in the event of a hot-journal rollback. |
||
4343 | ** |
||
4344 | ** If the Pager.noSync flag is set, then this function is a no-op. |
||
4345 | ** Otherwise, the actions required depend on the journal-mode and the |
||
4346 | ** device characteristics of the the file-system, as follows: |
||
4347 | ** |
||
4348 | ** * If the journal file is an in-memory journal file, no action need |
||
4349 | ** be taken. |
||
4350 | ** |
||
4351 | ** * Otherwise, if the device does not support the SAFE_APPEND property, |
||
4352 | ** then the nRec field of the most recently written journal header |
||
4353 | ** is updated to contain the number of journal records that have |
||
4354 | ** been written following it. If the pager is operating in full-sync |
||
4355 | ** mode, then the journal file is synced before this field is updated. |
||
4356 | ** |
||
4357 | ** * If the device does not support the SEQUENTIAL property, then |
||
4358 | ** journal file is synced. |
||
4359 | ** |
||
4360 | ** Or, in pseudo-code: |
||
4361 | ** |
||
4362 | ** if( NOT <in-memory journal> ){ |
||
4363 | ** if( NOT SAFE_APPEND ){ |
||
4364 | ** if( <full-sync mode> ) xSync(<journal file>); |
||
4365 | ** <update nRec field> |
||
4366 | ** } |
||
4367 | ** if( NOT SEQUENTIAL ) xSync(<journal file>); |
||
4368 | ** } |
||
4369 | ** |
||
4370 | ** If successful, this routine clears the PGHDR_NEED_SYNC flag of every |
||
4371 | ** page currently held in memory before returning SQLITE_OK. If an IO |
||
4372 | ** error is encountered, then the IO error code is returned to the caller. |
||
4373 | */ |
||
4374 | static int syncJournal( Pager pPager, int newHdr ) |
||
4375 | { |
||
4376 | int rc = SQLITE_OK; |
||
4377 | Debug.Assert( pPager.eState == PAGER_WRITER_CACHEMOD |
||
4378 | || pPager.eState == PAGER_WRITER_DBMOD |
||
4379 | ); |
||
4380 | Debug.Assert( assert_pager_state( pPager ) ); |
||
4381 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
4382 | |||
4383 | rc = sqlite3PagerExclusiveLock( pPager ); |
||
4384 | if ( rc != SQLITE_OK ) |
||
4385 | return rc; |
||
4386 | |||
4387 | if ( !pPager.noSync ) |
||
4388 | { |
||
4389 | Debug.Assert( !pPager.tempFile ); |
||
4390 | if ( isOpen( pPager.jfd ) && pPager.journalMode != PAGER_JOURNALMODE_MEMORY ) |
||
4391 | { |
||
4392 | int iDc = sqlite3OsDeviceCharacteristics( pPager.fd ); |
||
4393 | Debug.Assert( isOpen( pPager.jfd ) ); |
||
4394 | |||
4395 | if ( 0 == ( iDc & SQLITE_IOCAP_SAFE_APPEND ) ) |
||
4396 | { |
||
4397 | /* This block deals with an obscure problem. If the last connection |
||
4398 | ** that wrote to this database was operating in persistent-journal |
||
4399 | ** mode, then the journal file may at this point actually be larger |
||
4400 | ** than Pager.journalOff bytes. If the next thing in the journal |
||
4401 | ** file happens to be a journal-header (written as part of the |
||
4402 | ** previous connection's transaction), and a crash or power-failure |
||
4403 | ** occurs after nRec is updated but before this connection writes |
||
4404 | ** anything else to the journal file (or commits/rolls back its |
||
4405 | ** transaction), then SQLite may become confused when doing the |
||
4406 | ** hot-journal rollback following recovery. It may roll back all |
||
4407 | ** of this connections data, then proceed to rolling back the old, |
||
4408 | ** out-of-date data that follows it. Database corruption. |
||
4409 | ** |
||
4410 | ** To work around this, if the journal file does appear to contain |
||
4411 | ** a valid header following Pager.journalOff, then write a 0x00 |
||
4412 | ** byte to the start of it to prevent it from being recognized. |
||
4413 | ** |
||
4414 | ** Variable iNextHdrOffset is set to the offset at which this |
||
4415 | ** problematic header will occur, if it exists. aMagic is used |
||
4416 | ** as a temporary buffer to inspect the first couple of bytes of |
||
4417 | ** the potential journal header. |
||
4418 | */ |
||
4419 | i64 iNextHdrOffset; |
||
4420 | u8[] aMagic = new u8[8]; |
||
4421 | u8[] zHeader = new u8[aJournalMagic.Length + 4]; |
||
4422 | aJournalMagic.CopyTo( zHeader, 0 );// memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); |
||
4423 | put32bits( zHeader, aJournalMagic.Length, pPager.nRec ); |
||
4424 | iNextHdrOffset = journalHdrOffset( pPager ); |
||
4425 | rc = sqlite3OsRead( pPager.jfd, aMagic, 8, iNextHdrOffset ); |
||
4426 | if ( rc == SQLITE_OK && 0 == memcmp( aMagic, aJournalMagic, 8 ) ) |
||
4427 | { |
||
4428 | u8[] zerobyte = new u8[1]; |
||
4429 | rc = sqlite3OsWrite( pPager.jfd, zerobyte, 1, iNextHdrOffset ); |
||
4430 | } |
||
4431 | if ( rc != SQLITE_OK && rc != SQLITE_IOERR_SHORT_READ ) |
||
4432 | { |
||
4433 | return rc; |
||
4434 | } |
||
4435 | |||
4436 | /* Write the nRec value into the journal file header. If in |
||
4437 | ** full-synchronous mode, sync the journal first. This ensures that |
||
4438 | ** all data has really hit the disk before nRec is updated to mark |
||
4439 | ** it as a candidate for rollback. |
||
4440 | ** |
||
4441 | ** This is not required if the persistent media supports the |
||
4442 | ** SAFE_APPEND property. Because in this case it is not possible |
||
4443 | ** for garbage data to be appended to the file, the nRec field |
||
4444 | ** is populated with 0xFFFFFFFF when the journal header is written |
||
4445 | ** and never needs to be updated. |
||
4446 | */ |
||
4447 | if ( pPager.fullSync && 0 == ( iDc & SQLITE_IOCAP_SEQUENTIAL ) ) |
||
4448 | { |
||
4449 | |||
4450 | PAGERTRACE( "SYNC journal of %d\n", PAGERID( pPager ) ); |
||
4451 | IOTRACE( "JSYNC %p\n", pPager ); |
||
4452 | rc = sqlite3OsSync( pPager.jfd, pPager.syncFlags ); |
||
4453 | if ( rc != SQLITE_OK ) |
||
4454 | return rc; |
||
4455 | } |
||
4456 | IOTRACE( "JHDR %p %lld\n", pPager, pPager.journalHdr ); |
||
4457 | rc = sqlite3OsWrite( |
||
4458 | pPager.jfd, zHeader, zHeader.Length, pPager.journalHdr |
||
4459 | ); |
||
4460 | if ( rc != SQLITE_OK ) |
||
4461 | return rc; |
||
4462 | } |
||
4463 | if ( 0 == ( iDc & SQLITE_IOCAP_SEQUENTIAL ) ) |
||
4464 | { |
||
4465 | |||
4466 | PAGERTRACE( "SYNC journal of %d\n", PAGERID( pPager ) ); |
||
4467 | IOTRACE( "JSYNC %p\n", pPager ); |
||
4468 | rc = sqlite3OsSync( pPager.jfd, pPager.syncFlags | |
||
4469 | ( pPager.syncFlags == SQLITE_SYNC_FULL ? SQLITE_SYNC_DATAONLY : 0 ) |
||
4470 | ); |
||
4471 | if ( rc != SQLITE_OK ) |
||
4472 | return rc; |
||
4473 | } |
||
4474 | pPager.journalHdr = pPager.journalOff; |
||
4475 | if ( newHdr != 0 && 0 == ( iDc & SQLITE_IOCAP_SAFE_APPEND ) ) |
||
4476 | { |
||
4477 | pPager.nRec = 0; |
||
4478 | rc = writeJournalHdr( pPager ); |
||
4479 | if ( rc != SQLITE_OK ) |
||
4480 | return rc; |
||
4481 | } |
||
4482 | } |
||
4483 | else |
||
4484 | { |
||
4485 | pPager.journalHdr = pPager.journalOff; |
||
4486 | } |
||
4487 | } |
||
4488 | /* Unless the pager is in noSync mode, the journal file was just |
||
4489 | ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on |
||
4490 | ** all pages. |
||
4491 | */ |
||
4492 | sqlite3PcacheClearSyncFlags( pPager.pPCache ); |
||
4493 | pPager.eState = PAGER_WRITER_DBMOD; |
||
4494 | Debug.Assert( assert_pager_state( pPager ) ); |
||
4495 | return SQLITE_OK; |
||
4496 | } |
||
4497 | |||
4498 | /* |
||
4499 | ** The argument is the first in a linked list of dirty pages connected |
||
4500 | ** by the PgHdr.pDirty pointer. This function writes each one of the |
||
4501 | ** in-memory pages in the list to the database file. The argument may |
||
4502 | ** be NULL, representing an empty list. In this case this function is |
||
4503 | ** a no-op. |
||
4504 | ** |
||
4505 | ** The pager must hold at least a RESERVED lock when this function |
||
4506 | ** is called. Before writing anything to the database file, this lock |
||
4507 | ** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained, |
||
4508 | ** SQLITE_BUSY is returned and no data is written to the database file. |
||
4509 | ** |
||
4510 | ** If the pager is a temp-file pager and the actual file-system file |
||
4511 | ** is not yet open, it is created and opened before any data is |
||
4512 | ** written out. |
||
4513 | ** |
||
4514 | ** Once the lock has been upgraded and, if necessary, the file opened, |
||
4515 | ** the pages are written out to the database file in list order. Writing |
||
4516 | ** a page is skipped if it meets either of the following criteria: |
||
4517 | ** |
||
4518 | ** * The page number is greater than Pager.dbSize, or |
||
4519 | ** * The PGHDR_DONT_WRITE flag is set on the page. |
||
4520 | ** |
||
4521 | ** If writing out a page causes the database file to grow, Pager.dbFileSize |
||
4522 | ** is updated accordingly. If page 1 is written out, then the value cached |
||
4523 | ** in Pager.dbFileVers[] is updated to match the new value stored in |
||
4524 | ** the database file. |
||
4525 | ** |
||
4526 | ** If everything is successful, SQLITE_OK is returned. If an IO error |
||
4527 | ** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot |
||
4528 | ** be obtained, SQLITE_BUSY is returned. |
||
4529 | */ |
||
4530 | static int pager_write_pagelist( Pager pPager, PgHdr pList ) |
||
4531 | { |
||
4532 | int rc = SQLITE_OK; /* Return code */ |
||
4533 | |||
4534 | /* This function is only called for rollback pagers in WRITER_DBMOD state. */ |
||
4535 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
4536 | Debug.Assert( pPager.eState == PAGER_WRITER_DBMOD ); |
||
4537 | Debug.Assert( pPager.eLock == EXCLUSIVE_LOCK ); |
||
4538 | /* If the file is a temp-file has not yet been opened, open it now. It |
||
4539 | ** is not possible for rc to be other than SQLITE_OK if this branch |
||
4540 | ** is taken, as pager_wait_on_lock() is a no-op for temp-files. |
||
4541 | */ |
||
4542 | if ( !isOpen( pPager.fd ) ) |
||
4543 | { |
||
4544 | Debug.Assert( pPager.tempFile && rc == SQLITE_OK ); |
||
4545 | rc = pagerOpentemp( pPager, ref pPager.fd, (int)pPager.vfsFlags ); |
||
4546 | } |
||
4547 | |||
4548 | /* Before the first write, give the VFS a hint of what the final |
||
4549 | ** file size will be. |
||
4550 | */ |
||
4551 | Debug.Assert( rc != SQLITE_OK || isOpen( pPager.fd ) ); |
||
4552 | if ( rc == SQLITE_OK && pPager.dbSize > pPager.dbHintSize ) |
||
4553 | { |
||
4554 | sqlite3_int64 szFile = pPager.pageSize * (sqlite3_int64)pPager.dbSize; |
||
4555 | sqlite3OsFileControl( pPager.fd, SQLITE_FCNTL_SIZE_HINT, ref szFile ); |
||
4556 | pPager.dbHintSize = pPager.dbSize; |
||
4557 | } |
||
4558 | while ( rc == SQLITE_OK && pList ) |
||
4559 | { |
||
4560 | Pgno pgno = pList.pgno; |
||
4561 | |||
4562 | /* If there are dirty pages in the page cache with page numbers greater |
||
4563 | ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to |
||
4564 | ** make the file smaller (presumably by auto-vacuum code). Do not write |
||
4565 | ** any such pages to the file. |
||
4566 | ** |
||
4567 | ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag |
||
4568 | ** set (set by sqlite3PagerDontWrite()). |
||
4569 | */ |
||
4570 | if ( pList.pgno <= pPager.dbSize && 0 == ( pList.flags & PGHDR_DONT_WRITE ) ) |
||
4571 | { |
||
4572 | i64 offset = ( pList.pgno - 1 ) * (i64)pPager.pageSize; /* Offset to write */ |
||
4573 | byte[] pData = null; /* Data to write */ |
||
4574 | |||
4575 | Debug.Assert( ( pList.flags & PGHDR_NEED_SYNC ) == 0 ); |
||
4576 | if ( pList.pgno == 1 ) |
||
4577 | pager_write_changecounter( pList ); |
||
4578 | |||
4579 | /* Encode the database */ |
||
4580 | if ( CODEC2( pPager, pList.pData, pgno, SQLITE_ENCRYPT_WRITE_CTX, ref pData ) ) |
||
4581 | return SQLITE_NOMEM;// CODEC2(pPager, pList.pData, pgno, 6, return SQLITE_NOMEM, pData); |
||
4582 | |||
4583 | /* Write out the page data. */ |
||
4584 | rc = sqlite3OsWrite( pPager.fd, pData, pPager.pageSize, offset ); |
||
4585 | /* If page 1 was just written, update Pager.dbFileVers to match |
||
4586 | ** the value now stored in the database file. If writing this |
||
4587 | ** page caused the database file to grow, update dbFileSize. |
||
4588 | */ |
||
4589 | if ( pgno == 1 ) |
||
4590 | { |
||
4591 | Buffer.BlockCopy( pData, 24, pPager.dbFileVers, 0, pPager.dbFileVers.Length );// memcpy(pPager.dbFileVers, pData[24], pPager.dbFileVers).Length; |
||
4592 | } |
||
4593 | if ( pgno > pPager.dbFileSize ) |
||
4594 | { |
||
4595 | pPager.dbFileSize = pgno; |
||
4596 | } |
||
4597 | /* Update any backup objects copying the contents of this pager. */ |
||
4598 | sqlite3BackupUpdate( pPager.pBackup, pgno, pList.pData ); |
||
4599 | |||
4600 | |||
4601 | PAGERTRACE( "STORE %d page %d hash(%08x)\n", |
||
4602 | PAGERID( pPager ), pgno, pager_pagehash( pList ) ); |
||
4603 | IOTRACE( "PGOUT %p %d\n", pPager, pgno ); |
||
4604 | #if SQLITE_TEST |
||
4605 | #if !TCLSH |
||
4606 | PAGER_INCR( ref sqlite3_pager_writedb_count ); |
||
4607 | #else |
||
4608 | int iValue; |
||
4609 | iValue = sqlite3_pager_writedb_count.iValue; |
||
4610 | PAGER_INCR( ref iValue ); |
||
4611 | sqlite3_pager_writedb_count.iValue = iValue; |
||
4612 | #endif |
||
4613 | |||
4614 | PAGER_INCR( ref pPager.nWrite ); |
||
4615 | #endif |
||
4616 | } |
||
4617 | else |
||
4618 | { |
||
4619 | |||
4620 | PAGERTRACE( "NOSTORE %d page %d\n", PAGERID( pPager ), pgno ); |
||
4621 | } |
||
4622 | pager_set_pagehash( pList ); |
||
4623 | pList = pList.pDirty; |
||
4624 | } |
||
4625 | return rc; |
||
4626 | } |
||
4627 | |||
4628 | /* |
||
4629 | ** Ensure that the sub-journal file is open. If it is already open, this |
||
4630 | ** function is a no-op. |
||
4631 | ** |
||
4632 | ** SQLITE_OK is returned if everything goes according to plan. An |
||
4633 | ** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() |
||
4634 | ** fails. |
||
4635 | */ |
||
4636 | static int openSubJournal( Pager pPager ) |
||
4637 | { |
||
4638 | int rc = SQLITE_OK; |
||
4639 | if ( !isOpen( pPager.sjfd ) ) |
||
4640 | { |
||
4641 | if ( pPager.journalMode == PAGER_JOURNALMODE_MEMORY || pPager.subjInMemory != 0 ) |
||
4642 | { |
||
4643 | sqlite3MemJournalOpen( pPager.sjfd ); |
||
4644 | } |
||
4645 | else |
||
4646 | { |
||
4647 | rc = pagerOpentemp( pPager, ref pPager.sjfd, SQLITE_OPEN_SUBJOURNAL ); |
||
4648 | } |
||
4649 | } |
||
4650 | return rc; |
||
4651 | } |
||
4652 | |||
4653 | /* |
||
4654 | ** Append a record of the current state of page pPg to the sub-journal. |
||
4655 | ** It is the callers responsibility to use subjRequiresPage() to check |
||
4656 | ** that it is really required before calling this function. |
||
4657 | ** |
||
4658 | ** If successful, set the bit corresponding to pPg.pgno in the bitvecs |
||
4659 | ** for all open savepoints before returning. |
||
4660 | ** |
||
4661 | ** This function returns SQLITE_OK if everything is successful, an IO |
||
4662 | ** error code if the attempt to write to the sub-journal fails, or |
||
4663 | ** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint |
||
4664 | ** bitvec. |
||
4665 | */ |
||
4666 | static int subjournalPage( PgHdr pPg ) |
||
4667 | { |
||
4668 | int rc = SQLITE_OK; |
||
4669 | Pager pPager = pPg.pPager; |
||
4670 | if ( pPager.journalMode != PAGER_JOURNALMODE_OFF ) |
||
4671 | { |
||
4672 | |||
4673 | /* Open the sub-journal, if it has not already been opened */ |
||
4674 | Debug.Assert( pPager.useJournal != 0 ); |
||
4675 | Debug.Assert( isOpen( pPager.jfd ) || pagerUseWal( pPager ) ); |
||
4676 | Debug.Assert( isOpen( pPager.sjfd ) || pPager.nSubRec == 0 ); |
||
4677 | Debug.Assert( pagerUseWal( pPager ) |
||
4678 | || pageInJournal( pPg ) |
||
4679 | || pPg.pgno > pPager.dbOrigSize |
||
4680 | ); |
||
4681 | rc = openSubJournal( pPager ); |
||
4682 | |||
4683 | /* If the sub-journal was opened successfully (or was already open), |
||
4684 | ** write the journal record into the file. */ |
||
4685 | if ( rc == SQLITE_OK ) |
||
4686 | { |
||
4687 | byte[] pData = pPg.pData; |
||
4688 | i64 offset = pPager.nSubRec * ( 4 + pPager.pageSize ); |
||
4689 | byte[] pData2 = null; |
||
4690 | |||
4691 | if ( CODEC2( pPager, pData, pPg.pgno, SQLITE_ENCRYPT_READ_CTX, ref pData2 ) ) |
||
4692 | return SQLITE_NOMEM;//CODEC2(pPager, pData, pPg.pgno, 7, return SQLITE_NOMEM, pData2); |
||
4693 | PAGERTRACE( "STMT-JOURNAL %d page %d\n", PAGERID( pPager ), pPg.pgno ); |
||
4694 | rc = write32bits( pPager.sjfd, offset, pPg.pgno ); |
||
4695 | if ( rc == SQLITE_OK ) |
||
4696 | { |
||
4697 | rc = sqlite3OsWrite( pPager.sjfd, pData2, pPager.pageSize, offset + 4 ); |
||
4698 | } |
||
4699 | } |
||
4700 | } |
||
4701 | if ( rc == SQLITE_OK ) |
||
4702 | { |
||
4703 | pPager.nSubRec++; |
||
4704 | Debug.Assert( pPager.nSavepoint > 0 ); |
||
4705 | rc = addToSavepointBitvecs( pPager, pPg.pgno ); |
||
4706 | } |
||
4707 | return rc; |
||
4708 | } |
||
4709 | |||
4710 | /* |
||
4711 | ** This function is called by the pcache layer when it has reached some |
||
4712 | ** soft memory limit. The first argument is a pointer to a Pager object |
||
4713 | ** (cast as a void*). The pager is always 'purgeable' (not an in-memory |
||
4714 | ** database). The second argument is a reference to a page that is |
||
4715 | ** currently dirty but has no outstanding references. The page |
||
4716 | ** is always associated with the Pager object passed as the first |
||
4717 | ** argument. |
||
4718 | ** |
||
4719 | ** The job of this function is to make pPg clean by writing its contents |
||
4720 | ** out to the database file, if possible. This may involve syncing the |
||
4721 | ** journal file. |
||
4722 | ** |
||
4723 | ** If successful, sqlite3PcacheMakeClean() is called on the page and |
||
4724 | ** SQLITE_OK returned. If an IO error occurs while trying to make the |
||
4725 | ** page clean, the IO error code is returned. If the page cannot be |
||
4726 | ** made clean for some other reason, but no error occurs, then SQLITE_OK |
||
4727 | ** is returned by sqlite3PcacheMakeClean() is not called. |
||
4728 | */ |
||
4729 | static int pagerStress( object p, PgHdr pPg ) |
||
4730 | { |
||
4731 | Pager pPager = (Pager)p; |
||
4732 | int rc = SQLITE_OK; |
||
4733 | |||
4734 | Debug.Assert( pPg.pPager == pPager ); |
||
4735 | Debug.Assert( ( pPg.flags & PGHDR_DIRTY ) != 0 ); |
||
4736 | |||
4737 | /* The doNotSyncSpill flag is set during times when doing a sync of |
||
4738 | ** journal (and adding a new header) is not allowed. This occurs |
||
4739 | ** during calls to sqlite3PagerWrite() while trying to journal multiple |
||
4740 | ** pages belonging to the same sector. |
||
4741 | ** |
||
4742 | ** The doNotSpill flag inhibits all cache spilling regardless of whether |
||
4743 | ** or not a sync is required. This is set during a rollback. |
||
4744 | ** |
||
4745 | ** Spilling is also prohibited when in an error state since that could |
||
4746 | ** lead to database corruption. In the current implementaton it |
||
4747 | ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1 |
||
4748 | ** while in the error state, hence it is impossible for this routine to |
||
4749 | ** be called in the error state. Nevertheless, we include a NEVER() |
||
4750 | ** test for the error state as a safeguard against future changes. |
||
4751 | */ |
||
4752 | if ( NEVER( pPager.errCode != 0 ) ) |
||
4753 | return SQLITE_OK; |
||
4754 | if ( pPager.doNotSpill != 0 ) |
||
4755 | return SQLITE_OK; |
||
4756 | if ( pPager.doNotSyncSpill != 0 && ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ) |
||
4757 | { |
||
4758 | return SQLITE_OK; |
||
4759 | } |
||
4760 | pPg.pDirty = null; |
||
4761 | if ( pagerUseWal( pPager ) ) |
||
4762 | { |
||
4763 | /* Write a single frame for this page to the log. */ |
||
4764 | if ( subjRequiresPage( pPg ) ) |
||
4765 | { |
||
4766 | rc = subjournalPage( pPg ); |
||
4767 | } |
||
4768 | if ( rc == SQLITE_OK ) |
||
4769 | { |
||
4770 | rc = pagerWalFrames( pPager, pPg, 0, 0, 0 ); |
||
4771 | } |
||
4772 | } |
||
4773 | else |
||
4774 | { |
||
4775 | |||
4776 | /* Sync the journal file if required. */ |
||
4777 | if ( ( pPg.flags & PGHDR_NEED_SYNC ) != 0 |
||
4778 | || pPager.eState == PAGER_WRITER_CACHEMOD |
||
4779 | ) |
||
4780 | { |
||
4781 | rc = syncJournal( pPager, 1 ); |
||
4782 | } |
||
4783 | |||
4784 | /* If the page number of this page is larger than the current size of |
||
4785 | ** the database image, it may need to be written to the sub-journal. |
||
4786 | ** This is because the call to pager_write_pagelist() below will not |
||
4787 | ** actually write data to the file in this case. |
||
4788 | ** |
||
4789 | ** Consider the following sequence of events: |
||
4790 | ** |
||
4791 | ** BEGIN; |
||
4792 | ** <journal page X> |
||
4793 | ** <modify page X> |
||
4794 | ** SAVEPOINT sp; |
||
4795 | ** <shrink database file to Y pages> |
||
4796 | ** pagerStress(page X) |
||
4797 | ** ROLLBACK TO sp; |
||
4798 | ** |
||
4799 | ** If (X>Y), then when pagerStress is called page X will not be written |
||
4800 | ** out to the database file, but will be dropped from the cache. Then, |
||
4801 | ** following the "ROLLBACK TO sp" statement, reading page X will read |
||
4802 | ** data from the database file. This will be the copy of page X as it |
||
4803 | ** was when the transaction started, not as it was when "SAVEPOINT sp" |
||
4804 | ** was executed. |
||
4805 | ** |
||
4806 | ** The solution is to write the current data for page X into the |
||
4807 | ** sub-journal file now (if it is not already there), so that it will |
||
4808 | ** be restored to its current value when the "ROLLBACK TO sp" is |
||
4809 | ** executed. |
||
4810 | */ |
||
4811 | if ( NEVER( |
||
4812 | rc == SQLITE_OK && pPg.pgno > pPager.dbSize && subjRequiresPage( pPg ) |
||
4813 | ) ) |
||
4814 | { |
||
4815 | rc = subjournalPage( pPg ); |
||
4816 | } |
||
4817 | |||
4818 | /* Write the contents of the page out to the database file. */ |
||
4819 | if ( rc == SQLITE_OK ) |
||
4820 | { |
||
4821 | Debug.Assert( ( pPg.flags & PGHDR_NEED_SYNC ) == 0 ); |
||
4822 | rc = pager_write_pagelist( pPager, pPg ); |
||
4823 | } |
||
4824 | } |
||
4825 | /* Mark the page as clean. */ |
||
4826 | if ( rc == SQLITE_OK ) |
||
4827 | { |
||
4828 | PAGERTRACE( "STRESS %d page %d\n", PAGERID( pPager ), pPg.pgno ); |
||
4829 | sqlite3PcacheMakeClean( pPg ); |
||
4830 | } |
||
4831 | |||
4832 | return pager_error( pPager, rc ); |
||
4833 | } |
||
4834 | |||
4835 | |||
4836 | /* |
||
4837 | ** Allocate and initialize a new Pager object and put a pointer to it |
||
4838 | ** in *ppPager. The pager should eventually be freed by passing it |
||
4839 | ** to sqlite3PagerClose(). |
||
4840 | ** |
||
4841 | ** The zFilename argument is the path to the database file to open. |
||
4842 | ** If zFilename is NULL then a randomly-named temporary file is created |
||
4843 | ** and used as the file to be cached. Temporary files are be deleted |
||
4844 | ** automatically when they are closed. If zFilename is ":memory:" then |
||
4845 | ** all information is held in cache. It is never written to disk. |
||
4846 | ** This can be used to implement an in-memory database. |
||
4847 | ** |
||
4848 | ** The nExtra parameter specifies the number of bytes of space allocated |
||
4849 | ** along with each page reference. This space is available to the user |
||
4850 | ** via the sqlite3PagerGetExtra() API. |
||
4851 | ** |
||
4852 | ** The flags argument is used to specify properties that affect the |
||
4853 | ** operation of the pager. It should be passed some bitwise combination |
||
4854 | ** of the PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK flags. |
||
4855 | ** |
||
4856 | ** The vfsFlags parameter is a bitmask to pass to the flags parameter |
||
4857 | ** of the xOpen() method of the supplied VFS when opening files. |
||
4858 | ** |
||
4859 | ** If the pager object is allocated and the specified file opened |
||
4860 | ** successfully, SQLITE_OK is returned and *ppPager set to point to |
||
4861 | ** the new pager object. If an error occurs, *ppPager is set to NULL |
||
4862 | ** and error code returned. This function may return SQLITE_NOMEM |
||
4863 | ** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or |
||
4864 | ** various SQLITE_IO_XXX errors. |
||
4865 | */ |
||
4866 | static int sqlite3PagerOpen( |
||
4867 | sqlite3_vfs pVfs, /* The virtual file system to use */ |
||
4868 | out Pager ppPager, /* OUT: Return the Pager structure here */ |
||
4869 | string zFilename, /* Name of the database file to open */ |
||
4870 | int nExtra, /* Extra bytes append to each in-memory page */ |
||
4871 | int flags, /* flags controlling this file */ |
||
4872 | int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ |
||
4873 | dxReiniter xReinit /* Function to reinitialize pages */ |
||
4874 | ) |
||
4875 | { |
||
4876 | u8 pPtr; |
||
4877 | Pager pPager = null; /* Pager object to allocate and return */ |
||
4878 | int rc = SQLITE_OK; /* Return code */ |
||
4879 | u8 tempFile = 0; /* True for temp files (incl. in-memory files) */ // Needs to be u8 for later tests |
||
4880 | u8 memDb = 0; /* True if this is an in-memory file */ |
||
4881 | bool readOnly = false; /* True if this is a read-only file */ |
||
4882 | ////int journalFileSize; /* Bytes to allocate for each journal fd */ |
||
4883 | StringBuilder zPathname = null; /* Full path to database file */ |
||
4884 | int nPathname = 0; /* Number of bytes in zPathname */ |
||
4885 | bool useJournal = ( flags & PAGER_OMIT_JOURNAL ) == 0; /* False to omit journal */ |
||
4886 | bool noReadlock = ( flags & PAGER_NO_READLOCK ) != 0; /* True to omit read-lock */ |
||
4887 | ////int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ |
||
4888 | u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ |
||
4889 | ////string zUri = null; /* URI args to copy */ |
||
4890 | ////int nUri = 0; /* Number of bytes of URI args at *zUri */ |
||
4891 | |||
4892 | /* Figure out how much space is required for each journal file-handle |
||
4893 | ** (there are two of them, the main journal and the sub-journal). This |
||
4894 | ** is the maximum space required for an in-memory journal file handle |
||
4895 | ** and a regular journal file-handle. Note that a "regular journal-handle" |
||
4896 | ** may be a wrapper capable of caching the first portion of the journal |
||
4897 | ** file in memory to implement the atomic-write optimization (see |
||
4898 | ** source file journal.c). |
||
4899 | */ |
||
4900 | ////if ( sqlite3JournalSize( pVfs ) > sqlite3MemJournalSize() ) |
||
4901 | ////{ |
||
4902 | //// journalFileSize = ROUND8( sqlite3JournalSize( pVfs ) ); |
||
4903 | ////} |
||
4904 | ////else |
||
4905 | ////{ |
||
4906 | //// journalFileSize = ROUND8( sqlite3MemJournalSize() ); |
||
4907 | ////} |
||
4908 | |||
4909 | /* Set the output variable to NULL in case an error occurs. */ |
||
4910 | ppPager = null; |
||
4911 | |||
4912 | #if !SQLITE_OMIT_MEMORYDB |
||
4913 | if ( ( flags & PAGER_MEMORY ) != 0 ) |
||
4914 | { |
||
4915 | memDb = 1; |
||
4916 | zFilename = null; |
||
4917 | } |
||
4918 | #endif |
||
4919 | |||
4920 | /* Compute and store the full pathname in an allocated buffer pointed |
||
4921 | ** to by zPathname, length nPathname. Or, if this is a temporary file, |
||
4922 | ** leave both nPathname and zPathname set to 0. |
||
4923 | */ |
||
4924 | if ( !string.IsNullOrEmpty( zFilename ) ) |
||
4925 | { |
||
4926 | string z; |
||
4927 | nPathname = pVfs.mxPathname + 1; |
||
4928 | zPathname = new StringBuilder( nPathname * 2 );// sqlite3Malloc( nPathname * 2 ); |
||
4929 | //if ( zPathname == null ) |
||
4930 | //{ |
||
4931 | // return SQLITE_NOMEM; |
||
4932 | //} |
||
4933 | //zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ |
||
4934 | rc = sqlite3OsFullPathname( pVfs, zFilename, nPathname, zPathname ); |
||
4935 | |||
4936 | nPathname = sqlite3Strlen30( zPathname ); |
||
4937 | ////z = zUri = zFilename;//.Substring(sqlite3Strlen30( zFilename ) ); |
||
4938 | //while ( *z ) |
||
4939 | //{ |
||
4940 | // z += sqlite3Strlen30( z ) + 1; |
||
4941 | // z += sqlite3Strlen30( z ) + 1; |
||
4942 | //} |
||
4943 | ////nUri = zUri.Length;// &z[1] - zUri; |
||
4944 | if ( rc == SQLITE_OK && nPathname + 8 > pVfs.mxPathname ) |
||
4945 | { |
||
4946 | /* This branch is taken when the journal path required by |
||
4947 | ** the database being opened will be more than pVfs.mxPathname |
||
4948 | ** bytes in length. This means the database cannot be opened, |
||
4949 | ** as it will not be possible to open the journal file or even |
||
4950 | ** check for a hot-journal before reading. |
||
4951 | */ |
||
4952 | rc = SQLITE_CANTOPEN_BKPT(); |
||
4953 | } |
||
4954 | if ( rc != SQLITE_OK ) |
||
4955 | { |
||
4956 | //sqlite3_free( ref zPathname ); |
||
4957 | return rc; |
||
4958 | } |
||
4959 | } |
||
4960 | |||
4961 | /* Allocate memory for the Pager structure, PCache object, the |
||
4962 | ** three file descriptors, the database file name and the journal |
||
4963 | ** file name. The layout in memory is as follows: |
||
4964 | ** |
||
4965 | ** Pager object (sizeof(Pager) bytes) |
||
4966 | ** PCache object (sqlite3PcacheSize() bytes) |
||
4967 | ** Database file handle (pVfs.szOsFile bytes) |
||
4968 | ** Sub-journal file handle (journalFileSize bytes) |
||
4969 | ** Main journal file handle (journalFileSize bytes) |
||
4970 | ** Database file name (nPathname+1 bytes) |
||
4971 | ** Journal file name (nPathname+8+1 bytes) |
||
4972 | */ |
||
4973 | //pPtr = (u8 *)sqlite3MallocZero( |
||
4974 | // ROUND8(sizeof(*pPager)) + /* Pager structure */ |
||
4975 | // ROUND8(pcacheSize) + /* PCache object */ |
||
4976 | // ROUND8(pVfs.szOsFile) + /* The main db file */ |
||
4977 | // journalFileSize * 2 + /* The two journal files */ |
||
4978 | // nPathname + 1 + nUri + /* zFilename */ |
||
4979 | // nPathname + 8 + 1 /* zJournal */ |
||
4980 | //#if !SQLITE_OMIT_WAL |
||
4981 | // + nPathname + 4 + 1 /* zWal */ |
||
4982 | //#endif |
||
4983 | //); |
||
4984 | // Debug.Assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize))); |
||
4985 | //if( !pPtr ){ |
||
4986 | // //sqlite3_free(zPathname); |
||
4987 | // return SQLITE_NOMEM; |
||
4988 | //} |
||
4989 | pPager = new Pager();//(Pager*)(pPtr); |
||
4990 | pPager.pPCache = new PCache();//(PCache*)(pPtr += ROUND8(sizeof(*pPager))); |
||
4991 | pPager.fd = new sqlite3_file();//(sqlite3_file*)(pPtr += ROUND8(pcacheSize)); |
||
4992 | pPager.sjfd = new sqlite3_file();//(sqlite3_file*)(pPtr += ROUND8(pVfs.szOsFile)); |
||
4993 | pPager.jfd = new sqlite3_file();//(sqlite3_file*)(pPtr += journalFileSize); |
||
4994 | //pPager.zFilename = (char*)(pPtr += journalFileSize); |
||
4995 | //Debug.Assert( EIGHT_BYTE_ALIGNMENT(pPager.jfd) ); |
||
4996 | |||
4997 | /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ |
||
4998 | if ( zPathname != null ) |
||
4999 | { |
||
5000 | Debug.Assert( nPathname > 0 ); |
||
5001 | //pPager.zJournal = (char*)(pPtr += nPathname + 1 + nUri); |
||
5002 | //memcpy(pPager.zFilename, zPathname, nPathname); |
||
5003 | pPager.zFilename = zPathname.ToString(); |
||
5004 | ////zUri = pPager.zFilename;//.Substring( nPathname + 1 );//memcpy( &pPager.zFilename[nPathname + 1], zUri, nUri ); |
||
5005 | //memcpy(pPager.zJournal, zPathname, nPathname); |
||
5006 | //memcpy(&pPager.zJournal[nPathname], "-journal", 8); |
||
5007 | pPager.zJournal = pPager.zFilename + "-journal"; |
||
5008 | sqlite3FileSuffix3( pPager.zFilename, pPager.zJournal ); |
||
5009 | #if !SQLITE_OMIT_WAL |
||
5010 | pPager.zWal = &pPager.zJournal[nPathname+8+1]; |
||
5011 | memcpy(pPager.zWal, zPathname, nPathname); |
||
5012 | memcpy(&pPager.zWal[nPathname], "-wal", 4); |
||
5013 | sqlite3FileSuffix3(pPager.zFilename, pPager.zWal); |
||
5014 | #endif |
||
5015 | |||
5016 | //sqlite3_free( ref zPathname ); |
||
5017 | } |
||
5018 | else |
||
5019 | { |
||
5020 | pPager.zFilename = string.Empty; |
||
5021 | } |
||
5022 | pPager.pVfs = pVfs; |
||
5023 | pPager.vfsFlags = (u32)vfsFlags; |
||
5024 | |||
5025 | /* Open the pager file. |
||
5026 | */ |
||
5027 | if ( !string.IsNullOrEmpty( zFilename ) ) |
||
5028 | { |
||
5029 | int fout = 0; /* VFS flags returned by xOpen() */ |
||
5030 | rc = sqlite3OsOpen( pVfs, pPager.zFilename, pPager.fd, vfsFlags, ref fout ); |
||
5031 | Debug.Assert( 0 == memDb ); |
||
5032 | readOnly = ( fout & SQLITE_OPEN_READONLY ) != 0; |
||
5033 | |||
5034 | /* If the file was successfully opened for read/write access, |
||
5035 | ** choose a default page size in case we have to create the |
||
5036 | ** database file. The default page size is the maximum of: |
||
5037 | ** |
||
5038 | ** + SQLITE_DEFAULT_PAGE_SIZE, |
||
5039 | ** + The value returned by sqlite3OsSectorSize() |
||
5040 | ** + The largest page size that can be written atomically. |
||
5041 | */ |
||
5042 | if ( rc == SQLITE_OK && !readOnly ) |
||
5043 | { |
||
5044 | setSectorSize( pPager ); |
||
5045 | Debug.Assert( SQLITE_DEFAULT_PAGE_SIZE <= SQLITE_MAX_DEFAULT_PAGE_SIZE ); |
||
5046 | if ( szPageDflt < pPager.sectorSize ) |
||
5047 | { |
||
5048 | if ( pPager.sectorSize > SQLITE_MAX_DEFAULT_PAGE_SIZE ) |
||
5049 | { |
||
5050 | szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; |
||
5051 | } |
||
5052 | else |
||
5053 | { |
||
5054 | szPageDflt = (u32)pPager.sectorSize; |
||
5055 | } |
||
5056 | } |
||
5057 | #if SQLITE_ENABLE_ATOMIC_WRITE |
||
5058 | { |
||
5059 | int iDc = sqlite3OsDeviceCharacteristics(pPager.fd); |
||
5060 | int ii; |
||
5061 | Debug.Assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); |
||
5062 | Debug.Assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); |
||
5063 | Debug.Assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); |
||
5064 | for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ |
||
5065 | if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ |
||
5066 | szPageDflt = ii; |
||
5067 | } |
||
5068 | } |
||
5069 | } |
||
5070 | #endif |
||
5071 | } |
||
5072 | } |
||
5073 | else |
||
5074 | { |
||
5075 | /* If a temporary file is requested, it is not opened immediately. |
||
5076 | ** In this case we accept the default page size and delay actually |
||
5077 | ** opening the file until the first call to OsWrite(). |
||
5078 | ** |
||
5079 | ** This branch is also run for an in-memory database. An in-memory |
||
5080 | ** database is the same as a temp-file that is never written out to |
||
5081 | ** disk and uses an in-memory rollback journal. |
||
5082 | */ |
||
5083 | tempFile = 1; |
||
5084 | pPager.eState = PAGER_READER; |
||
5085 | pPager.eLock = EXCLUSIVE_LOCK; |
||
5086 | readOnly = ( vfsFlags & SQLITE_OPEN_READONLY ) != 0; |
||
5087 | } |
||
5088 | |||
5089 | /* The following call to PagerSetPagesize() serves to set the value of |
||
5090 | ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. |
||
5091 | */ |
||
5092 | if ( rc == SQLITE_OK ) |
||
5093 | { |
||
5094 | Debug.Assert( pPager.memDb == 0 ); |
||
5095 | rc = sqlite3PagerSetPagesize( pPager, ref szPageDflt, -1 ); |
||
5096 | testcase( rc != SQLITE_OK ); |
||
5097 | } |
||
5098 | |||
5099 | /* If an error occurred in either of the blocks above, free the |
||
5100 | ** Pager structure and close the file. |
||
5101 | */ |
||
5102 | if ( rc != SQLITE_OK ) |
||
5103 | { |
||
5104 | Debug.Assert( null == pPager.pTmpSpace ); |
||
5105 | sqlite3OsClose( pPager.fd ); |
||
5106 | //sqlite3_free( ref pPager ); |
||
5107 | return rc; |
||
5108 | } |
||
5109 | |||
5110 | /* Initialize the PCache object. */ |
||
5111 | Debug.Assert( nExtra < 1000 ); |
||
5112 | nExtra = ROUND8( nExtra ); |
||
5113 | sqlite3PcacheOpen( (int)szPageDflt, nExtra, 0 == memDb, |
||
5114 | |||
5115 | |||
5116 | PAGERTRACE( "OPEN %d %s\n", FILEHANDLEID( pPager.fd ), pPager.zFilename ); |
||
5117 | IOTRACE( "OPEN %p %s\n", pPager, pPager.zFilename ); |
||
5118 | pPager.useJournal = (u8)( useJournal ? 1 : 0 ); |
||
5119 | pPager.noReadlock = (u8)( noReadlock && readOnly ? 1 : 0 ); |
||
5120 | /* pPager.stmtOpen = 0; */ |
||
5121 | /* pPager.stmtInUse = 0; */ |
||
5122 | /* pPager.nRef = 0; */ |
||
5123 | /* pPager.stmtSize = 0; */ |
||
5124 | /* pPager.stmtJSize = 0; */ |
||
5125 | /* pPager.nPage = 0; */ |
||
5126 | pPager.mxPgno = SQLITE_MAX_PAGE_COUNT; |
||
5127 | /* pPager.state = PAGER_UNLOCK; */ |
||
5128 | #if FALSE |
||
5129 | Debug.Assert(pPager.state == (tempFile != 0 ? PAGER_EXCLUSIVE : PAGER_UNLOCK)); |
||
5130 | #endif |
||
5131 | /* pPager.errMask = 0; */ |
||
5132 | pPager.tempFile = tempFile != 0; |
||
5133 | Debug.Assert( tempFile == PAGER_LOCKINGMODE_NORMAL |
||
5134 | || tempFile == PAGER_LOCKINGMODE_EXCLUSIVE ); |
||
5135 | Debug.Assert( PAGER_LOCKINGMODE_EXCLUSIVE == 1 ); |
||
5136 | pPager.exclusiveMode = tempFile != 0; |
||
5137 | pPager.changeCountDone = pPager.tempFile; |
||
5138 | pPager.memDb = memDb; |
||
5139 | pPager.readOnly = readOnly; |
||
5140 | Debug.Assert( useJournal || pPager.tempFile ); |
||
5141 | pPager.noSync = pPager.tempFile; |
||
5142 | pPager.fullSync = pPager.noSync; |
||
5143 | pPager.syncFlags = (byte)( pPager.noSync ? 0 : SQLITE_SYNC_NORMAL ); |
||
5144 | pPager.ckptSyncFlags = pPager.syncFlags; |
||
5145 | /* pPager.pFirst = 0; */ |
||
5146 | /* pPager.pFirstSynced = 0; */ |
||
5147 | /* pPager.pLast = 0; */ |
||
5148 | pPager.nExtra = (u16)nExtra; |
||
5149 | pPager.journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; |
||
5150 | Debug.Assert( isOpen( pPager.fd ) || tempFile != 0 ); |
||
5151 | setSectorSize( pPager ); |
||
5152 | if ( !useJournal ) |
||
5153 | { |
||
5154 | pPager.journalMode = PAGER_JOURNALMODE_OFF; |
||
5155 | } |
||
5156 | else if ( memDb != 0 ) |
||
5157 | { |
||
5158 | pPager.journalMode = PAGER_JOURNALMODE_MEMORY; |
||
5159 | } |
||
5160 | /* pPager.xBusyHandler = 0; */ |
||
5161 | /* pPager.pBusyHandlerArg = 0; */ |
||
5162 | pPager.xReiniter = xReinit; |
||
5163 | /* memset(pPager.aHash, 0, sizeof(pPager.aHash)); */ |
||
5164 | ppPager = pPager; |
||
5165 | return SQLITE_OK; |
||
5166 | } |
||
5167 | |||
5168 | |||
5169 | |||
5170 | /* |
||
5171 | ** This function is called after transitioning from PAGER_UNLOCK to |
||
5172 | ** PAGER_SHARED state. It tests if there is a hot journal present in |
||
5173 | ** the file-system for the given pager. A hot journal is one that |
||
5174 | ** needs to be played back. According to this function, a hot-journal |
||
5175 | ** file exists if the following criteria are met: |
||
5176 | ** |
||
5177 | ** * The journal file exists in the file system, and |
||
5178 | ** * No process holds a RESERVED or greater lock on the database file, and |
||
5179 | ** * The database file itself is greater than 0 bytes in size, and |
||
5180 | ** * The first byte of the journal file exists and is not 0x00. |
||
5181 | ** |
||
5182 | ** If the current size of the database file is 0 but a journal file |
||
5183 | ** exists, that is probably an old journal left over from a prior |
||
5184 | ** database with the same name. In this case the journal file is |
||
5185 | ** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK |
||
5186 | ** is returned. |
||
5187 | ** |
||
5188 | ** This routine does not check if there is a master journal filename |
||
5189 | ** at the end of the file. If there is, and that master journal file |
||
5190 | ** does not exist, then the journal file is not really hot. In this |
||
5191 | ** case this routine will return a false-positive. The pager_playback() |
||
5192 | ** routine will discover that the journal file is not really hot and |
||
5193 | ** will not roll it back. |
||
5194 | ** |
||
5195 | ** If a hot-journal file is found to exist, *pExists is set to 1 and |
||
5196 | ** SQLITE_OK returned. If no hot-journal file is present, *pExists is |
||
5197 | ** set to 0 and SQLITE_OK returned. If an IO error occurs while trying |
||
5198 | ** to determine whether or not a hot-journal file exists, the IO error |
||
5199 | ** code is returned and the value of *pExists is undefined. |
||
5200 | */ |
||
5201 | static int hasHotJournal( Pager pPager, ref int pExists ) |
||
5202 | { |
||
5203 | sqlite3_vfs pVfs = pPager.pVfs; |
||
5204 | int rc = SQLITE_OK; /* Return code */ |
||
5205 | int exists = 1; /* True if a journal file is present */ |
||
5206 | int jrnlOpen = isOpen( pPager.jfd ) ? 1 : 0; |
||
5207 | Debug.Assert( pPager.useJournal != 0 ); |
||
5208 | Debug.Assert( isOpen( pPager.fd ) ); |
||
5209 | Debug.Assert( pPager.eState == PAGER_OPEN ); |
||
5210 | |||
5211 | Debug.Assert( jrnlOpen == 0 || ( sqlite3OsDeviceCharacteristics( pPager.jfd ) & |
||
5212 | SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
||
5213 | ) != 0 ); |
||
5214 | |||
5215 | |||
5216 | pExists = 0; |
||
5217 | |||
5218 | if ( 0 == jrnlOpen ) |
||
5219 | { |
||
5220 | rc = sqlite3OsAccess( pVfs, pPager.zJournal, SQLITE_ACCESS_EXISTS, ref exists ); |
||
5221 | } |
||
5222 | if ( rc == SQLITE_OK && exists != 0 ) |
||
5223 | { |
||
5224 | int locked = 0; /* True if some process holds a RESERVED lock */ |
||
5225 | |||
5226 | /* Race condition here: Another process might have been holding the |
||
5227 | ** the RESERVED lock and have a journal open at the sqlite3OsAccess() |
||
5228 | ** call above, but then delete the journal and drop the lock before |
||
5229 | ** we get to the following sqlite3OsCheckReservedLock() call. If that |
||
5230 | ** is the case, this routine might think there is a hot journal when |
||
5231 | ** in fact there is none. This results in a false-positive which will |
||
5232 | ** be dealt with by the playback routine. Ticket #3883. |
||
5233 | */ |
||
5234 | rc = sqlite3OsCheckReservedLock( pPager.fd, ref locked ); |
||
5235 | if ( rc == SQLITE_OK && locked == 0 ) |
||
5236 | { |
||
5237 | Pgno nPage = 0; /* Number of pages in database file */ |
||
5238 | |||
5239 | /* Check the size of the database file. If it consists of 0 pages, |
||
5240 | ** then delete the journal file. See the header comment above for |
||
5241 | ** the reasoning here. Delete the obsolete journal file under |
||
5242 | ** a RESERVED lock to avoid race conditions and to avoid violating |
||
5243 | ** [H33020]. |
||
5244 | */ |
||
5245 | rc = pagerPagecount( pPager, ref nPage ); |
||
5246 | if ( rc == SQLITE_OK ) |
||
5247 | { |
||
5248 | if ( nPage == 0 ) |
||
5249 | { |
||
5250 | sqlite3BeginBenignMalloc(); |
||
5251 | if ( pagerLockDb( pPager, RESERVED_LOCK ) == SQLITE_OK ) |
||
5252 | { |
||
5253 | sqlite3OsDelete( pVfs, pPager.zJournal, 0 ); |
||
5254 | if ( !pPager.exclusiveMode ) |
||
5255 | pagerUnlockDb( pPager, SHARED_LOCK ); |
||
5256 | } |
||
5257 | sqlite3EndBenignMalloc(); |
||
5258 | } |
||
5259 | else |
||
5260 | { |
||
5261 | /* The journal file exists and no other connection has a reserved |
||
5262 | ** or greater lock on the database file. Now check that there is |
||
5263 | ** at least one non-zero bytes at the start of the journal file. |
||
5264 | ** If there is, then we consider this journal to be hot. If not, |
||
5265 | ** it can be ignored. |
||
5266 | */ |
||
5267 | if ( 0 == jrnlOpen ) |
||
5268 | { |
||
5269 | int f = SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_JOURNAL; |
||
5270 | rc = sqlite3OsOpen( pVfs, pPager.zJournal, pPager.jfd, f, ref f ); |
||
5271 | } |
||
5272 | if ( rc == SQLITE_OK ) |
||
5273 | { |
||
5274 | u8[] first = new u8[1]; |
||
5275 | rc = sqlite3OsRead( pPager.jfd, first, 1, 0 ); |
||
5276 | if ( rc == SQLITE_IOERR_SHORT_READ ) |
||
5277 | { |
||
5278 | rc = SQLITE_OK; |
||
5279 | } |
||
5280 | if ( 0 == jrnlOpen ) |
||
5281 | { |
||
5282 | sqlite3OsClose( pPager.jfd ); |
||
5283 | } |
||
5284 | pExists = ( first[0] != 0 ) ? 1 : 0; |
||
5285 | } |
||
5286 | else if ( rc == SQLITE_CANTOPEN ) |
||
5287 | { |
||
5288 | /* If we cannot open the rollback journal file in order to see if |
||
5289 | ** its has a zero header, that might be due to an I/O error, or |
||
5290 | ** it might be due to the race condition described above and in |
||
5291 | ** ticket #3883. Either way, assume that the journal is hot. |
||
5292 | ** This might be a false positive. But if it is, then the |
||
5293 | ** automatic journal playback and recovery mechanism will deal |
||
5294 | ** with it under an EXCLUSIVE lock where we do not need to |
||
5295 | ** worry so much with race conditions. |
||
5296 | */ |
||
5297 | pExists = 1; |
||
5298 | rc = SQLITE_OK; |
||
5299 | } |
||
5300 | } |
||
5301 | } |
||
5302 | } |
||
5303 | } |
||
5304 | return rc; |
||
5305 | } |
||
5306 | |||
5307 | |||
5308 | |||
5309 | /* |
||
5310 | ** This function is called to obtain a shared lock on the database file. |
||
5311 | ** It is illegal to call sqlite3PagerAcquire() until after this function |
||
5312 | ** has been successfully called. If a shared-lock is already held when |
||
5313 | ** this function is called, it is a no-op. |
||
5314 | ** |
||
5315 | ** The following operations are also performed by this function. |
||
5316 | ** |
||
5317 | ** 1) If the pager is currently in PAGER_OPEN state (no lock held |
||
5318 | ** on the database file), then an attempt is made to obtain a |
||
5319 | ** SHARED lock on the database file. Immediately after obtaining |
||
5320 | ** the SHARED lock, the file-system is checked for a hot-journal, |
||
5321 | ** which is played back if present. Following any hot-journal |
||
5322 | ** rollback, the contents of the cache are validated by checking |
||
5323 | ** the 'change-counter' field of the database file header and |
||
5324 | ** discarded if they are found to be invalid. |
||
5325 | ** |
||
5326 | ** 2) If the pager is running in exclusive-mode, and there are currently |
||
5327 | ** no outstanding references to any pages, and is in the error state, |
||
5328 | ** then an attempt is made to clear the error state by discarding |
||
5329 | ** the contents of the page cache and rolling back any open journal |
||
5330 | ** file. |
||
5331 | ** |
||
5332 | ** If everything is successful, SQLITE_OK is returned. If an IO error |
||
5333 | ** occurs while locking the database, checking for a hot-journal file or |
||
5334 | ** rolling back a journal file, the IO error code is returned. |
||
5335 | */ |
||
5336 | static int sqlite3PagerSharedLock( Pager pPager ) |
||
5337 | { |
||
5338 | int rc = SQLITE_OK; /* Return code */ |
||
5339 | |||
5340 | /* This routine is only called from b-tree and only when there are no |
||
5341 | ** outstanding pages. This implies that the pager state should either |
||
5342 | ** be OPEN or READER. READER is only possible if the pager is or was in |
||
5343 | ** exclusive access mode. |
||
5344 | */ |
||
5345 | Debug.Assert( sqlite3PcacheRefCount( pPager.pPCache ) == 0 ); |
||
5346 | Debug.Assert( assert_pager_state( pPager ) ); |
||
5347 | Debug.Assert( pPager.eState == PAGER_OPEN || pPager.eState == PAGER_READER ); |
||
5348 | if ( NEVER( |
||
5349 | #if SQLITE_OMIT_MEMORYDB |
||
5350 | 0!=MEMDB |
||
5351 | #else |
||
5352 | |||
5353 | #endif |
||
5354 | && pPager.errCode != 0 ) ) |
||
5355 | { |
||
5356 | return pPager.errCode; |
||
5357 | } |
||
5358 | |||
5359 | if ( !pagerUseWal( pPager ) && pPager.eState == PAGER_OPEN ) |
||
5360 | { |
||
5361 | int bHotJournal = 1; /* True if there exists a hot journal-file */ |
||
5362 | |||
5363 | Debug.Assert( |
||
5364 | #if SQLITE_OMIT_MEMORYDB |
||
5365 | 0==MEMDB |
||
5366 | #else |
||
5367 | |||
5368 | #endif |
||
5369 | ); |
||
5370 | Debug.Assert( pPager.noReadlock == 0 || pPager.readOnly ); |
||
5371 | |||
5372 | if ( pPager.noReadlock == 0 ) |
||
5373 | { |
||
5374 | rc = pager_wait_on_lock( pPager, SHARED_LOCK ); |
||
5375 | if ( rc != SQLITE_OK ) |
||
5376 | { |
||
5377 | Debug.Assert( pPager.eLock == NO_LOCK || pPager.eLock == UNKNOWN_LOCK ); |
||
5378 | goto failed; |
||
5379 | } |
||
5380 | } |
||
5381 | |||
5382 | /* If a journal file exists, and there is no RESERVED lock on the |
||
5383 | ** database file, then it either needs to be played back or deleted. |
||
5384 | */ |
||
5385 | if ( pPager.eLock <= SHARED_LOCK ) |
||
5386 | { |
||
5387 | rc = hasHotJournal( pPager, ref bHotJournal ); |
||
5388 | } |
||
5389 | if ( rc != SQLITE_OK ) |
||
5390 | { |
||
5391 | goto failed; |
||
5392 | } |
||
5393 | if ( bHotJournal != 0 ) |
||
5394 | { |
||
5395 | /* Get an EXCLUSIVE lock on the database file. At this point it is |
||
5396 | ** important that a RESERVED lock is not obtained on the way to the |
||
5397 | ** EXCLUSIVE lock. If it were, another process might open the |
||
5398 | ** database file, detect the RESERVED lock, and conclude that the |
||
5399 | ** database is safe to read while this process is still rolling the |
||
5400 | ** hot-journal back. |
||
5401 | ** |
||
5402 | ** Because the intermediate RESERVED lock is not requested, any |
||
5403 | ** other process attempting to access the database file will get to |
||
5404 | ** this point in the code and fail to obtain its own EXCLUSIVE lock |
||
5405 | ** on the database file. |
||
5406 | ** |
||
5407 | ** Unless the pager is in locking_mode=exclusive mode, the lock is |
||
5408 | ** downgraded to SHARED_LOCK before this function returns. |
||
5409 | */ |
||
5410 | rc = pagerLockDb( pPager, EXCLUSIVE_LOCK ); |
||
5411 | if ( rc != SQLITE_OK ) |
||
5412 | { |
||
5413 | goto failed; |
||
5414 | } |
||
5415 | |||
5416 | /* If it is not already open and the file exists on disk, open the |
||
5417 | ** journal for read/write access. Write access is required because |
||
5418 | ** in exclusive-access mode the file descriptor will be kept open |
||
5419 | ** and possibly used for a transaction later on. Also, write-access |
||
5420 | ** is usually required to finalize the journal in journal_mode=persist |
||
5421 | ** mode (and also for journal_mode=truncate on some systems). |
||
5422 | ** |
||
5423 | ** If the journal does not exist, it usually means that some |
||
5424 | ** other connection managed to get in and roll it back before |
||
5425 | ** this connection obtained the exclusive lock above. Or, it |
||
5426 | ** may mean that the pager was in the error-state when this |
||
5427 | ** function was called and the journal file does not exist. |
||
5428 | */ |
||
5429 | if ( !isOpen( pPager.jfd ) ) |
||
5430 | { |
||
5431 | sqlite3_vfs pVfs = pPager.pVfs; |
||
5432 | int bExists = 0; /* True if journal file exists */ |
||
5433 | rc = sqlite3OsAccess( |
||
5434 | pVfs, pPager.zJournal, SQLITE_ACCESS_EXISTS, ref bExists ); |
||
5435 | if ( rc == SQLITE_OK && bExists != 0 ) |
||
5436 | { |
||
5437 | int fout = 0; |
||
5438 | int f = SQLITE_OPEN_READWRITE | SQLITE_OPEN_MAIN_JOURNAL; |
||
5439 | Debug.Assert( !pPager.tempFile ); |
||
5440 | rc = sqlite3OsOpen( pVfs, pPager.zJournal, pPager.jfd, f, ref fout ); |
||
5441 | Debug.Assert( rc != SQLITE_OK || isOpen( pPager.jfd ) ); |
||
5442 | if ( rc == SQLITE_OK && ( fout & SQLITE_OPEN_READONLY ) != 0 ) |
||
5443 | { |
||
5444 | rc = SQLITE_CANTOPEN_BKPT(); |
||
5445 | sqlite3OsClose( pPager.jfd ); |
||
5446 | } |
||
5447 | } |
||
5448 | } |
||
5449 | |||
5450 | /* Playback and delete the journal. Drop the database write |
||
5451 | ** lock and reacquire the read lock. Purge the cache before |
||
5452 | ** playing back the hot-journal so that we don't end up with |
||
5453 | ** an inconsistent cache. Sync the hot journal before playing |
||
5454 | ** it back since the process that crashed and left the hot journal |
||
5455 | ** probably did not sync it and we are required to always sync |
||
5456 | ** the journal before playing it back. |
||
5457 | */ |
||
5458 | if ( isOpen( pPager.jfd ) ) |
||
5459 | { |
||
5460 | Debug.Assert( rc == SQLITE_OK ); |
||
5461 | rc = pagerSyncHotJournal( pPager ); |
||
5462 | if ( rc == SQLITE_OK ) |
||
5463 | { |
||
5464 | rc = pager_playback( pPager, 1 ); |
||
5465 | pPager.eState = PAGER_OPEN; |
||
5466 | } |
||
5467 | } |
||
5468 | else if ( !pPager.exclusiveMode ) |
||
5469 | { |
||
5470 | pagerUnlockDb( pPager, SHARED_LOCK ); |
||
5471 | } |
||
5472 | |||
5473 | if ( rc != SQLITE_OK ) |
||
5474 | { |
||
5475 | /* This branch is taken if an error occurs while trying to open |
||
5476 | ** or roll back a hot-journal while holding an EXCLUSIVE lock. The |
||
5477 | ** pager_unlock() routine will be called before returning to unlock |
||
5478 | ** the file. If the unlock attempt fails, then Pager.eLock must be |
||
5479 | ** set to UNKNOWN_LOCK (see the comment above the #define for |
||
5480 | ** UNKNOWN_LOCK above for an explanation). |
||
5481 | ** |
||
5482 | ** In order to get pager_unlock() to do this, set Pager.eState to |
||
5483 | ** PAGER_ERROR now. This is not actually counted as a transition |
||
5484 | ** to ERROR state in the state diagram at the top of this file, |
||
5485 | ** since we know that the same call to pager_unlock() will very |
||
5486 | ** shortly transition the pager object to the OPEN state. Calling |
||
5487 | ** assert_pager_state() would fail now, as it should not be possible |
||
5488 | ** to be in ERROR state when there are zero outstanding page |
||
5489 | ** references. |
||
5490 | */ |
||
5491 | pager_error( pPager, rc ); |
||
5492 | goto failed; |
||
5493 | } |
||
5494 | |||
5495 | Debug.Assert( pPager.eState == PAGER_OPEN ); |
||
5496 | Debug.Assert( ( pPager.eLock == SHARED_LOCK ) |
||
5497 | || ( pPager.exclusiveMode && pPager.eLock > SHARED_LOCK ) |
||
5498 | ); |
||
5499 | } |
||
5500 | |||
5501 | if ( !pPager.tempFile |
||
5502 | && ( pPager.pBackup != null || sqlite3PcachePagecount( pPager.pPCache ) > 0 ) |
||
5503 | ) |
||
5504 | { |
||
5505 | /* The shared-lock has just been acquired on the database file |
||
5506 | ** and there are already pages in the cache (from a previous |
||
5507 | ** read or write transaction). Check to see if the database |
||
5508 | ** has been modified. If the database has changed, flush the |
||
5509 | ** cache. |
||
5510 | ** |
||
5511 | ** Database changes is detected by looking at 15 bytes beginning |
||
5512 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
||
5513 | ** a 32-bit counter that is incremented with each change. The |
||
5514 | ** other bytes change randomly with each file change when |
||
5515 | ** a codec is in use. |
||
5516 | ** |
||
5517 | ** There is a vanishingly small chance that a change will not be |
||
5518 | ** detected. The chance of an undetected change is so small that |
||
5519 | ** it can be neglected. |
||
5520 | */ |
||
5521 | Pgno nPage = 0; |
||
5522 | byte[] dbFileVers = new byte[pPager.dbFileVers.Length]; |
||
5523 | |||
5524 | rc = pagerPagecount( pPager, ref nPage ); |
||
5525 | if ( rc != 0 ) |
||
5526 | goto failed; |
||
5527 | |||
5528 | if ( nPage > 0 ) |
||
5529 | { |
||
5530 | IOTRACE( "CKVERS %p %d\n", pPager, dbFileVers.Length ); |
||
5531 | rc = sqlite3OsRead( pPager.fd, dbFileVers, dbFileVers.Length, 24 ); |
||
5532 | if ( rc != SQLITE_OK ) |
||
5533 | { |
||
5534 | goto failed; |
||
5535 | } |
||
5536 | } |
||
5537 | else |
||
5538 | { |
||
5539 | Array.Clear( dbFileVers, 0, dbFileVers.Length );// memset( dbFileVers, 0, sizeof( dbFileVers ) ); |
||
5540 | } |
||
5541 | |||
5542 | if ( memcmp( pPager.dbFileVers, dbFileVers, dbFileVers.Length ) != 0 ) |
||
5543 | { |
||
5544 | pager_reset( pPager ); |
||
5545 | } |
||
5546 | } |
||
5547 | |||
5548 | /* If there is a WAL file in the file-system, open this database in WAL |
||
5549 | ** mode. Otherwise, the following function call is a no-op. |
||
5550 | */ |
||
5551 | rc = pagerOpenWalIfPresent( pPager ); |
||
5552 | #if !SQLITE_OMIT_WAL |
||
5553 | Debug.Assert( pPager.pWal == null || rc == SQLITE_OK ); |
||
5554 | #endif |
||
5555 | } |
||
5556 | |||
5557 | if ( pagerUseWal( pPager ) ) |
||
5558 | { |
||
5559 | Debug.Assert( rc == SQLITE_OK ); |
||
5560 | rc = pagerBeginReadTransaction( pPager ); |
||
5561 | } |
||
5562 | |||
5563 | if ( pPager.eState == PAGER_OPEN && rc == SQLITE_OK ) |
||
5564 | { |
||
5565 | rc = pagerPagecount( pPager, ref pPager.dbSize ); |
||
5566 | } |
||
5567 | |||
5568 | failed: |
||
5569 | if ( rc != SQLITE_OK ) |
||
5570 | { |
||
5571 | Debug.Assert( |
||
5572 | #if SQLITE_OMIT_MEMORYDB |
||
5573 | 0==MEMDB |
||
5574 | #else |
||
5575 | |||
5576 | #endif |
||
5577 | ); |
||
5578 | pager_unlock( pPager ); |
||
5579 | Debug.Assert( pPager.eState == PAGER_OPEN ); |
||
5580 | } |
||
5581 | else |
||
5582 | { |
||
5583 | pPager.eState = PAGER_READER; |
||
5584 | } |
||
5585 | return rc; |
||
5586 | } |
||
5587 | |||
5588 | /* |
||
5589 | ** If the reference count has reached zero, rollback any active |
||
5590 | ** transaction and unlock the pager. |
||
5591 | ** |
||
5592 | ** Except, in locking_mode=EXCLUSIVE when there is nothing to in |
||
5593 | ** the rollback journal, the unlock is not performed and there is |
||
5594 | ** nothing to rollback, so this routine is a no-op. |
||
5595 | */ |
||
5596 | static void pagerUnlockIfUnused( Pager pPager ) |
||
5597 | { |
||
5598 | if ( sqlite3PcacheRefCount( pPager.pPCache ) == 0 ) |
||
5599 | { |
||
5600 | pagerUnlockAndRollback( pPager ); |
||
5601 | } |
||
5602 | } |
||
5603 | |||
5604 | /* |
||
5605 | ** Acquire a reference to page number pgno in pager pPager (a page |
||
5606 | ** reference has type DbPage*). If the requested reference is |
||
5607 | ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. |
||
5608 | ** |
||
5609 | ** If the requested page is already in the cache, it is returned. |
||
5610 | ** Otherwise, a new page object is allocated and populated with data |
||
5611 | ** read from the database file. In some cases, the pcache module may |
||
5612 | ** choose not to allocate a new page object and may reuse an existing |
||
5613 | ** object with no outstanding references. |
||
5614 | ** |
||
5615 | ** The extra data appended to a page is always initialized to zeros the |
||
5616 | ** first time a page is loaded into memory. If the page requested is |
||
5617 | ** already in the cache when this function is called, then the extra |
||
5618 | ** data is left as it was when the page object was last used. |
||
5619 | ** |
||
5620 | ** If the database image is smaller than the requested page or if a |
||
5621 | ** non-zero value is passed as the noContent parameter and the |
||
5622 | ** requested page is not already stored in the cache, then no |
||
5623 | ** actual disk read occurs. In this case the memory image of the |
||
5624 | ** page is initialized to all zeros. |
||
5625 | ** |
||
5626 | ** If noContent is true, it means that we do not care about the contents |
||
5627 | ** of the page. This occurs in two seperate scenarios: |
||
5628 | ** |
||
5629 | ** a) When reading a free-list leaf page from the database, and |
||
5630 | ** |
||
5631 | ** b) When a savepoint is being rolled back and we need to load |
||
5632 | ** a new page into the cache to be filled with the data read |
||
5633 | ** from the savepoint journal. |
||
5634 | ** |
||
5635 | ** If noContent is true, then the data returned is zeroed instead of |
||
5636 | ** being read from the database. Additionally, the bits corresponding |
||
5637 | ** to pgno in Pager.pInJournal (bitvec of pages already written to the |
||
5638 | ** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open |
||
5639 | ** savepoints are set. This means if the page is made writable at any |
||
5640 | ** point in the future, using a call to sqlite3PagerWrite(), its contents |
||
5641 | ** will not be journaled. This saves IO. |
||
5642 | ** |
||
5643 | ** The acquisition might fail for several reasons. In all cases, |
||
5644 | ** an appropriate error code is returned and *ppPage is set to NULL. |
||
5645 | ** |
||
5646 | ** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt |
||
5647 | ** to find a page in the in-memory cache first. If the page is not already |
||
5648 | ** in memory, this routine goes to disk to read it in whereas Lookup() |
||
5649 | ** just returns 0. This routine acquires a read-lock the first time it |
||
5650 | ** has to go to disk, and could also playback an old journal if necessary. |
||
5651 | ** Since Lookup() never goes to disk, it never has to deal with locks |
||
5652 | ** or journal files. |
||
5653 | */ |
||
5654 | |||
5655 | // Under C# from the header file |
||
5656 | //#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) |
||
5657 | |||
5658 | static int sqlite3PagerGet( |
||
5659 | Pager pPager, /* The pager open on the database file */ |
||
5660 | u32 pgno, /* Page number to fetch */ |
||
5661 | ref DbPage ppPage /* Write a pointer to the page here */ |
||
5662 | ) |
||
5663 | { |
||
5664 | return sqlite3PagerAcquire( pPager, pgno, ref ppPage, 0 ); |
||
5665 | } |
||
5666 | |||
5667 | static int sqlite3PagerAcquire( |
||
5668 | Pager pPager, /* The pager open on the database file */ |
||
5669 | u32 pgno, /* Page number to fetch */ |
||
5670 | ref DbPage ppPage, /* Write a pointer to the page here */ |
||
5671 | u8 noContent /* Do not bother reading content from disk if true */ |
||
5672 | ) |
||
5673 | { |
||
5674 | int rc; |
||
5675 | PgHdr pPg = null; |
||
5676 | |||
5677 | Debug.Assert( pPager.eState >= PAGER_READER ); |
||
5678 | Debug.Assert( assert_pager_state( pPager ) ); |
||
5679 | if ( pgno == 0 ) |
||
5680 | { |
||
5681 | return SQLITE_CORRUPT_BKPT(); |
||
5682 | } |
||
5683 | |||
5684 | /* If the pager is in the error state, return an error immediately. |
||
5685 | ** Otherwise, request the page from the PCache layer. */ |
||
5686 | if ( pPager.errCode != SQLITE_OK ) |
||
5687 | { |
||
5688 | rc = pPager.errCode; |
||
5689 | } |
||
5690 | else |
||
5691 | { |
||
5692 | rc = sqlite3PcacheFetch( pPager.pPCache, pgno, 1, ref ppPage ); |
||
5693 | } |
||
5694 | |||
5695 | if ( rc != SQLITE_OK ) |
||
5696 | { |
||
5697 | /* Either the call to sqlite3PcacheFetch() returned an error or the |
||
5698 | ** pager was already in the error-state when this function was called. |
||
5699 | ** Set pPg to 0 and jump to the exception handler. */ |
||
5700 | pPg = null; |
||
5701 | goto pager_acquire_err; |
||
5702 | } |
||
5703 | Debug.Assert( ( ppPage ).pgno == pgno ); |
||
5704 | Debug.Assert( ( ppPage ).pPager == pPager || ( ppPage ).pPager == null ); |
||
5705 | |||
5706 | if ( ( ppPage ).pPager != null && 0 == noContent ) |
||
5707 | { |
||
5708 | /* In this case the pcache already contains an initialized copy of |
||
5709 | ** the page. Return without further ado. */ |
||
5710 | Debug.Assert( pgno <= PAGER_MAX_PGNO && pgno != PAGER_MJ_PGNO( pPager ) ); |
||
5711 | PAGER_INCR( ref pPager.nHit ); |
||
5712 | return SQLITE_OK; |
||
5713 | |||
5714 | } |
||
5715 | else |
||
5716 | { |
||
5717 | /* The pager cache has created a new page. Its content needs to |
||
5718 | ** be initialized. */ |
||
5719 | #if SQLITE_TEST |
||
5720 | PAGER_INCR( ref pPager.nMiss ); |
||
5721 | #endif |
||
5722 | pPg = ppPage; |
||
5723 | pPg.pPager = pPager; |
||
5724 | pPg.pExtra = new MemPage();//memset(pPg.pExtra, 0, pPager.nExtra); |
||
5725 | |||
5726 | /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page |
||
5727 | ** number greater than this, or the unused locking-page, is requested. */ |
||
5728 | if ( pgno > PAGER_MAX_PGNO || pgno == PAGER_MJ_PGNO( pPager ) ) |
||
5729 | { |
||
5730 | rc = SQLITE_CORRUPT_BKPT(); |
||
5731 | goto pager_acquire_err; |
||
5732 | } |
||
5733 | if ( |
||
5734 | #if SQLITE_OMIT_MEMORYDB |
||
5735 | 1==MEMDB |
||
5736 | #else |
||
5737 | pPager.memDb != 0 |
||
5738 | #endif |
||
5739 | || pPager.dbSize < pgno || noContent != 0 || !isOpen( pPager.fd ) ) |
||
5740 | { |
||
5741 | if ( pgno > pPager.mxPgno ) |
||
5742 | { |
||
5743 | rc = SQLITE_FULL; |
||
5744 | goto pager_acquire_err; |
||
5745 | } |
||
5746 | if ( noContent != 0 ) |
||
5747 | { |
||
5748 | /* Failure to set the bits in the InJournal bit-vectors is benign. |
||
5749 | ** It merely means that we might do some extra work to journal a |
||
5750 | ** page that does not need to be journaled. Nevertheless, be sure |
||
5751 | ** to test the case where a malloc error occurs while trying to set |
||
5752 | ** a bit in a bit vector. |
||
5753 | */ |
||
5754 | sqlite3BeginBenignMalloc(); |
||
5755 | if ( pgno <= pPager.dbOrigSize ) |
||
5756 | { |
||
5757 | #if !NDEBUG || SQLITE_COVERAGE_TEST |
||
5758 | rc = sqlite3BitvecSet( pPager.pInJournal, pgno ); //TESTONLY( rc = ) sqlite3BitvecSet(pPager.pInJournal, pgno); |
||
5759 | #else |
||
5760 | sqlite3BitvecSet(pPager.pInJournal, pgno); |
||
5761 | #endif |
||
5762 | testcase( rc == SQLITE_NOMEM ); |
||
5763 | } |
||
5764 | #if !NDEBUG || SQLITE_COVERAGE_TEST |
||
5765 | rc = addToSavepointBitvecs( pPager, pgno ); //TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); |
||
5766 | #else |
||
5767 | addToSavepointBitvecs(pPager, pgno); |
||
5768 | #endif |
||
5769 | |||
5770 | testcase( rc == SQLITE_NOMEM ); |
||
5771 | sqlite3EndBenignMalloc(); |
||
5772 | } |
||
5773 | //memset(pPg.pData, 0, pPager.pageSize); |
||
5774 | Array.Clear( pPg.pData, 0, pPager.pageSize ); |
||
5775 | IOTRACE( "ZERO %p %d\n", pPager, pgno ); |
||
5776 | } |
||
5777 | else |
||
5778 | { |
||
5779 | Debug.Assert( pPg.pPager == pPager ); |
||
5780 | rc = readDbPage( pPg ); |
||
5781 | if ( rc != SQLITE_OK ) |
||
5782 | { |
||
5783 | goto pager_acquire_err; |
||
5784 | } |
||
5785 | } |
||
5786 | |||
5787 | pager_set_pagehash( pPg ); |
||
5788 | } |
||
5789 | return SQLITE_OK; |
||
5790 | |||
5791 | pager_acquire_err: |
||
5792 | Debug.Assert( rc != SQLITE_OK ); |
||
5793 | if ( pPg != null ) |
||
5794 | { |
||
5795 | sqlite3PcacheDrop( pPg ); |
||
5796 | } |
||
5797 | pagerUnlockIfUnused( pPager ); |
||
5798 | |||
5799 | ppPage = null; |
||
5800 | return rc; |
||
5801 | } |
||
5802 | |||
5803 | /* |
||
5804 | ** Acquire a page if it is already in the in-memory cache. Do |
||
5805 | ** not read the page from disk. Return a pointer to the page, |
||
5806 | ** or 0 if the page is not in cache. |
||
5807 | ** |
||
5808 | ** See also sqlite3PagerGet(). The difference between this routine |
||
5809 | ** and sqlite3PagerGet() is that _get() will go to the disk and read |
||
5810 | ** in the page if the page is not already in cache. This routine |
||
5811 | ** returns NULL if the page is not in cache or if a disk I/O error |
||
5812 | ** has ever happened. |
||
5813 | */ |
||
5814 | static DbPage sqlite3PagerLookup( Pager pPager, u32 pgno ) |
||
5815 | { |
||
5816 | PgHdr pPg = null; |
||
5817 | |||
5818 | Debug.Assert( pPager != null ); |
||
5819 | Debug.Assert( pgno != 0 ); |
||
5820 | Debug.Assert( pPager.pPCache != null ); |
||
5821 | Debug.Assert( pPager.eState >= PAGER_READER && pPager.eState != PAGER_ERROR ); |
||
5822 | sqlite3PcacheFetch( pPager.pPCache, pgno, 0, ref pPg ); |
||
5823 | |||
5824 | return pPg; |
||
5825 | } |
||
5826 | |||
5827 | /* |
||
5828 | ** Release a page reference. |
||
5829 | ** |
||
5830 | ** If the number of references to the page drop to zero, then the |
||
5831 | ** page is added to the LRU list. When all references to all pages |
||
5832 | ** are released, a rollback occurs and the lock on the database is |
||
5833 | ** removed. |
||
5834 | */ |
||
5835 | static void sqlite3PagerUnref( DbPage pPg ) |
||
5836 | { |
||
5837 | if ( pPg != null ) |
||
5838 | { |
||
5839 | Pager pPager = pPg.pPager; |
||
5840 | sqlite3PcacheRelease( pPg ); |
||
5841 | pagerUnlockIfUnused( pPager ); |
||
5842 | } |
||
5843 | } |
||
5844 | |||
5845 | /* |
||
5846 | ** This function is called at the start of every write transaction. |
||
5847 | ** There must already be a RESERVED or EXCLUSIVE lock on the database |
||
5848 | ** file when this routine is called. |
||
5849 | ** |
||
5850 | ** Open the journal file for pager pPager and write a journal header |
||
5851 | ** to the start of it. If there are active savepoints, open the sub-journal |
||
5852 | ** as well. This function is only used when the journal file is being |
||
5853 | ** opened to write a rollback log for a transaction. It is not used |
||
5854 | ** when opening a hot journal file to roll it back. |
||
5855 | ** |
||
5856 | ** If the journal file is already open (as it may be in exclusive mode), |
||
5857 | ** then this function just writes a journal header to the start of the |
||
5858 | ** already open file. |
||
5859 | ** |
||
5860 | ** Whether or not the journal file is opened by this function, the |
||
5861 | ** Pager.pInJournal bitvec structure is allocated. |
||
5862 | ** |
||
5863 | ** Return SQLITE_OK if everything is successful. Otherwise, return |
||
5864 | ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or |
||
5865 | ** an IO error code if opening or writing the journal file fails. |
||
5866 | */ |
||
5867 | static int pager_open_journal( Pager pPager ) |
||
5868 | { |
||
5869 | int rc = SQLITE_OK; /* Return code */ |
||
5870 | sqlite3_vfs pVfs = pPager.pVfs; /* Local cache of vfs pointer */ |
||
5871 | |||
5872 | Debug.Assert( pPager.eState == PAGER_WRITER_LOCKED ); |
||
5873 | Debug.Assert( assert_pager_state( pPager ) ); |
||
5874 | Debug.Assert( pPager.pInJournal == null ); |
||
5875 | |||
5876 | /* If already in the error state, this function is a no-op. But on |
||
5877 | ** the other hand, this routine is never called if we are already in |
||
5878 | ** an error state. */ |
||
5879 | if ( NEVER( pPager.errCode ) != 0 ) |
||
5880 | return pPager.errCode; |
||
5881 | |||
5882 | if ( !pagerUseWal( pPager ) && pPager.journalMode != PAGER_JOURNALMODE_OFF ) |
||
5883 | { |
||
5884 | pPager.pInJournal = sqlite3BitvecCreate( pPager.dbSize ); |
||
5885 | //if (pPager.pInJournal == null) |
||
5886 | //{ |
||
5887 | // return SQLITE_NOMEM; |
||
5888 | //} |
||
5889 | |||
5890 | /* Open the journal file if it is not already open. */ |
||
5891 | if ( !isOpen( pPager.jfd ) ) |
||
5892 | { |
||
5893 | if ( pPager.journalMode == PAGER_JOURNALMODE_MEMORY ) |
||
5894 | { |
||
5895 | sqlite3MemJournalOpen( pPager.jfd ); |
||
5896 | } |
||
5897 | else |
||
5898 | { |
||
5899 | int flags = /* VFS flags to open journal file */ |
||
5900 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | |
||
5901 | ( pPager.tempFile ? |
||
5902 | ( SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_JOURNAL ) : |
||
5903 | ( SQLITE_OPEN_MAIN_JOURNAL ) |
||
5904 | ); |
||
5905 | #if SQLITE_ENABLE_ATOMIC_WRITE |
||
5906 | rc = sqlite3JournalOpen( |
||
5907 | pVfs, pPager.zJournal, pPager.jfd, flags, jrnlBufferSize(pPager) |
||
5908 | ); |
||
5909 | #else |
||
5910 | int int0 = 0; |
||
5911 | rc = sqlite3OsOpen( pVfs, pPager.zJournal, pPager.jfd, flags, ref int0 ); |
||
5912 | #endif |
||
5913 | } |
||
5914 | Debug.Assert( rc != SQLITE_OK || isOpen( pPager.jfd ) ); |
||
5915 | } |
||
5916 | |||
5917 | /* Write the first journal header to the journal file and open |
||
5918 | ** the sub-journal if necessary. |
||
5919 | */ |
||
5920 | if ( rc == SQLITE_OK ) |
||
5921 | { |
||
5922 | /* TODO: Check if all of these are really required. */ |
||
5923 | pPager.nRec = 0; |
||
5924 | pPager.journalOff = 0; |
||
5925 | pPager.setMaster = 0; |
||
5926 | pPager.journalHdr = 0; |
||
5927 | rc = writeJournalHdr( pPager ); |
||
5928 | } |
||
5929 | } |
||
5930 | if ( rc != SQLITE_OK ) |
||
5931 | { |
||
5932 | sqlite3BitvecDestroy( ref pPager.pInJournal ); |
||
5933 | pPager.pInJournal = null; |
||
5934 | } |
||
5935 | else |
||
5936 | { |
||
5937 | Debug.Assert( pPager.eState == PAGER_WRITER_LOCKED ); |
||
5938 | pPager.eState = PAGER_WRITER_CACHEMOD; |
||
5939 | } |
||
5940 | return rc; |
||
5941 | } |
||
5942 | |||
5943 | /* |
||
5944 | ** Begin a write-transaction on the specified pager object. If a |
||
5945 | ** write-transaction has already been opened, this function is a no-op. |
||
5946 | ** |
||
5947 | ** If the exFlag argument is false, then acquire at least a RESERVED |
||
5948 | ** lock on the database file. If exFlag is true, then acquire at least |
||
5949 | ** an EXCLUSIVE lock. If such a lock is already held, no locking |
||
5950 | ** functions need be called. |
||
5951 | ** |
||
5952 | ** If the subjInMemory argument is non-zero, then any sub-journal opened |
||
5953 | ** within this transaction will be opened as an in-memory file. This |
||
5954 | ** has no effect if the sub-journal is already opened (as it may be when |
||
5955 | ** running in exclusive mode) or if the transaction does not require a |
||
5956 | ** sub-journal. If the subjInMemory argument is zero, then any required |
||
5957 | ** sub-journal is implemented in-memory if pPager is an in-memory database, |
||
5958 | ** or using a temporary file otherwise. |
||
5959 | */ |
||
5960 | static int sqlite3PagerBegin( Pager pPager, bool exFlag, int subjInMemory ) |
||
5961 | { |
||
5962 | int rc = SQLITE_OK; |
||
5963 | if ( pPager.errCode != 0 ) |
||
5964 | return pPager.errCode; |
||
5965 | Debug.Assert( pPager.eState >= PAGER_READER && pPager.eState < PAGER_ERROR ); |
||
5966 | pPager.subjInMemory = (u8)subjInMemory; |
||
5967 | if ( ALWAYS( pPager.eState == PAGER_READER ) ) |
||
5968 | { |
||
5969 | Debug.Assert( pPager.pInJournal == null ); |
||
5970 | if ( pagerUseWal( pPager ) ) |
||
5971 | { |
||
5972 | /* If the pager is configured to use locking_mode=exclusive, and an |
||
5973 | ** exclusive lock on the database is not already held, obtain it now. |
||
5974 | */ |
||
5975 | if ( pPager.exclusiveMode && sqlite3WalExclusiveMode( pPager.pWal, -1 ) ) |
||
5976 | { |
||
5977 | rc = pagerLockDb( pPager, EXCLUSIVE_LOCK ); |
||
5978 | if ( rc != SQLITE_OK ) |
||
5979 | { |
||
5980 | return rc; |
||
5981 | } |
||
5982 | sqlite3WalExclusiveMode( pPager.pWal, 1 ); |
||
5983 | } |
||
5984 | |||
5985 | /* Grab the write lock on the log file. If successful, upgrade to |
||
5986 | ** PAGER_RESERVED state. Otherwise, return an error code to the caller. |
||
5987 | ** The busy-handler is not invoked if another connection already |
||
5988 | ** holds the write-lock. If possible, the upper layer will call it. |
||
5989 | */ |
||
5990 | rc = sqlite3WalBeginWriteTransaction( pPager.pWal ); |
||
5991 | } |
||
5992 | else |
||
5993 | { |
||
5994 | /* Obtain a RESERVED lock on the database file. If the exFlag parameter |
||
5995 | ** is true, then immediately upgrade this to an EXCLUSIVE lock. The |
||
5996 | ** busy-handler callback can be used when upgrading to the EXCLUSIVE |
||
5997 | ** lock, but not when obtaining the RESERVED lock. |
||
5998 | */ |
||
5999 | rc = pagerLockDb( pPager, RESERVED_LOCK ); |
||
6000 | if ( rc == SQLITE_OK && exFlag ) |
||
6001 | { |
||
6002 | rc = pager_wait_on_lock( pPager, EXCLUSIVE_LOCK ); |
||
6003 | } |
||
6004 | } |
||
6005 | |||
6006 | if ( rc == SQLITE_OK ) |
||
6007 | { |
||
6008 | /* Change to WRITER_LOCKED state. |
||
6009 | ** |
||
6010 | ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD |
||
6011 | ** when it has an open transaction, but never to DBMOD or FINISHED. |
||
6012 | ** This is because in those states the code to roll back savepoint |
||
6013 | ** transactions may copy data from the sub-journal into the database |
||
6014 | ** file as well as into the page cache. Which would be incorrect in |
||
6015 | ** WAL mode. |
||
6016 | */ |
||
6017 | pPager.eState = PAGER_WRITER_LOCKED; |
||
6018 | pPager.dbHintSize = pPager.dbSize; |
||
6019 | pPager.dbFileSize = pPager.dbSize; |
||
6020 | pPager.dbOrigSize = pPager.dbSize; |
||
6021 | pPager.journalOff = 0; |
||
6022 | } |
||
6023 | |||
6024 | Debug.Assert( rc == SQLITE_OK || pPager.eState == PAGER_READER ); |
||
6025 | Debug.Assert( rc != SQLITE_OK || pPager.eState == PAGER_WRITER_LOCKED ); |
||
6026 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6027 | } |
||
6028 | |||
6029 | PAGERTRACE( "TRANSACTION %d\n", PAGERID( pPager ) ); |
||
6030 | return rc; |
||
6031 | } |
||
6032 | |||
6033 | |||
6034 | /* |
||
6035 | ** Mark a single data page as writeable. The page is written into the |
||
6036 | ** main journal or sub-journal as required. If the page is written into |
||
6037 | ** one of the journals, the corresponding bit is set in the |
||
6038 | ** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs |
||
6039 | ** of any open savepoints as appropriate. |
||
6040 | */ |
||
6041 | static int pager_write( PgHdr pPg ) |
||
6042 | { |
||
6043 | byte[] pData = pPg.pData; |
||
6044 | Pager pPager = pPg.pPager; |
||
6045 | int rc = SQLITE_OK; |
||
6046 | |||
6047 | /* This routine is not called unless a write-transaction has already |
||
6048 | ** been started. The journal file may or may not be open at this point. |
||
6049 | ** It is never called in the ERROR state. |
||
6050 | */ |
||
6051 | Debug.Assert( pPager.eState == PAGER_WRITER_LOCKED |
||
6052 | || pPager.eState == PAGER_WRITER_CACHEMOD |
||
6053 | || pPager.eState == PAGER_WRITER_DBMOD |
||
6054 | ); |
||
6055 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6056 | |||
6057 | /* If an error has been previously detected, report the same error |
||
6058 | ** again. This should not happen, but the check provides robustness. */ |
||
6059 | if ( NEVER( pPager.errCode ) != 0 ) |
||
6060 | return pPager.errCode; |
||
6061 | |||
6062 | /* Higher-level routines never call this function if database is not |
||
6063 | ** writable. But check anyway, just for robustness. */ |
||
6064 | if ( NEVER( pPager.readOnly ) ) |
||
6065 | return SQLITE_PERM; |
||
6066 | |||
6067 | #if SQLITE_CHECK_PAGES |
||
6068 | CHECK_PAGE(pPg); |
||
6069 | #endif |
||
6070 | /* The journal file needs to be opened. Higher level routines have already |
||
6071 | ** obtained the necessary locks to begin the write-transaction, but the |
||
6072 | ** rollback journal might not yet be open. Open it now if this is the case. |
||
6073 | ** |
||
6074 | ** This is done before calling sqlite3PcacheMakeDirty() on the page. |
||
6075 | ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then |
||
6076 | ** an error might occur and the pager would end up in WRITER_LOCKED state |
||
6077 | ** with pages marked as dirty in the cache. |
||
6078 | */ |
||
6079 | if ( pPager.eState == PAGER_WRITER_LOCKED ) |
||
6080 | { |
||
6081 | rc = pager_open_journal( pPager ); |
||
6082 | if ( rc != SQLITE_OK ) |
||
6083 | return rc; |
||
6084 | } |
||
6085 | Debug.Assert( pPager.eState >= PAGER_WRITER_CACHEMOD ); |
||
6086 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6087 | |||
6088 | /* Mark the page as dirty. If the page has already been written |
||
6089 | ** to the journal then we can return right away. |
||
6090 | */ |
||
6091 | sqlite3PcacheMakeDirty( pPg ); |
||
6092 | if ( pageInJournal( pPg ) && !subjRequiresPage( pPg ) ) |
||
6093 | { |
||
6094 | Debug.Assert( !pagerUseWal( pPager ) ); |
||
6095 | } |
||
6096 | else |
||
6097 | { |
||
6098 | /* The transaction journal now exists and we have a RESERVED or an |
||
6099 | ** EXCLUSIVE lock on the main database file. Write the current page to |
||
6100 | ** the transaction journal if it is not there already. |
||
6101 | */ |
||
6102 | if ( !pageInJournal( pPg ) && !pagerUseWal( pPager ) ) |
||
6103 | { |
||
6104 | Debug.Assert( pagerUseWal( pPager ) == false ); |
||
6105 | if ( pPg.pgno <= pPager.dbOrigSize && isOpen( pPager.jfd ) ) |
||
6106 | { |
||
6107 | u32 cksum; |
||
6108 | byte[] pData2 = null; |
||
6109 | i64 iOff = pPager.journalOff; |
||
6110 | |||
6111 | /* We should never write to the journal file the page that |
||
6112 | ** contains the database locks. The following Debug.Assert verifies |
||
6113 | ** that we do not. */ |
||
6114 | Debug.Assert( pPg.pgno != ( ( PENDING_BYTE / ( pPager.pageSize ) ) + 1 ) );//PAGER_MJ_PGNO(pPager) ); |
||
6115 | |||
6116 | Debug.Assert( pPager.journalHdr <= pPager.journalOff ); |
||
6117 | if ( CODEC2( pPager, pData, pPg.pgno, SQLITE_ENCRYPT_READ_CTX, ref pData2 ) ) |
||
6118 | return SQLITE_NOMEM; // CODEC2(pPager, pData, pPg.pgno, 7, return SQLITE_NOMEM, pData2); |
||
6119 | cksum = pager_cksum( pPager, pData2 ); |
||
6120 | |||
6121 | /* Even if an IO or diskfull error occurred while journalling the |
||
6122 | ** page in the block above, set the need-sync flag for the page. |
||
6123 | ** Otherwise, when the transaction is rolled back, the logic in |
||
6124 | ** playback_one_page() will think that the page needs to be restored |
||
6125 | ** in the database file. And if an IO error occurs while doing so, |
||
6126 | ** then corruption may follow. |
||
6127 | */ |
||
6128 | |||
6129 | pPg.flags |= PGHDR_NEED_SYNC; |
||
6130 | |||
6131 | rc = write32bits( pPager.jfd, iOff, pPg.pgno ); |
||
6132 | if ( rc != SQLITE_OK ) |
||
6133 | return rc; |
||
6134 | rc = sqlite3OsWrite( pPager.jfd, pData2, pPager.pageSize, iOff + 4 ); |
||
6135 | if ( rc != SQLITE_OK ) |
||
6136 | return rc; |
||
6137 | rc = write32bits( pPager.jfd, iOff + pPager.pageSize + 4, cksum ); |
||
6138 | if ( rc != SQLITE_OK ) |
||
6139 | return rc; |
||
6140 | |||
6141 | IOTRACE( "JOUT %p %d %lld %d\n", pPager, pPg.pgno, |
||
6142 | pPager.journalOff, pPager.pageSize ); |
||
6143 | #if SQLITE_TEST |
||
6144 | #if !TCLSH |
||
6145 | PAGER_INCR( ref sqlite3_pager_writej_count ); |
||
6146 | #else |
||
6147 | int iValue = sqlite3_pager_writej_count.iValue; |
||
6148 | PAGER_INCR( ref iValue ); |
||
6149 | sqlite3_pager_writej_count.iValue = iValue; |
||
6150 | #endif |
||
6151 | #endif |
||
6152 | PAGERTRACE( "JOURNAL %d page %d needSync=%d hash(%08x)\n", |
||
6153 | PAGERID( pPager ), pPg.pgno, |
||
6154 | ( ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ? 1 : 0 ), pager_pagehash( pPg ) ); |
||
6155 | |||
6156 | pPager.journalOff += 8 + pPager.pageSize; |
||
6157 | pPager.nRec++; |
||
6158 | Debug.Assert( pPager.pInJournal != null ); |
||
6159 | rc = sqlite3BitvecSet( pPager.pInJournal, pPg.pgno ); |
||
6160 | testcase( rc == SQLITE_NOMEM ); |
||
6161 | Debug.Assert( rc == SQLITE_OK || rc == SQLITE_NOMEM ); |
||
6162 | rc |= addToSavepointBitvecs( pPager, pPg.pgno ); |
||
6163 | if ( rc != SQLITE_OK ) |
||
6164 | { |
||
6165 | Debug.Assert( rc == SQLITE_NOMEM ); |
||
6166 | return rc; |
||
6167 | } |
||
6168 | } |
||
6169 | else |
||
6170 | { |
||
6171 | if ( pPager.eState != PAGER_WRITER_DBMOD ) |
||
6172 | { |
||
6173 | pPg.flags |= PGHDR_NEED_SYNC; |
||
6174 | } |
||
6175 | PAGERTRACE( "APPEND %d page %d needSync=%d\n", |
||
6176 | PAGERID( pPager ), pPg.pgno, |
||
6177 | ( ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ? 1 : 0 ) ); |
||
6178 | } |
||
6179 | } |
||
6180 | |||
6181 | /* If the statement journal is open and the page is not in it, |
||
6182 | ** then write the current page to the statement journal. Note that |
||
6183 | ** the statement journal format differs from the standard journal format |
||
6184 | ** in that it omits the checksums and the header. |
||
6185 | */ |
||
6186 | if ( subjRequiresPage( pPg ) ) |
||
6187 | { |
||
6188 | rc = subjournalPage( pPg ); |
||
6189 | } |
||
6190 | } |
||
6191 | |||
6192 | /* Update the database size and return. |
||
6193 | */ |
||
6194 | if ( pPager.dbSize < pPg.pgno ) |
||
6195 | { |
||
6196 | pPager.dbSize = pPg.pgno; |
||
6197 | } |
||
6198 | return rc; |
||
6199 | } |
||
6200 | |||
6201 | /* |
||
6202 | ** Mark a data page as writeable. This routine must be called before |
||
6203 | ** making changes to a page. The caller must check the return value |
||
6204 | ** of this function and be careful not to change any page data unless |
||
6205 | ** this routine returns SQLITE_OK. |
||
6206 | ** |
||
6207 | ** The difference between this function and pager_write() is that this |
||
6208 | ** function also deals with the special case where 2 or more pages |
||
6209 | ** fit on a single disk sector. In this case all co-resident pages |
||
6210 | ** must have been written to the journal file before returning. |
||
6211 | ** |
||
6212 | ** If an error occurs, SQLITE_NOMEM or an IO error code is returned |
||
6213 | ** as appropriate. Otherwise, SQLITE_OK. |
||
6214 | */ |
||
6215 | static int sqlite3PagerWrite( DbPage pDbPage ) |
||
6216 | { |
||
6217 | int rc = SQLITE_OK; |
||
6218 | |||
6219 | PgHdr pPg = pDbPage; |
||
6220 | Pager pPager = pPg.pPager; |
||
6221 | u32 nPagePerSector = (u32)( pPager.sectorSize / pPager.pageSize ); |
||
6222 | |||
6223 | Debug.Assert( pPager.eState >= PAGER_WRITER_LOCKED ); |
||
6224 | Debug.Assert( pPager.eState != PAGER_ERROR ); |
||
6225 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6226 | |||
6227 | if ( nPagePerSector > 1 ) |
||
6228 | { |
||
6229 | Pgno nPageCount = 0; /* Total number of pages in database file */ |
||
6230 | Pgno pg1; /* First page of the sector pPg is located on. */ |
||
6231 | Pgno nPage = 0; /* Number of pages starting at pg1 to journal */ |
||
6232 | int ii; /* Loop counter */ |
||
6233 | bool needSync = false; /* True if any page has PGHDR_NEED_SYNC */ |
||
6234 | |||
6235 | /* Set the doNotSyncSpill flag to 1. This is because we cannot allow |
||
6236 | ** a journal header to be written between the pages journaled by |
||
6237 | ** this function. |
||
6238 | */ |
||
6239 | Debug.Assert( |
||
6240 | #if SQLITE_OMIT_MEMORYDB |
||
6241 | 0==MEMDB |
||
6242 | #else |
||
6243 | |||
6244 | #endif |
||
6245 | ); |
||
6246 | Debug.Assert( pPager.doNotSyncSpill == 0 ); |
||
6247 | pPager.doNotSyncSpill++; |
||
6248 | |||
6249 | /* This trick assumes that both the page-size and sector-size are |
||
6250 | ** an integer power of 2. It sets variable pg1 to the identifier |
||
6251 | ** of the first page of the sector pPg is located on. |
||
6252 | */ |
||
6253 | pg1 = (u32)( ( pPg.pgno - 1 ) & ~( nPagePerSector - 1 ) ) + 1; |
||
6254 | |||
6255 | nPageCount = pPager.dbSize; |
||
6256 | if ( pPg.pgno > nPageCount ) |
||
6257 | { |
||
6258 | nPage = ( pPg.pgno - pg1 ) + 1; |
||
6259 | } |
||
6260 | else if ( ( pg1 + nPagePerSector - 1 ) > nPageCount ) |
||
6261 | { |
||
6262 | nPage = nPageCount + 1 - pg1; |
||
6263 | } |
||
6264 | else |
||
6265 | { |
||
6266 | nPage = nPagePerSector; |
||
6267 | } |
||
6268 | Debug.Assert( nPage > 0 ); |
||
6269 | Debug.Assert( pg1 <= pPg.pgno ); |
||
6270 | Debug.Assert( ( pg1 + nPage ) > pPg.pgno ); |
||
6271 | |||
6272 | for ( ii = 0; ii < nPage && rc == SQLITE_OK; ii++ ) |
||
6273 | { |
||
6274 | u32 pg = (u32)( pg1 + ii ); |
||
6275 | PgHdr pPage = new PgHdr(); |
||
6276 | if ( pg == pPg.pgno || sqlite3BitvecTest( pPager.pInJournal, pg ) == 0 ) |
||
6277 | { |
||
6278 | if ( pg != ( ( PENDING_BYTE / ( pPager.pageSize ) ) + 1 ) ) //PAGER_MJ_PGNO(pPager)) |
||
6279 | { |
||
6280 | rc = sqlite3PagerGet( pPager, pg, ref pPage ); |
||
6281 | if ( rc == SQLITE_OK ) |
||
6282 | { |
||
6283 | rc = pager_write( pPage ); |
||
6284 | if ( ( pPage.flags & PGHDR_NEED_SYNC ) != 0 ) |
||
6285 | { |
||
6286 | needSync = true; |
||
6287 | } |
||
6288 | sqlite3PagerUnref( pPage ); |
||
6289 | } |
||
6290 | } |
||
6291 | } |
||
6292 | else if ( ( pPage = pager_lookup( pPager, pg ) ) != null ) |
||
6293 | { |
||
6294 | if ( ( pPage.flags & PGHDR_NEED_SYNC ) != 0 ) |
||
6295 | { |
||
6296 | needSync = true; |
||
6297 | } |
||
6298 | sqlite3PagerUnref( pPage ); |
||
6299 | } |
||
6300 | } |
||
6301 | |||
6302 | /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages |
||
6303 | ** starting at pg1, then it needs to be set for all of them. Because |
||
6304 | ** writing to any of these nPage pages may damage the others, the |
||
6305 | ** journal file must contain sync()ed copies of all of them |
||
6306 | ** before any of them can be written out to the database file. |
||
6307 | */ |
||
6308 | if ( rc == SQLITE_OK && needSync ) |
||
6309 | { |
||
6310 | Debug.Assert( |
||
6311 | #if SQLITE_OMIT_MEMORYDB |
||
6312 | 0==MEMDB |
||
6313 | #else |
||
6314 | |||
6315 | #endif |
||
6316 | ); |
||
6317 | for ( ii = 0; ii < nPage; ii++ ) |
||
6318 | { |
||
6319 | PgHdr pPage = pager_lookup( pPager, (u32)( pg1 + ii ) ); |
||
6320 | if ( pPage != null ) |
||
6321 | { |
||
6322 | pPage.flags |= PGHDR_NEED_SYNC; |
||
6323 | sqlite3PagerUnref( pPage ); |
||
6324 | } |
||
6325 | } |
||
6326 | } |
||
6327 | |||
6328 | Debug.Assert( pPager.doNotSyncSpill == 1 ); |
||
6329 | pPager.doNotSyncSpill--; |
||
6330 | } |
||
6331 | else |
||
6332 | { |
||
6333 | rc = pager_write( pDbPage ); |
||
6334 | } |
||
6335 | return rc; |
||
6336 | } |
||
6337 | |||
6338 | /* |
||
6339 | ** Return TRUE if the page given in the argument was previously passed |
||
6340 | ** to sqlite3PagerWrite(). In other words, return TRUE if it is ok |
||
6341 | ** to change the content of the page. |
||
6342 | */ |
||
6343 | #if !NDEBUG |
||
6344 | static bool sqlite3PagerIswriteable( DbPage pPg ) |
||
6345 | { |
||
6346 | return ( pPg.flags & PGHDR_DIRTY ) != 0; |
||
6347 | } |
||
6348 | #else |
||
6349 | static bool sqlite3PagerIswriteable( DbPage pPg ) { return true; } |
||
6350 | #endif |
||
6351 | |||
6352 | /* |
||
6353 | ** A call to this routine tells the pager that it is not necessary to |
||
6354 | ** write the information on page pPg back to the disk, even though |
||
6355 | ** that page might be marked as dirty. This happens, for example, when |
||
6356 | ** the page has been added as a leaf of the freelist and so its |
||
6357 | ** content no longer matters. |
||
6358 | ** |
||
6359 | ** The overlying software layer calls this routine when all of the data |
||
6360 | ** on the given page is unused. The pager marks the page as clean so |
||
6361 | ** that it does not get written to disk. |
||
6362 | ** |
||
6363 | ** Tests show that this optimization can quadruple the speed of large |
||
6364 | ** DELETE operations. |
||
6365 | */ |
||
6366 | static void sqlite3PagerDontWrite( PgHdr pPg ) |
||
6367 | { |
||
6368 | Pager pPager = pPg.pPager; |
||
6369 | |||
6370 | if ( ( pPg.flags & PGHDR_DIRTY ) != 0 && pPager.nSavepoint == 0 ) |
||
6371 | { |
||
6372 | PAGERTRACE( "DONT_WRITE page %d of %d\n", pPg.pgno, PAGERID( pPager ) ); |
||
6373 | IOTRACE( "CLEAN %p %d\n", pPager, pPg.pgno ); |
||
6374 | pPg.flags |= PGHDR_DONT_WRITE; |
||
6375 | pager_set_pagehash( pPg ); |
||
6376 | } |
||
6377 | } |
||
6378 | |||
6379 | /* |
||
6380 | ** This routine is called to increment the value of the database file |
||
6381 | ** change-counter, stored as a 4-byte big-endian integer starting at |
||
6382 | ** byte offset 24 of the pager file. The secondary change counter at |
||
6383 | ** 92 is also updated, as is the SQLite version number at offset 96. |
||
6384 | ** |
||
6385 | ** But this only happens if the pPager.changeCountDone flag is false. |
||
6386 | ** To avoid excess churning of page 1, the update only happens once. |
||
6387 | ** See also the pager_write_changecounter() routine that does an |
||
6388 | ** unconditional update of the change counters. |
||
6389 | ** |
||
6390 | ** If the isDirectMode flag is zero, then this is done by calling |
||
6391 | ** sqlite3PagerWrite() on page 1, then modifying the contents of the |
||
6392 | ** page data. In this case the file will be updated when the current |
||
6393 | ** transaction is committed. |
||
6394 | ** |
||
6395 | ** The isDirectMode flag may only be non-zero if the library was compiled |
||
6396 | ** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, |
||
6397 | ** if isDirect is non-zero, then the database file is updated directly |
||
6398 | ** by writing an updated version of page 1 using a call to the |
||
6399 | ** sqlite3OsWrite() function. |
||
6400 | */ |
||
6401 | static int pager_incr_changecounter( Pager pPager, bool isDirectMode ) |
||
6402 | { |
||
6403 | int rc = SQLITE_OK; |
||
6404 | |||
6405 | Debug.Assert( pPager.eState == PAGER_WRITER_CACHEMOD |
||
6406 | || pPager.eState == PAGER_WRITER_DBMOD |
||
6407 | ); |
||
6408 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6409 | |||
6410 | /* Declare and initialize constant integer 'isDirect'. If the |
||
6411 | ** atomic-write optimization is enabled in this build, then isDirect |
||
6412 | ** is initialized to the value passed as the isDirectMode parameter |
||
6413 | ** to this function. Otherwise, it is always set to zero. |
||
6414 | ** |
||
6415 | ** The idea is that if the atomic-write optimization is not |
||
6416 | ** enabled at compile time, the compiler can omit the tests of |
||
6417 | ** 'isDirect' below, as well as the block enclosed in the |
||
6418 | ** "if( isDirect )" condition. |
||
6419 | */ |
||
6420 | #if !SQLITE_ENABLE_ATOMIC_WRITE |
||
6421 | //# define DIRECT_MODE 0 |
||
6422 | bool DIRECT_MODE = false; |
||
6423 | Debug.Assert( isDirectMode == false ); |
||
6424 | UNUSED_PARAMETER( isDirectMode ); |
||
6425 | #else |
||
6426 | //# define DIRECT_MODE isDirectMode |
||
6427 | int DIRECT_MODE = isDirectMode; |
||
6428 | #endif |
||
6429 | |||
6430 | if ( !pPager.changeCountDone && pPager.dbSize > 0 ) |
||
6431 | { |
||
6432 | PgHdr pPgHdr = null; /* Reference to page 1 */ |
||
6433 | |||
6434 | Debug.Assert( !pPager.tempFile && isOpen( pPager.fd ) ); |
||
6435 | |||
6436 | /* Open page 1 of the file for writing. */ |
||
6437 | rc = sqlite3PagerGet( pPager, 1, ref pPgHdr ); |
||
6438 | Debug.Assert( pPgHdr == null || rc == SQLITE_OK ); |
||
6439 | |||
6440 | /* If page one was fetched successfully, and this function is not |
||
6441 | ** operating in direct-mode, make page 1 writable. When not in |
||
6442 | ** direct mode, page 1 is always held in cache and hence the PagerGet() |
||
6443 | ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. |
||
6444 | */ |
||
6445 | if ( !DIRECT_MODE && ALWAYS( rc == SQLITE_OK ) ) |
||
6446 | { |
||
6447 | rc = sqlite3PagerWrite( pPgHdr ); |
||
6448 | } |
||
6449 | |||
6450 | if ( rc == SQLITE_OK ) |
||
6451 | { |
||
6452 | /* Actually do the update of the change counter */ |
||
6453 | pager_write_changecounter( pPgHdr ); |
||
6454 | |||
6455 | /* If running in direct mode, write the contents of page 1 to the file. */ |
||
6456 | if ( DIRECT_MODE ) |
||
6457 | { |
||
6458 | u8[] zBuf = null; |
||
6459 | Debug.Assert( pPager.dbFileSize > 0 ); |
||
6460 | if ( CODEC2( pPager, pPgHdr.pData, 1, SQLITE_ENCRYPT_WRITE_CTX, ref zBuf ) ) |
||
6461 | return rc = SQLITE_NOMEM;//CODEC2(pPager, pPgHdr.pData, 1, 6, rc=SQLITE_NOMEM, zBuf); |
||
6462 | if ( rc == SQLITE_OK ) |
||
6463 | { |
||
6464 | rc = sqlite3OsWrite( pPager.fd, zBuf, pPager.pageSize, 0 ); |
||
6465 | } |
||
6466 | |||
6467 | if ( rc == SQLITE_OK ) |
||
6468 | { |
||
6469 | pPager.changeCountDone = true; |
||
6470 | } |
||
6471 | } |
||
6472 | else |
||
6473 | { |
||
6474 | pPager.changeCountDone = true; |
||
6475 | } |
||
6476 | } |
||
6477 | |||
6478 | /* Release the page reference. */ |
||
6479 | sqlite3PagerUnref( pPgHdr ); |
||
6480 | } |
||
6481 | return rc; |
||
6482 | } |
||
6483 | |||
6484 | /* |
||
6485 | ** Sync the database file to disk. This is a no-op for in-memory databases |
||
6486 | ** or pages with the Pager.noSync flag set. |
||
6487 | ** |
||
6488 | ** If successful, or if called on a pager for which it is a no-op, this |
||
6489 | ** function returns SQLITE_OK. Otherwise, an IO error code is returned. |
||
6490 | */ |
||
6491 | static int sqlite3PagerSync( Pager pPager ) |
||
6492 | { |
||
6493 | long rc = SQLITE_OK; |
||
6494 | if ( !pPager.noSync ) |
||
6495 | { |
||
6496 | Debug.Assert( |
||
6497 | #if SQLITE_OMIT_MEMORYDB |
||
6498 | |||
6499 | #else |
||
6500 | |||
6501 | #endif |
||
6502 | ); |
||
6503 | rc = sqlite3OsSync( pPager.fd, pPager.syncFlags ); |
||
6504 | } |
||
6505 | else if ( isOpen( pPager.fd ) ) |
||
6506 | { |
||
6507 | Debug.Assert( |
||
6508 | #if SQLITE_OMIT_MEMORYDB |
||
6509 | |||
6510 | #else |
||
6511 | |||
6512 | #endif |
||
6513 | ); |
||
6514 | sqlite3OsFileControl( pPager.fd, SQLITE_FCNTL_SYNC_OMITTED, ref rc ); |
||
6515 | } |
||
6516 | return (int)rc; |
||
6517 | } |
||
6518 | |||
6519 | /* |
||
6520 | ** This function may only be called while a write-transaction is active in |
||
6521 | ** rollback. If the connection is in WAL mode, this call is a no-op. |
||
6522 | ** Otherwise, if the connection does not already have an EXCLUSIVE lock on |
||
6523 | ** the database file, an attempt is made to obtain one. |
||
6524 | ** |
||
6525 | ** If the EXCLUSIVE lock is already held or the attempt to obtain it is |
||
6526 | ** successful, or the connection is in WAL mode, SQLITE_OK is returned. |
||
6527 | ** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is |
||
6528 | ** returned. |
||
6529 | */ |
||
6530 | static int sqlite3PagerExclusiveLock( Pager pPager ) |
||
6531 | { |
||
6532 | int rc = SQLITE_OK; |
||
6533 | Debug.Assert( pPager.eState == PAGER_WRITER_CACHEMOD |
||
6534 | || pPager.eState == PAGER_WRITER_DBMOD |
||
6535 | || pPager.eState == PAGER_WRITER_LOCKED |
||
6536 | ); |
||
6537 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6538 | if ( false == pagerUseWal( pPager ) ) |
||
6539 | { |
||
6540 | rc = pager_wait_on_lock( pPager, EXCLUSIVE_LOCK ); |
||
6541 | } |
||
6542 | return rc; |
||
6543 | } |
||
6544 | |||
6545 | /* |
||
6546 | ** Sync the database file for the pager pPager. zMaster points to the name |
||
6547 | ** of a master journal file that should be written into the individual |
||
6548 | ** journal file. zMaster may be NULL, which is interpreted as no master |
||
6549 | ** journal (a single database transaction). |
||
6550 | ** |
||
6551 | ** This routine ensures that: |
||
6552 | ** |
||
6553 | ** * The database file change-counter is updated, |
||
6554 | ** * the journal is synced (unless the atomic-write optimization is used), |
||
6555 | ** * all dirty pages are written to the database file, |
||
6556 | ** * the database file is truncated (if required), and |
||
6557 | ** * the database file synced. |
||
6558 | ** |
||
6559 | ** The only thing that remains to commit the transaction is to finalize |
||
6560 | ** (delete, truncate or zero the first part of) the journal file (or |
||
6561 | ** delete the master journal file if specified). |
||
6562 | ** |
||
6563 | ** Note that if zMaster==NULL, this does not overwrite a previous value |
||
6564 | ** passed to an sqlite3PagerCommitPhaseOne() call. |
||
6565 | ** |
||
6566 | ** If the final parameter - noSync - is true, then the database file itself |
||
6567 | ** is not synced. The caller must call sqlite3PagerSync() directly to |
||
6568 | ** sync the database file before calling CommitPhaseTwo() to delete the |
||
6569 | ** journal file in this case. |
||
6570 | */ |
||
6571 | static int sqlite3PagerCommitPhaseOne( |
||
6572 | Pager pPager, /* Pager object */ |
||
6573 | string zMaster, /* If not NULL, the master journal name */ |
||
6574 | bool noSync /* True to omit the xSync on the db file */ |
||
6575 | ) |
||
6576 | { |
||
6577 | int rc = SQLITE_OK; /* Return code */ |
||
6578 | |||
6579 | Debug.Assert( pPager.eState == PAGER_WRITER_LOCKED |
||
6580 | || pPager.eState == PAGER_WRITER_CACHEMOD |
||
6581 | || pPager.eState == PAGER_WRITER_DBMOD |
||
6582 | || pPager.eState == PAGER_ERROR |
||
6583 | ); |
||
6584 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6585 | |||
6586 | /* If a prior error occurred, report that error again. */ |
||
6587 | if ( NEVER( pPager.errCode != 0 ) ) |
||
6588 | return pPager.errCode; |
||
6589 | |||
6590 | PAGERTRACE( "DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", |
||
6591 | pPager.zFilename, zMaster, pPager.dbSize ); |
||
6592 | |||
6593 | /* If no database changes have been made, return early. */ |
||
6594 | if ( pPager.eState < PAGER_WRITER_CACHEMOD ) |
||
6595 | return SQLITE_OK; |
||
6596 | |||
6597 | if ( |
||
6598 | #if SQLITE_OMIT_MEMORYDB |
||
6599 | |||
6600 | #else |
||
6601 | |||
6602 | #endif |
||
6603 | ) |
||
6604 | { |
||
6605 | /* If this is an in-memory db, or no pages have been written to, or this |
||
6606 | ** function has already been called, it is mostly a no-op. However, any |
||
6607 | ** backup in progress needs to be restarted. |
||
6608 | */ |
||
6609 | sqlite3BackupRestart( pPager.pBackup ); |
||
6610 | } |
||
6611 | else |
||
6612 | { |
||
6613 | if ( pagerUseWal( pPager ) ) |
||
6614 | { |
||
6615 | PgHdr pList = sqlite3PcacheDirtyList( pPager.pPCache ); |
||
6616 | PgHdr pPageOne = null; |
||
6617 | if ( pList == null ) |
||
6618 | { |
||
6619 | /* Must have at least one page for the WAL commit flag. |
||
6620 | ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2null11-null5-18 */ |
||
6621 | rc = sqlite3PagerGet( pPager, 1, ref pPageOne ); |
||
6622 | pList = pPageOne; |
||
6623 | pList.pDirty = null; |
||
6624 | } |
||
6625 | Debug.Assert( rc == SQLITE_OK ); |
||
6626 | if ( ALWAYS( pList ) ) |
||
6627 | { |
||
6628 | |||
6629 | rc = pagerWalFrames( pPager, pList, pPager.dbSize, 1, |
||
6630 | ( pPager.fullSync ? pPager.syncFlags : (byte)0 ) |
||
6631 | ); |
||
6632 | } |
||
6633 | sqlite3PagerUnref( pPageOne ); |
||
6634 | if ( rc == SQLITE_OK ) |
||
6635 | { |
||
6636 | sqlite3PcacheCleanAll( pPager.pPCache ); |
||
6637 | } |
||
6638 | } |
||
6639 | else |
||
6640 | { |
||
6641 | |||
6642 | /* The following block updates the change-counter. Exactly how it |
||
6643 | ** does this depends on whether or not the atomic-update optimization |
||
6644 | ** was enabled at compile time, and if this transaction meets the |
||
6645 | ** runtime criteria to use the operation: |
||
6646 | ** |
||
6647 | ** * The file-system supports the atomic-write property for |
||
6648 | ** blocks of size page-size, and |
||
6649 | ** * This commit is not part of a multi-file transaction, and |
||
6650 | ** * Exactly one page has been modified and store in the journal file. |
||
6651 | ** |
||
6652 | ** If the optimization was not enabled at compile time, then the |
||
6653 | ** pager_incr_changecounter() function is called to update the change |
||
6654 | ** counter in 'indirect-mode'. If the optimization is compiled in but |
||
6655 | ** is not applicable to this transaction, call sqlite3JournalCreate() |
||
6656 | ** to make sure the journal file has actually been created, then call |
||
6657 | ** pager_incr_changecounter() to update the change-counter in indirect |
||
6658 | ** mode. |
||
6659 | ** |
||
6660 | ** Otherwise, if the optimization is both enabled and applicable, |
||
6661 | ** then call pager_incr_changecounter() to update the change-counter |
||
6662 | ** in 'direct' mode. In this case the journal file will never be |
||
6663 | ** created for this transaction. |
||
6664 | */ |
||
6665 | #if SQLITE_ENABLE_ATOMIC_WRITE |
||
6666 | PgHdr *pPg; |
||
6667 | Debug.Assert( isOpen(pPager.jfd) |
||
6668 | || pPager.journalMode==PAGER_JOURNALMODE_OFF |
||
6669 | || pPager.journalMode==PAGER_JOURNALMODE_WAL |
||
6670 | ); |
||
6671 | if( !zMaster && isOpen(pPager.jfd) |
||
6672 | && pPager.journalOff==jrnlBufferSize(pPager) |
||
6673 | && pPager.dbSize>=pPager.dbOrigSize |
||
6674 | && (0==(pPg = sqlite3PcacheDirtyList(pPager.pPCache)) || 0==pPg.pDirty) |
||
6675 | ){ |
||
6676 | /* Update the db file change counter via the direct-write method. The |
||
6677 | ** following call will modify the in-memory representation of page 1 |
||
6678 | ** to include the updated change counter and then write page 1 |
||
6679 | ** directly to the database file. Because of the atomic-write |
||
6680 | ** property of the host file-system, this is safe. |
||
6681 | */ |
||
6682 | rc = pager_incr_changecounter(pPager, 1); |
||
6683 | }else{ |
||
6684 | rc = sqlite3JournalCreate(pPager.jfd); |
||
6685 | if( rc==SQLITE_OK ){ |
||
6686 | rc = pager_incr_changecounter(pPager, 0); |
||
6687 | } |
||
6688 | } |
||
6689 | #else |
||
6690 | rc = pager_incr_changecounter( pPager, false ); |
||
6691 | #endif |
||
6692 | if ( rc != SQLITE_OK ) |
||
6693 | goto commit_phase_one_exit; |
||
6694 | |||
6695 | /* If this transaction has made the database smaller, then all pages |
||
6696 | ** being discarded by the truncation must be written to the journal |
||
6697 | ** file. This can only happen in auto-vacuum mode. |
||
6698 | ** |
||
6699 | ** Before reading the pages with page numbers larger than the |
||
6700 | ** current value of Pager.dbSize, set dbSize back to the value |
||
6701 | ** that it took at the start of the transaction. Otherwise, the |
||
6702 | ** calls to sqlite3PagerGet() return zeroed pages instead of |
||
6703 | ** reading data from the database file. |
||
6704 | */ |
||
6705 | #if !SQLITE_OMIT_AUTOVACUUM |
||
6706 | if ( pPager.dbSize < pPager.dbOrigSize |
||
6707 | && pPager.journalMode != PAGER_JOURNALMODE_OFF |
||
6708 | ) |
||
6709 | { |
||
6710 | Pgno i; /* Iterator variable */ |
||
6711 | Pgno iSkip = PAGER_MJ_PGNO( pPager ); /* Pending lock page */ |
||
6712 | Pgno dbSize = pPager.dbSize; /* Database image size */ |
||
6713 | pPager.dbSize = pPager.dbOrigSize; |
||
6714 | for ( i = dbSize + 1; i <= pPager.dbOrigSize; i++ ) |
||
6715 | { |
||
6716 | if ( 0 == sqlite3BitvecTest( pPager.pInJournal, i ) && i != iSkip ) |
||
6717 | { |
||
6718 | PgHdr pPage = null; /* Page to journal */ |
||
6719 | rc = sqlite3PagerGet( pPager, i, ref pPage ); |
||
6720 | if ( rc != SQLITE_OK ) |
||
6721 | goto commit_phase_one_exit; |
||
6722 | rc = sqlite3PagerWrite( pPage ); |
||
6723 | sqlite3PagerUnref( pPage ); |
||
6724 | if ( rc != SQLITE_OK ) |
||
6725 | goto commit_phase_one_exit; |
||
6726 | } |
||
6727 | } |
||
6728 | pPager.dbSize = dbSize; |
||
6729 | } |
||
6730 | #endif |
||
6731 | |||
6732 | /* Write the master journal name into the journal file. If a master |
||
6733 | ** journal file name has already been written to the journal file, |
||
6734 | ** or if zMaster is NULL (no master journal), then this call is a no-op. |
||
6735 | */ |
||
6736 | rc = writeMasterJournal( pPager, zMaster ); |
||
6737 | if ( rc != SQLITE_OK ) |
||
6738 | goto commit_phase_one_exit; |
||
6739 | |||
6740 | /* Sync the journal file and write all dirty pages to the database. |
||
6741 | ** If the atomic-update optimization is being used, this sync will not |
||
6742 | ** create the journal file or perform any real IO. |
||
6743 | ** |
||
6744 | ** Because the change-counter page was just modified, unless the |
||
6745 | ** atomic-update optimization is used it is almost certain that the |
||
6746 | ** journal requires a sync here. However, in locking_mode=exclusive |
||
6747 | ** on a system under memory pressure it is just possible that this is |
||
6748 | ** not the case. In this case it is likely enough that the redundant |
||
6749 | ** xSync() call will be changed to a no-op by the OS anyhow. |
||
6750 | */ |
||
6751 | rc = syncJournal( pPager, 0 ); |
||
6752 | if ( rc != SQLITE_OK ) |
||
6753 | goto commit_phase_one_exit; |
||
6754 | |||
6755 | rc = pager_write_pagelist( pPager, sqlite3PcacheDirtyList( pPager.pPCache ) ); |
||
6756 | if ( rc != SQLITE_OK ) |
||
6757 | { |
||
6758 | Debug.Assert( rc != SQLITE_IOERR_BLOCKED ); |
||
6759 | goto commit_phase_one_exit; |
||
6760 | } |
||
6761 | sqlite3PcacheCleanAll( pPager.pPCache ); |
||
6762 | |||
6763 | /* If the file on disk is not the same size as the database image, |
||
6764 | ** then use pager_truncate to grow or shrink the file here. |
||
6765 | */ |
||
6766 | if ( pPager.dbSize != pPager.dbFileSize ) |
||
6767 | { |
||
6768 | Pgno nNew = (Pgno)( pPager.dbSize - ( pPager.dbSize == PAGER_MJ_PGNO( pPager ) ? 1 : 0 ) ); |
||
6769 | Debug.Assert( pPager.eState >= PAGER_WRITER_DBMOD ); |
||
6770 | rc = pager_truncate( pPager, nNew ); |
||
6771 | if ( rc != SQLITE_OK ) |
||
6772 | goto commit_phase_one_exit; |
||
6773 | } |
||
6774 | |||
6775 | /* Finally, sync the database file. */ |
||
6776 | if ( !noSync ) |
||
6777 | { |
||
6778 | rc = sqlite3PagerSync( pPager ); |
||
6779 | } |
||
6780 | IOTRACE( "DBSYNC %p\n", pPager ); |
||
6781 | } |
||
6782 | } |
||
6783 | |||
6784 | commit_phase_one_exit: |
||
6785 | if ( rc == SQLITE_OK && !pagerUseWal( pPager ) ) |
||
6786 | { |
||
6787 | pPager.eState = PAGER_WRITER_FINISHED; |
||
6788 | } |
||
6789 | return rc; |
||
6790 | } |
||
6791 | |||
6792 | |||
6793 | /* |
||
6794 | ** When this function is called, the database file has been completely |
||
6795 | ** updated to reflect the changes made by the current transaction and |
||
6796 | ** synced to disk. The journal file still exists in the file-system |
||
6797 | ** though, and if a failure occurs at this point it will eventually |
||
6798 | ** be used as a hot-journal and the current transaction rolled back. |
||
6799 | ** |
||
6800 | ** This function finalizes the journal file, either by deleting, |
||
6801 | ** truncating or partially zeroing it, so that it cannot be used |
||
6802 | ** for hot-journal rollback. Once this is done the transaction is |
||
6803 | ** irrevocably committed. |
||
6804 | ** |
||
6805 | ** If an error occurs, an IO error code is returned and the pager |
||
6806 | ** moves into the error state. Otherwise, SQLITE_OK is returned. |
||
6807 | */ |
||
6808 | static int sqlite3PagerCommitPhaseTwo( Pager pPager ) |
||
6809 | { |
||
6810 | int rc = SQLITE_OK; /* Return code */ |
||
6811 | |||
6812 | /* This routine should not be called if a prior error has occurred. |
||
6813 | ** But if (due to a coding error elsewhere in the system) it does get |
||
6814 | ** called, just return the same error code without doing anything. */ |
||
6815 | if ( NEVER( pPager.errCode ) != 0 ) |
||
6816 | return pPager.errCode; |
||
6817 | |||
6818 | Debug.Assert( pPager.eState == PAGER_WRITER_LOCKED |
||
6819 | || pPager.eState == PAGER_WRITER_FINISHED |
||
6820 | || ( pagerUseWal( pPager ) && pPager.eState == PAGER_WRITER_CACHEMOD ) |
||
6821 | ); |
||
6822 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6823 | |||
6824 | /* An optimization. If the database was not actually modified during |
||
6825 | ** this transaction, the pager is running in exclusive-mode and is |
||
6826 | ** using persistent journals, then this function is a no-op. |
||
6827 | ** |
||
6828 | ** The start of the journal file currently contains a single journal |
||
6829 | ** header with the nRec field set to 0. If such a journal is used as |
||
6830 | ** a hot-journal during hot-journal rollback, 0 changes will be made |
||
6831 | ** to the database file. So there is no need to zero the journal |
||
6832 | ** header. Since the pager is in exclusive mode, there is no need |
||
6833 | ** to drop any locks either. |
||
6834 | */ |
||
6835 | if ( pPager.eState == PAGER_WRITER_LOCKED |
||
6836 | && pPager.exclusiveMode |
||
6837 | && pPager.journalMode == PAGER_JOURNALMODE_PERSIST |
||
6838 | ) |
||
6839 | { |
||
6840 | Debug.Assert( pPager.journalOff == JOURNAL_HDR_SZ( pPager ) || 0 == pPager.journalOff ); |
||
6841 | pPager.eState = PAGER_READER; |
||
6842 | return SQLITE_OK; |
||
6843 | } |
||
6844 | |||
6845 | PAGERTRACE( "COMMIT %d\n", PAGERID( pPager ) ); |
||
6846 | rc = pager_end_transaction( pPager, pPager.setMaster ); |
||
6847 | return pager_error( pPager, rc ); |
||
6848 | } |
||
6849 | |||
6850 | /* |
||
6851 | ** If a write transaction is open, then all changes made within the |
||
6852 | ** transaction are reverted and the current write-transaction is closed. |
||
6853 | ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR |
||
6854 | ** state if an error occurs. |
||
6855 | ** |
||
6856 | ** If the pager is already in PAGER_ERROR state when this function is called, |
||
6857 | ** it returns Pager.errCode immediately. No work is performed in this case. |
||
6858 | ** |
||
6859 | ** Otherwise, in rollback mode, this function performs two functions: |
||
6860 | ** |
||
6861 | ** 1) It rolls back the journal file, restoring all database file and |
||
6862 | ** in-memory cache pages to the state they were in when the transaction |
||
6863 | ** was opened, and |
||
6864 | ** |
||
6865 | ** 2) It finalizes the journal file, so that it is not used for hot |
||
6866 | ** rollback at any point in the future. |
||
6867 | ** |
||
6868 | ** Finalization of the journal file (task 2) is only performed if the |
||
6869 | ** rollback is successful. |
||
6870 | ** |
||
6871 | ** In WAL mode, all cache-entries containing data modified within the |
||
6872 | ** current transaction are either expelled from the cache or reverted to |
||
6873 | ** their pre-transaction state by re-reading data from the database or |
||
6874 | ** WAL files. The WAL transaction is then closed. |
||
6875 | */ |
||
6876 | static int sqlite3PagerRollback( Pager pPager ) |
||
6877 | { |
||
6878 | int rc = SQLITE_OK; /* Return code */ |
||
6879 | PAGERTRACE( "ROLLBACK %d\n", PAGERID( pPager ) ); |
||
6880 | |||
6881 | /* PagerRollback() is a no-op if called in READER or OPEN state. If |
||
6882 | ** the pager is already in the ERROR state, the rollback is not |
||
6883 | ** attempted here. Instead, the error code is returned to the caller. |
||
6884 | */ |
||
6885 | Debug.Assert( assert_pager_state( pPager ) ); |
||
6886 | if ( pPager.eState == PAGER_ERROR ) |
||
6887 | return pPager.errCode; |
||
6888 | if ( pPager.eState <= PAGER_READER ) |
||
6889 | return SQLITE_OK; |
||
6890 | |||
6891 | if ( pagerUseWal( pPager ) ) |
||
6892 | { |
||
6893 | int rc2; |
||
6894 | |||
6895 | rc = sqlite3PagerSavepoint( pPager, SAVEPOINT_ROLLBACK, -1 ); |
||
6896 | rc2 = pager_end_transaction( pPager, pPager.setMaster ); |
||
6897 | if ( rc == SQLITE_OK ) |
||
6898 | rc = rc2; |
||
6899 | rc = pager_error( pPager, rc ); |
||
6900 | } |
||
6901 | else if ( !isOpen( pPager.jfd ) || pPager.eState == PAGER_WRITER_LOCKED ) |
||
6902 | { |
||
6903 | int eState = pPager.eState; |
||
6904 | rc = pager_end_transaction( pPager, 0 ); |
||
6905 | if ( |
||
6906 | #if SQLITE_OMIT_MEMORYDB |
||
6907 | 0==MEMDB |
||
6908 | #else |
||
6909 | |||
6910 | #endif |
||
6911 | && eState > PAGER_WRITER_LOCKED ) |
||
6912 | { |
||
6913 | /* This can happen using journal_mode=off. Move the pager to the error |
||
6914 | ** state to indicate that the contents of the cache may not be trusted. |
||
6915 | ** Any active readers will get SQLITE_ABORT. |
||
6916 | */ |
||
6917 | pPager.errCode = SQLITE_ABORT; |
||
6918 | pPager.eState = PAGER_ERROR; |
||
6919 | return rc; |
||
6920 | } |
||
6921 | } |
||
6922 | else |
||
6923 | { |
||
6924 | rc = pager_playback( pPager, 0 ); |
||
6925 | } |
||
6926 | |||
6927 | Debug.Assert( pPager.eState == PAGER_READER || rc != SQLITE_OK ); |
||
6928 | Debug.Assert( rc == SQLITE_OK || rc == SQLITE_FULL || ( rc & 0xFF ) == SQLITE_IOERR ); |
||
6929 | |||
6930 | /* If an error occurs during a ROLLBACK, we can no longer trust the pager |
||
6931 | ** cache. So call pager_error() on the way out to make any error persistent. |
||
6932 | */ |
||
6933 | return pager_error( pPager, rc ); |
||
6934 | } |
||
6935 | |||
6936 | |||
6937 | /* |
||
6938 | ** Return TRUE if the database file is opened read-only. Return FALSE |
||
6939 | ** if the database is (in theory) writable. |
||
6940 | */ |
||
6941 | static bool sqlite3PagerIsreadonly( Pager pPager ) |
||
6942 | { |
||
6943 | return pPager.readOnly; |
||
6944 | } |
||
6945 | |||
6946 | /* |
||
6947 | ** Return the number of references to the pager. |
||
6948 | */ |
||
6949 | static int sqlite3PagerRefcount( Pager pPager ) |
||
6950 | { |
||
6951 | return sqlite3PcacheRefCount( pPager.pPCache ); |
||
6952 | } |
||
6953 | |||
6954 | /* |
||
6955 | ** Return the approximate number of bytes of memory currently |
||
6956 | ** used by the pager and its associated cache. |
||
6957 | */ |
||
6958 | static int sqlite3PagerMemUsed( Pager pPager ) |
||
6959 | { |
||
6960 | int perPageSize = pPager.pageSize + pPager.nExtra + 20; //+ sizeof(PgHdr) + 5*sizeof(void*); |
||
6961 | return perPageSize * sqlite3PcachePagecount( pPager.pPCache ) |
||
6962 | + 0// Not readily available under C#// sqlite3MallocSize(pPager); |
||
6963 | + pPager.pageSize; |
||
6964 | } |
||
6965 | |||
6966 | /* |
||
6967 | ** Return the number of references to the specified page. |
||
6968 | */ |
||
6969 | static int sqlite3PagerPageRefcount( DbPage pPage ) |
||
6970 | { |
||
6971 | return sqlite3PcachePageRefcount( pPage ); |
||
6972 | } |
||
6973 | |||
6974 | |||
6975 | #if SQLITE_TEST |
||
6976 | /* |
||
6977 | ** This routine is used for testing and analysis only. |
||
6978 | */ |
||
6979 | static int[] sqlite3PagerStats( Pager pPager ) |
||
6980 | { |
||
6981 | int[] a = new int[11]; |
||
6982 | a[0] = sqlite3PcacheRefCount( pPager.pPCache ); |
||
6983 | a[1] = sqlite3PcachePagecount( pPager.pPCache ); |
||
6984 | a[2] = sqlite3PcacheGetCachesize( pPager.pPCache ); |
||
6985 | a[3] = pPager.eState == PAGER_OPEN ? -1 : (int)pPager.dbSize; |
||
6986 | a[4] = pPager.eState; |
||
6987 | a[5] = pPager.errCode; |
||
6988 | a[6] = pPager.nHit; |
||
6989 | a[7] = pPager.nMiss; |
||
6990 | a[8] = 0; /* Used to be pPager.nOvfl */ |
||
6991 | a[9] = pPager.nRead; |
||
6992 | a[10] = pPager.nWrite; |
||
6993 | return a; |
||
6994 | } |
||
6995 | #endif |
||
6996 | |||
6997 | /* |
||
6998 | ** Return true if this is an in-memory pager. |
||
6999 | */ |
||
7000 | static bool sqlite3PagerIsMemdb( Pager pPager ) |
||
7001 | { |
||
7002 | #if SQLITE_OMIT_MEMORYDB |
||
7003 | return MEMDB != 0; |
||
7004 | #else |
||
7005 | return pPager.memDb != 0; |
||
7006 | #endif |
||
7007 | } |
||
7008 | |||
7009 | /* |
||
7010 | ** Check that there are at least nSavepoint savepoints open. If there are |
||
7011 | ** currently less than nSavepoints open, then open one or more savepoints |
||
7012 | ** to make up the difference. If the number of savepoints is already |
||
7013 | ** equal to nSavepoint, then this function is a no-op. |
||
7014 | ** |
||
7015 | ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error |
||
7016 | ** occurs while opening the sub-journal file, then an IO error code is |
||
7017 | ** returned. Otherwise, SQLITE_OK. |
||
7018 | */ |
||
7019 | static int sqlite3PagerOpenSavepoint( Pager pPager, int nSavepoint ) |
||
7020 | { |
||
7021 | int rc = SQLITE_OK; /* Return code */ |
||
7022 | int nCurrent = pPager.nSavepoint; /* Current number of savepoints */ |
||
7023 | |||
7024 | Debug.Assert( pPager.eState >= PAGER_WRITER_LOCKED ); |
||
7025 | Debug.Assert( assert_pager_state( pPager ) ); |
||
7026 | |||
7027 | if ( nSavepoint > nCurrent && pPager.useJournal != 0 ) |
||
7028 | { |
||
7029 | int ii; /* Iterator variable */ |
||
7030 | PagerSavepoint[] aNew; /* New Pager.aSavepoint array */ |
||
7031 | |||
7032 | /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM |
||
7033 | ** if the allocation fails. Otherwise, zero the new portion in case a |
||
7034 | ** malloc failure occurs while populating it in the for(...) loop below. |
||
7035 | */ |
||
7036 | //aNew = (PagerSavepoint *)sqlite3Realloc( |
||
7037 | // pPager.aSavepoint, sizeof(PagerSavepoint)*nSavepoint |
||
7038 | //); |
||
7039 | Array.Resize( ref pPager.aSavepoint, nSavepoint ); |
||
7040 | aNew = pPager.aSavepoint; |
||
7041 | //if( null==aNew ){ |
||
7042 | // return SQLITE_NOMEM; |
||
7043 | //} |
||
7044 | // memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); |
||
7045 | // pPager.aSavepoint = aNew; |
||
7046 | |||
7047 | /* Populate the PagerSavepoint structures just allocated. */ |
||
7048 | for ( ii = nCurrent; ii < nSavepoint; ii++ ) |
||
7049 | { |
||
7050 | aNew[ii] = new PagerSavepoint(); |
||
7051 | aNew[ii].nOrig = pPager.dbSize; |
||
7052 | if ( isOpen( pPager.jfd ) && pPager.journalOff > 0 ) |
||
7053 | { |
||
7054 | aNew[ii].iOffset = pPager.journalOff; |
||
7055 | } |
||
7056 | else |
||
7057 | { |
||
7058 | aNew[ii].iOffset = (int)JOURNAL_HDR_SZ( pPager ); |
||
7059 | } |
||
7060 | aNew[ii].iSubRec = pPager.nSubRec; |
||
7061 | aNew[ii].pInSavepoint = sqlite3BitvecCreate( pPager.dbSize ); |
||
7062 | //if ( null == aNew[ii].pInSavepoint ) |
||
7063 | //{ |
||
7064 | // return SQLITE_NOMEM; |
||
7065 | //} |
||
7066 | if ( pagerUseWal( pPager ) ) |
||
7067 | { |
||
7068 | sqlite3WalSavepoint( pPager.pWal, aNew[ii].aWalData ); |
||
7069 | } |
||
7070 | pPager.nSavepoint = ii + 1; |
||
7071 | } |
||
7072 | Debug.Assert( pPager.nSavepoint == nSavepoint ); |
||
7073 | assertTruncateConstraint( pPager ); |
||
7074 | } |
||
7075 | |||
7076 | return rc; |
||
7077 | } |
||
7078 | |||
7079 | /* |
||
7080 | ** This function is called to rollback or release (commit) a savepoint. |
||
7081 | ** The savepoint to release or rollback need not be the most recently |
||
7082 | ** created savepoint. |
||
7083 | ** |
||
7084 | ** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE. |
||
7085 | ** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with |
||
7086 | ** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes |
||
7087 | ** that have occurred since the specified savepoint was created. |
||
7088 | ** |
||
7089 | ** The savepoint to rollback or release is identified by parameter |
||
7090 | ** iSavepoint. A value of 0 means to operate on the outermost savepoint |
||
7091 | ** (the first created). A value of (Pager.nSavepoint-1) means operate |
||
7092 | ** on the most recently created savepoint. If iSavepoint is greater than |
||
7093 | ** (Pager.nSavepoint-1), then this function is a no-op. |
||
7094 | ** |
||
7095 | ** If a negative value is passed to this function, then the current |
||
7096 | ** transaction is rolled back. This is different to calling |
||
7097 | ** sqlite3PagerRollback() because this function does not terminate |
||
7098 | ** the transaction or unlock the database, it just restores the |
||
7099 | ** contents of the database to its original state. |
||
7100 | ** |
||
7101 | ** In any case, all savepoints with an index greater than iSavepoint |
||
7102 | ** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE), |
||
7103 | ** then savepoint iSavepoint is also destroyed. |
||
7104 | ** |
||
7105 | ** This function may return SQLITE_NOMEM if a memory allocation fails, |
||
7106 | ** or an IO error code if an IO error occurs while rolling back a |
||
7107 | ** savepoint. If no errors occur, SQLITE_OK is returned. |
||
7108 | */ |
||
7109 | static int sqlite3PagerSavepoint( Pager pPager, int op, int iSavepoint ) |
||
7110 | { |
||
7111 | int rc = pPager.errCode; /* Return code */ |
||
7112 | |||
7113 | Debug.Assert( op == SAVEPOINT_RELEASE || op == SAVEPOINT_ROLLBACK ); |
||
7114 | Debug.Assert( iSavepoint >= 0 || op == SAVEPOINT_ROLLBACK ); |
||
7115 | |||
7116 | if ( rc == SQLITE_OK && iSavepoint < pPager.nSavepoint ) |
||
7117 | { |
||
7118 | int ii; /* Iterator variable */ |
||
7119 | int nNew; /* Number of remaining savepoints after this op. */ |
||
7120 | |||
7121 | /* Figure out how many savepoints will still be active after this |
||
7122 | ** operation. Store this value in nNew. Then free resources associated |
||
7123 | ** with any savepoints that are destroyed by this operation. |
||
7124 | */ |
||
7125 | nNew = iSavepoint + ( ( op == SAVEPOINT_RELEASE ) ? 0 : 1 ); |
||
7126 | for ( ii = nNew; ii < pPager.nSavepoint; ii++ ) |
||
7127 | { |
||
7128 | sqlite3BitvecDestroy( ref pPager.aSavepoint[ii].pInSavepoint ); |
||
7129 | } |
||
7130 | pPager.nSavepoint = nNew; |
||
7131 | |||
7132 | /* If this is a release of the outermost savepoint, truncate |
||
7133 | ** the sub-journal to zero bytes in size. */ |
||
7134 | if ( op == SAVEPOINT_RELEASE ) |
||
7135 | { |
||
7136 | if ( nNew == 0 && isOpen( pPager.sjfd ) ) |
||
7137 | { |
||
7138 | /* Only truncate if it is an in-memory sub-journal. */ |
||
7139 | if ( sqlite3IsMemJournal( pPager.sjfd ) ) |
||
7140 | { |
||
7141 | rc = sqlite3OsTruncate( pPager.sjfd, 0 ); |
||
7142 | Debug.Assert( rc == SQLITE_OK ); |
||
7143 | } |
||
7144 | pPager.nSubRec = 0; |
||
7145 | } |
||
7146 | } |
||
7147 | /* Else this is a rollback operation, playback the specified savepoint. |
||
7148 | ** If this is a temp-file, it is possible that the journal file has |
||
7149 | ** not yet been opened. In this case there have been no changes to |
||
7150 | ** the database file, so the playback operation can be skipped. |
||
7151 | */ |
||
7152 | else if ( pagerUseWal( pPager ) || isOpen( pPager.jfd ) ) |
||
7153 | { |
||
7154 | PagerSavepoint pSavepoint = ( nNew == 0 ) ? null : pPager.aSavepoint[nNew - 1]; |
||
7155 | rc = pagerPlaybackSavepoint( pPager, pSavepoint ); |
||
7156 | Debug.Assert( rc != SQLITE_DONE ); |
||
7157 | } |
||
7158 | } |
||
7159 | return rc; |
||
7160 | } |
||
7161 | |||
7162 | /* |
||
7163 | ** Return the full pathname of the database file. |
||
7164 | */ |
||
7165 | static string sqlite3PagerFilename( Pager pPager ) |
||
7166 | { |
||
7167 | return pPager.zFilename; |
||
7168 | } |
||
7169 | |||
7170 | /* |
||
7171 | ** Return the VFS structure for the pager. |
||
7172 | */ |
||
7173 | static sqlite3_vfs sqlite3PagerVfs( Pager pPager ) |
||
7174 | { |
||
7175 | return pPager.pVfs; |
||
7176 | } |
||
7177 | |||
7178 | /* |
||
7179 | ** Return the file handle for the database file associated |
||
7180 | ** with the pager. This might return NULL if the file has |
||
7181 | ** not yet been opened. |
||
7182 | */ |
||
7183 | static sqlite3_file sqlite3PagerFile( Pager pPager ) |
||
7184 | { |
||
7185 | return pPager.fd; |
||
7186 | } |
||
7187 | |||
7188 | /* |
||
7189 | ** Return the full pathname of the journal file. |
||
7190 | */ |
||
7191 | static string sqlite3PagerJournalname( Pager pPager ) |
||
7192 | { |
||
7193 | return pPager.zJournal; |
||
7194 | } |
||
7195 | |||
7196 | /* |
||
7197 | ** Return true if fsync() calls are disabled for this pager. Return FALSE |
||
7198 | ** if fsync()s are executed normally. |
||
7199 | */ |
||
7200 | static bool sqlite3PagerNosync( Pager pPager ) |
||
7201 | { |
||
7202 | return pPager.noSync; |
||
7203 | } |
||
7204 | |||
7205 | #if SQLITE_HAS_CODEC |
||
7206 | /* |
||
7207 | ** Set or retrieve the codec for this pager |
||
7208 | */ |
||
7209 | static void sqlite3PagerSetCodec( |
||
7210 | Pager pPager, |
||
7211 | dxCodec xCodec, //void *(*xCodec)(void*,void*,Pgno,int), |
||
7212 | dxCodecSizeChng xCodecSizeChng, //void (*xCodecSizeChng)(void*,int,int), |
||
7213 | dxCodecFree xCodecFree, //void (*xCodecFree)(void*), |
||
7214 | codec_ctx pCodec |
||
7215 | ) |
||
7216 | { |
||
7217 | if ( pPager.xCodecFree != null ) |
||
7218 | pPager.xCodecFree( ref pPager.pCodec ); |
||
7219 | pPager.xCodec = ( pPager.memDb != 0 ) ? null : xCodec; |
||
7220 | pPager.xCodecSizeChng = xCodecSizeChng; |
||
7221 | pPager.xCodecFree = xCodecFree; |
||
7222 | pPager.pCodec = pCodec; |
||
7223 | pagerReportSize( pPager ); |
||
7224 | } |
||
7225 | |||
7226 | static object sqlite3PagerGetCodec( Pager pPager ) |
||
7227 | { |
||
7228 | return pPager.pCodec; |
||
7229 | } |
||
7230 | #endif |
||
7231 | |||
7232 | #if !SQLITE_OMIT_AUTOVACUUM |
||
7233 | /* |
||
7234 | ** Move the page pPg to location pgno in the file. |
||
7235 | ** |
||
7236 | ** There must be no references to the page previously located at |
||
7237 | ** pgno (which we call pPgOld) though that page is allowed to be |
||
7238 | ** in cache. If the page previously located at pgno is not already |
||
7239 | ** in the rollback journal, it is not put there by by this routine. |
||
7240 | ** |
||
7241 | ** References to the page pPg remain valid. Updating any |
||
7242 | ** meta-data associated with pPg (i.e. data stored in the nExtra bytes |
||
7243 | ** allocated along with the page) is the responsibility of the caller. |
||
7244 | ** |
||
7245 | ** A transaction must be active when this routine is called. It used to be |
||
7246 | ** required that a statement transaction was not active, but this restriction |
||
7247 | ** has been removed (CREATE INDEX needs to move a page when a statement |
||
7248 | ** transaction is active). |
||
7249 | ** |
||
7250 | ** If the fourth argument, isCommit, is non-zero, then this page is being |
||
7251 | ** moved as part of a database reorganization just before the transaction |
||
7252 | ** is being committed. In this case, it is guaranteed that the database page |
||
7253 | ** pPg refers to will not be written to again within this transaction. |
||
7254 | ** |
||
7255 | ** This function may return SQLITE_NOMEM or an IO error code if an error |
||
7256 | ** occurs. Otherwise, it returns SQLITE_OK. |
||
7257 | */ |
||
7258 | static int sqlite3PagerMovepage( Pager pPager, DbPage pPg, u32 pgno, int isCommit ) |
||
7259 | { |
||
7260 | PgHdr pPgOld; /* The page being overwritten. */ |
||
7261 | u32 needSyncPgno = 0; /* Old value of pPg.pgno, if sync is required */ |
||
7262 | int rc; /* Return code */ |
||
7263 | Pgno origPgno; /* The original page number */ |
||
7264 | |||
7265 | Debug.Assert( pPg.nRef > 0 ); |
||
7266 | Debug.Assert( pPager.eState == PAGER_WRITER_CACHEMOD |
||
7267 | || pPager.eState == PAGER_WRITER_DBMOD |
||
7268 | ); |
||
7269 | Debug.Assert( assert_pager_state( pPager ) ); |
||
7270 | |||
7271 | /* In order to be able to rollback, an in-memory database must journal |
||
7272 | ** the page we are moving from. |
||
7273 | */ |
||
7274 | if ( |
||
7275 | #if SQLITE_OMIT_MEMORYDB |
||
7276 | 1==MEMDB |
||
7277 | #else |
||
7278 | pPager.memDb != 0 |
||
7279 | #endif |
||
7280 | ) |
||
7281 | { |
||
7282 | rc = sqlite3PagerWrite( pPg ); |
||
7283 | if ( rc != 0 ) |
||
7284 | return rc; |
||
7285 | } |
||
7286 | |||
7287 | /* If the page being moved is dirty and has not been saved by the latest |
||
7288 | ** savepoint, then save the current contents of the page into the |
||
7289 | ** sub-journal now. This is required to handle the following scenario: |
||
7290 | ** |
||
7291 | ** BEGIN; |
||
7292 | ** <journal page X, then modify it in memory> |
||
7293 | ** SAVEPOINT one; |
||
7294 | ** <Move page X to location Y> |
||
7295 | ** ROLLBACK TO one; |
||
7296 | ** |
||
7297 | ** If page X were not written to the sub-journal here, it would not |
||
7298 | ** be possible to restore its contents when the "ROLLBACK TO one" |
||
7299 | ** statement were is processed. |
||
7300 | ** |
||
7301 | ** subjournalPage() may need to allocate space to store pPg.pgno into |
||
7302 | ** one or more savepoint bitvecs. This is the reason this function |
||
7303 | ** may return SQLITE_NOMEM. |
||
7304 | */ |
||
7305 | if ( ( pPg.flags & PGHDR_DIRTY ) != 0 |
||
7306 | && subjRequiresPage( pPg ) |
||
7307 | && SQLITE_OK != ( rc = subjournalPage( pPg ) ) |
||
7308 | ) |
||
7309 | { |
||
7310 | return rc; |
||
7311 | } |
||
7312 | |||
7313 | PAGERTRACE( "MOVE %d page %d (needSync=%d) moves to %d\n", |
||
7314 | PAGERID( pPager ), pPg.pgno, ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ? 1 : 0, pgno ); |
||
7315 | IOTRACE( "MOVE %p %d %d\n", pPager, pPg.pgno, pgno ); |
||
7316 | |||
7317 | /* If the journal needs to be sync()ed before page pPg.pgno can |
||
7318 | ** be written to, store pPg.pgno in local variable needSyncPgno. |
||
7319 | ** |
||
7320 | ** If the isCommit flag is set, there is no need to remember that |
||
7321 | ** the journal needs to be sync()ed before database page pPg.pgno |
||
7322 | ** can be written to. The caller has already promised not to write to it. |
||
7323 | */ |
||
7324 | if ( ( ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ) && 0 == isCommit ) |
||
7325 | { |
||
7326 | needSyncPgno = pPg.pgno; |
||
7327 | Debug.Assert( pageInJournal( pPg ) || pPg.pgno > pPager.dbOrigSize ); |
||
7328 | Debug.Assert( ( pPg.flags & PGHDR_DIRTY ) != 0 ); |
||
7329 | } |
||
7330 | |||
7331 | /* If the cache contains a page with page-number pgno, remove it |
||
7332 | ** from its hash chain. Also, if the PGHDR_NEED_SYNC was set for |
||
7333 | ** page pgno before the 'move' operation, it needs to be retained |
||
7334 | ** for the page moved there. |
||
7335 | */ |
||
7336 | pPg.flags &= ~PGHDR_NEED_SYNC; |
||
7337 | pPgOld = pager_lookup( pPager, pgno ); |
||
7338 | Debug.Assert( null == pPgOld || pPgOld.nRef == 1 ); |
||
7339 | if ( pPgOld != null ) |
||
7340 | { |
||
7341 | pPg.flags |= ( pPgOld.flags & PGHDR_NEED_SYNC ); |
||
7342 | if ( |
||
7343 | #if SQLITE_OMIT_MEMORYDB |
||
7344 | 1==MEMDB |
||
7345 | #else |
||
7346 | pPager.memDb != 0 |
||
7347 | #endif |
||
7348 | ) |
||
7349 | { |
||
7350 | /* Do not discard pages from an in-memory database since we might |
||
7351 | ** need to rollback later. Just move the page out of the way. */ |
||
7352 | sqlite3PcacheMove( pPgOld, pPager.dbSize + 1 ); |
||
7353 | } |
||
7354 | else |
||
7355 | { |
||
7356 | sqlite3PcacheDrop( pPgOld ); |
||
7357 | } |
||
7358 | } |
||
7359 | origPgno = pPg.pgno; |
||
7360 | sqlite3PcacheMove( pPg, pgno ); |
||
7361 | sqlite3PcacheMakeDirty( pPg ); |
||
7362 | |||
7363 | /* For an in-memory database, make sure the original page continues |
||
7364 | ** to exist, in case the transaction needs to roll back. Use pPgOld |
||
7365 | ** as the original page since it has already been allocated. |
||
7366 | */ |
||
7367 | if ( |
||
7368 | #if SQLITE_OMIT_MEMORYDB |
||
7369 | 0!=MEMDB |
||
7370 | #else |
||
7371 | |||
7372 | #endif |
||
7373 | ) |
||
7374 | { |
||
7375 | Debug.Assert( pPgOld ); |
||
7376 | sqlite3PcacheMove( pPgOld, origPgno ); |
||
7377 | sqlite3PagerUnref( pPgOld ); |
||
7378 | } |
||
7379 | |||
7380 | if ( needSyncPgno != 0 ) |
||
7381 | { |
||
7382 | /* If needSyncPgno is non-zero, then the journal file needs to be |
||
7383 | ** sync()ed before any data is written to database file page needSyncPgno. |
||
7384 | ** Currently, no such page exists in the page-cache and the |
||
7385 | ** "is journaled" bitvec flag has been set. This needs to be remedied by |
||
7386 | ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC |
||
7387 | ** flag. |
||
7388 | ** |
||
7389 | ** If the attempt to load the page into the page-cache fails, (due |
||
7390 | ** to a malloc() or IO failure), clear the bit in the pInJournal[] |
||
7391 | ** array. Otherwise, if the page is loaded and written again in |
||
7392 | ** this transaction, it may be written to the database file before |
||
7393 | ** it is synced into the journal file. This way, it may end up in |
||
7394 | ** the journal file twice, but that is not a problem. |
||
7395 | */ |
||
7396 | PgHdr pPgHdr = null; |
||
7397 | rc = sqlite3PagerGet( pPager, needSyncPgno, ref pPgHdr ); |
||
7398 | if ( rc != SQLITE_OK ) |
||
7399 | { |
||
7400 | if ( needSyncPgno <= pPager.dbOrigSize ) |
||
7401 | { |
||
7402 | Debug.Assert( pPager.pTmpSpace != null ); |
||
7403 | u32[] pTemp = new u32[pPager.pTmpSpace.Length]; |
||
7404 | sqlite3BitvecClear( pPager.pInJournal, needSyncPgno, pTemp );//pPager.pTmpSpace ); |
||
7405 | } |
||
7406 | return rc; |
||
7407 | } |
||
7408 | pPgHdr.flags |= PGHDR_NEED_SYNC; |
||
7409 | sqlite3PcacheMakeDirty( pPgHdr ); |
||
7410 | sqlite3PagerUnref( pPgHdr ); |
||
7411 | } |
||
7412 | return SQLITE_OK; |
||
7413 | } |
||
7414 | #endif |
||
7415 | |||
7416 | /* |
||
7417 | ** Return a pointer to the data for the specified page. |
||
7418 | */ |
||
7419 | static byte[] sqlite3PagerGetData( DbPage pPg ) |
||
7420 | { |
||
7421 | Debug.Assert( pPg.nRef > 0 || pPg.pPager.memDb != 0 ); |
||
7422 | return pPg.pData; |
||
7423 | } |
||
7424 | |||
7425 | /* |
||
7426 | ** Return a pointer to the Pager.nExtra bytes of "extra" space |
||
7427 | ** allocated along with the specified page. |
||
7428 | */ |
||
7429 | static MemPage sqlite3PagerGetExtra( DbPage pPg ) |
||
7430 | { |
||
7431 | return pPg.pExtra; |
||
7432 | } |
||
7433 | |||
7434 | /* |
||
7435 | ** Get/set the locking-mode for this pager. Parameter eMode must be one |
||
7436 | ** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or |
||
7437 | ** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then |
||
7438 | ** the locking-mode is set to the value specified. |
||
7439 | ** |
||
7440 | ** The returned value is either PAGER_LOCKINGMODE_NORMAL or |
||
7441 | ** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) |
||
7442 | ** locking-mode. |
||
7443 | */ |
||
7444 | static bool sqlite3PagerLockingMode( Pager pPager, int eMode ) |
||
7445 | { |
||
7446 | Debug.Assert( eMode == PAGER_LOCKINGMODE_QUERY |
||
7447 | || eMode == PAGER_LOCKINGMODE_NORMAL |
||
7448 | || eMode == PAGER_LOCKINGMODE_EXCLUSIVE ); |
||
7449 | Debug.Assert( PAGER_LOCKINGMODE_QUERY < 0 ); |
||
7450 | Debug.Assert( PAGER_LOCKINGMODE_NORMAL >= 0 && PAGER_LOCKINGMODE_EXCLUSIVE >= 0 ); |
||
7451 | Debug.Assert( pPager.exclusiveMode || false == sqlite3WalHeapMemory( pPager.pWal ) ); |
||
7452 | if ( eMode >= 0 && !pPager.tempFile && !sqlite3WalHeapMemory( pPager.pWal ) ) |
||
7453 | { |
||
7454 | pPager.exclusiveMode = eMode != 0; |
||
7455 | } |
||
7456 | return pPager.exclusiveMode; |
||
7457 | } |
||
7458 | |||
7459 | /* |
||
7460 | ** Set the journal-mode for this pager. Parameter eMode must be one of: |
||
7461 | ** |
||
7462 | ** PAGER_JOURNALMODE_DELETE |
||
7463 | ** PAGER_JOURNALMODE_TRUNCATE |
||
7464 | ** PAGER_JOURNALMODE_PERSIST |
||
7465 | ** PAGER_JOURNALMODE_OFF |
||
7466 | ** PAGER_JOURNALMODE_MEMORY |
||
7467 | ** PAGER_JOURNALMODE_WAL |
||
7468 | ** |
||
7469 | ** The journalmode is set to the value specified if the change is allowed. |
||
7470 | ** The change may be disallowed for the following reasons: |
||
7471 | ** |
||
7472 | ** * An in-memory database can only have its journal_mode set to _OFF |
||
7473 | ** or _MEMORY. |
||
7474 | ** |
||
7475 | ** * Temporary databases cannot have _WAL journalmode. |
||
7476 | ** |
||
7477 | ** The returned indicate the current (possibly updated) journal-mode. |
||
7478 | */ |
||
7479 | static int sqlite3PagerSetJournalMode( Pager pPager, int eMode ) |
||
7480 | { |
||
7481 | u8 eOld = pPager.journalMode; /* Prior journalmode */ |
||
7482 | |||
7483 | #if SQLITE_DEBUG |
||
7484 | /* The print_pager_state() routine is intended to be used by the debugger |
||
7485 | ** only. We invoke it once here to suppress a compiler warning. */ |
||
7486 | print_pager_state( pPager ); |
||
7487 | #endif |
||
7488 | |||
7489 | /* The eMode parameter is always valid */ |
||
7490 | Debug.Assert( eMode == PAGER_JOURNALMODE_DELETE |
||
7491 | || eMode == PAGER_JOURNALMODE_TRUNCATE |
||
7492 | || eMode == PAGER_JOURNALMODE_PERSIST |
||
7493 | || eMode == PAGER_JOURNALMODE_OFF |
||
7494 | || eMode == PAGER_JOURNALMODE_WAL |
||
7495 | || eMode == PAGER_JOURNALMODE_MEMORY ); |
||
7496 | |||
7497 | /* This routine is only called from the OP_JournalMode opcode, and |
||
7498 | ** the logic there will never allow a temporary file to be changed |
||
7499 | ** to WAL mode. |
||
7500 | */ |
||
7501 | Debug.Assert( pPager.tempFile == false || eMode != PAGER_JOURNALMODE_WAL ); |
||
7502 | |||
7503 | /* Do allow the journalmode of an in-memory database to be set to |
||
7504 | ** anything other than MEMORY or OFF |
||
7505 | */ |
||
7506 | if ( |
||
7507 | #if SQLITE_OMIT_MEMORYDB |
||
7508 | 1==MEMDB |
||
7509 | #else |
||
7510 | 1 == pPager.memDb |
||
7511 | #endif |
||
7512 | ) |
||
7513 | { |
||
7514 | Debug.Assert( eOld == PAGER_JOURNALMODE_MEMORY || eOld == PAGER_JOURNALMODE_OFF ); |
||
7515 | if ( eMode != PAGER_JOURNALMODE_MEMORY && eMode != PAGER_JOURNALMODE_OFF ) |
||
7516 | { |
||
7517 | eMode = eOld; |
||
7518 | } |
||
7519 | } |
||
7520 | |||
7521 | if ( eMode != eOld ) |
||
7522 | { |
||
7523 | /* Change the journal mode. */ |
||
7524 | Debug.Assert( pPager.eState != PAGER_ERROR ); |
||
7525 | pPager.journalMode = (u8)eMode; |
||
7526 | |||
7527 | /* When transistioning from TRUNCATE or PERSIST to any other journal |
||
7528 | ** mode except WAL, unless the pager is in locking_mode=exclusive mode, |
||
7529 | ** delete the journal file. |
||
7530 | */ |
||
7531 | Debug.Assert( ( PAGER_JOURNALMODE_TRUNCATE & 5 ) == 1 ); |
||
7532 | Debug.Assert( ( PAGER_JOURNALMODE_PERSIST & 5 ) == 1 ); |
||
7533 | Debug.Assert( ( PAGER_JOURNALMODE_DELETE & 5 ) == 0 ); |
||
7534 | Debug.Assert( ( PAGER_JOURNALMODE_MEMORY & 5 ) == 4 ); |
||
7535 | Debug.Assert( ( PAGER_JOURNALMODE_OFF & 5 ) == 0 ); |
||
7536 | Debug.Assert( ( PAGER_JOURNALMODE_WAL & 5 ) == 5 ); |
||
7537 | |||
7538 | Debug.Assert( isOpen( pPager.fd ) || pPager.exclusiveMode ); |
||
7539 | if ( !pPager.exclusiveMode && ( eOld & 5 ) == 1 && ( eMode & 1 ) == 0 ) |
||
7540 | { |
||
7541 | |||
7542 | /* In this case we would like to delete the journal file. If it is |
||
7543 | ** not possible, then that is not a problem. Deleting the journal file |
||
7544 | ** here is an optimization only. |
||
7545 | ** |
||
7546 | ** Before deleting the journal file, obtain a RESERVED lock on the |
||
7547 | ** database file. This ensures that the journal file is not deleted |
||
7548 | ** while it is in use by some other client. |
||
7549 | */ |
||
7550 | sqlite3OsClose( pPager.jfd ); |
||
7551 | if ( pPager.eLock >= RESERVED_LOCK ) |
||
7552 | { |
||
7553 | sqlite3OsDelete( pPager.pVfs, pPager.zJournal, 0 ); |
||
7554 | } |
||
7555 | else |
||
7556 | { |
||
7557 | int rc = SQLITE_OK; |
||
7558 | int state = pPager.eState; |
||
7559 | Debug.Assert( state == PAGER_OPEN || state == PAGER_READER ); |
||
7560 | if ( state == PAGER_OPEN ) |
||
7561 | { |
||
7562 | rc = sqlite3PagerSharedLock( pPager ); |
||
7563 | } |
||
7564 | if ( pPager.eState == PAGER_READER ) |
||
7565 | { |
||
7566 | Debug.Assert( rc == SQLITE_OK ); |
||
7567 | rc = pagerLockDb( pPager, RESERVED_LOCK ); |
||
7568 | } |
||
7569 | if ( rc == SQLITE_OK ) |
||
7570 | { |
||
7571 | sqlite3OsDelete( pPager.pVfs, pPager.zJournal, 0 ); |
||
7572 | } |
||
7573 | if ( rc == SQLITE_OK && state == PAGER_READER ) |
||
7574 | { |
||
7575 | pagerUnlockDb( pPager, SHARED_LOCK ); |
||
7576 | } |
||
7577 | else if ( state == PAGER_OPEN ) |
||
7578 | { |
||
7579 | pager_unlock( pPager ); |
||
7580 | } |
||
7581 | Debug.Assert( state == pPager.eState ); |
||
7582 | } |
||
7583 | } |
||
7584 | } |
||
7585 | |||
7586 | /* Return the new journal mode */ |
||
7587 | return (int)pPager.journalMode; |
||
7588 | } |
||
7589 | |||
7590 | /* |
||
7591 | ** Return the current journal mode. |
||
7592 | */ |
||
7593 | static int sqlite3PagerGetJournalMode( Pager pPager ) |
||
7594 | { |
||
7595 | return (int)pPager.journalMode; |
||
7596 | } |
||
7597 | |||
7598 | /* |
||
7599 | ** Return TRUE if the pager is in a state where it is OK to change the |
||
7600 | ** journalmode. Journalmode changes can only happen when the database |
||
7601 | ** is unmodified. |
||
7602 | */ |
||
7603 | static int sqlite3PagerOkToChangeJournalMode( Pager pPager ) |
||
7604 | { |
||
7605 | Debug.Assert( assert_pager_state( pPager ) ); |
||
7606 | if ( pPager.eState >= PAGER_WRITER_CACHEMOD ) |
||
7607 | return 0; |
||
7608 | if ( NEVER( isOpen( pPager.jfd ) && pPager.journalOff > 0 ) ) |
||
7609 | return 0; |
||
7610 | return 1; |
||
7611 | } |
||
7612 | |||
7613 | |||
7614 | /* |
||
7615 | ** Get/set the size-limit used for persistent journal files. |
||
7616 | ** |
||
7617 | ** Setting the size limit to -1 means no limit is enforced. |
||
7618 | ** An attempt to set a limit smaller than -1 is a no-op. |
||
7619 | */ |
||
7620 | static i64 sqlite3PagerJournalSizeLimit( Pager pPager, i64 iLimit ) |
||
7621 | { |
||
7622 | if ( iLimit >= -1 ) |
||
7623 | { |
||
7624 | pPager.journalSizeLimit = iLimit; |
||
7625 | sqlite3WalLimit( pPager.pWal, iLimit ); |
||
7626 | } |
||
7627 | return pPager.journalSizeLimit; |
||
7628 | } |
||
7629 | |||
7630 | /* |
||
7631 | ** Return a pointer to the pPager.pBackup variable. The backup module |
||
7632 | ** in backup.c maintains the content of this variable. This module |
||
7633 | ** uses it opaquely as an argument to sqlite3BackupRestart() and |
||
7634 | ** sqlite3BackupUpdate() only. |
||
7635 | */ |
||
7636 | static sqlite3_backup sqlite3PagerBackupPtr( Pager pPager ) |
||
7637 | { |
||
7638 | return pPager.pBackup; |
||
7639 | } |
||
7640 | |||
7641 | #if !SQLITE_OMIT_WAL |
||
7642 | /* |
||
7643 | ** This function is called when the user invokes "PRAGMA wal_checkpoint", |
||
7644 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
||
7645 | ** or wal_blocking_checkpoint() API functions. |
||
7646 | ** |
||
7647 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
||
7648 | */ |
||
7649 | int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
||
7650 | int rc = SQLITE_OK; |
||
7651 | if( pPager.pWal ){ |
||
7652 | rc = sqlite3WalCheckpoint(pPager.pWal, eMode, |
||
7653 | pPager.xBusyHandler, pPager.pBusyHandlerArg, |
||
7654 | pPager.ckptSyncFlags, pPager.pageSize, (u8 *)pPager.pTmpSpace, |
||
7655 | pnLog, pnCkpt |
||
7656 | ); |
||
7657 | } |
||
7658 | return rc; |
||
7659 | } |
||
7660 | |||
7661 | int sqlite3PagerWalCallback(Pager *pPager){ |
||
7662 | return sqlite3WalCallback(pPager.pWal); |
||
7663 | } |
||
7664 | |||
7665 | /* |
||
7666 | ** Return true if the underlying VFS for the given pager supports the |
||
7667 | ** primitives necessary for write-ahead logging. |
||
7668 | */ |
||
7669 | int sqlite3PagerWalSupported(Pager *pPager){ |
||
7670 | const sqlite3_io_methods *pMethods = pPager.fd->pMethods; |
||
7671 | return pPager.exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); |
||
7672 | } |
||
7673 | |||
7674 | /* |
||
7675 | ** Attempt to take an exclusive lock on the database file. If a PENDING lock |
||
7676 | ** is obtained instead, immediately release it. |
||
7677 | */ |
||
7678 | static int pagerExclusiveLock(Pager *pPager){ |
||
7679 | int rc; /* Return code */ |
||
7680 | |||
7681 | assert( pPager.eLock==SHARED_LOCK || pPager.eLock==EXCLUSIVE_LOCK ); |
||
7682 | rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); |
||
7683 | if( rc!=SQLITE_OK ){ |
||
7684 | /* If the attempt to grab the exclusive lock failed, release the |
||
7685 | ** pending lock that may have been obtained instead. */ |
||
7686 | pagerUnlockDb(pPager, SHARED_LOCK); |
||
7687 | } |
||
7688 | |||
7689 | return rc; |
||
7690 | } |
||
7691 | |||
7692 | /* |
||
7693 | ** Call sqlite3WalOpen() to open the WAL handle. If the pager is in |
||
7694 | ** exclusive-locking mode when this function is called, take an EXCLUSIVE |
||
7695 | ** lock on the database file and use heap-memory to store the wal-index |
||
7696 | ** in. Otherwise, use the normal shared-memory. |
||
7697 | */ |
||
7698 | static int pagerOpenWal(Pager *pPager){ |
||
7699 | int rc = SQLITE_OK; |
||
7700 | |||
7701 | assert( pPager.pWal==0 && pPager.tempFile==0 ); |
||
7702 | assert( pPager.eLock==SHARED_LOCK || pPager.eLock==EXCLUSIVE_LOCK || pPager.noReadlock); |
||
7703 | |||
7704 | /* If the pager is already in exclusive-mode, the WAL module will use |
||
7705 | ** heap-memory for the wal-index instead of the VFS shared-memory |
||
7706 | ** implementation. Take the exclusive lock now, before opening the WAL |
||
7707 | ** file, to make sure this is safe. |
||
7708 | */ |
||
7709 | if( pPager.exclusiveMode ){ |
||
7710 | rc = pagerExclusiveLock(pPager); |
||
7711 | } |
||
7712 | |||
7713 | /* Open the connection to the log file. If this operation fails, |
||
7714 | ** (e.g. due to malloc() failure), return an error code. |
||
7715 | */ |
||
7716 | if( rc==SQLITE_OK ){ |
||
7717 | rc = sqlite3WalOpen(pPager.pVfs, |
||
7718 | pPager.fd, pPager.zWal, pPager.exclusiveMode, &pPager.pWal |
||
7719 | pPager.journalSizeLimit, &pPager.pWal |
||
7720 | ); |
||
7721 | } |
||
7722 | |||
7723 | return rc; |
||
7724 | } |
||
7725 | |||
7726 | |||
7727 | /* |
||
7728 | ** The caller must be holding a SHARED lock on the database file to call |
||
7729 | ** this function. |
||
7730 | ** |
||
7731 | ** If the pager passed as the first argument is open on a real database |
||
7732 | ** file (not a temp file or an in-memory database), and the WAL file |
||
7733 | ** is not already open, make an attempt to open it now. If successful, |
||
7734 | ** return SQLITE_OK. If an error occurs or the VFS used by the pager does |
||
7735 | ** not support the xShmXXX() methods, return an error code. *pbOpen is |
||
7736 | ** not modified in either case. |
||
7737 | ** |
||
7738 | ** If the pager is open on a temp-file (or in-memory database), or if |
||
7739 | ** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK |
||
7740 | ** without doing anything. |
||
7741 | */ |
||
7742 | int sqlite3PagerOpenWal( |
||
7743 | Pager *pPager, /* Pager object */ |
||
7744 | int *pbOpen /* OUT: Set to true if call is a no-op */ |
||
7745 | ){ |
||
7746 | int rc = SQLITE_OK; /* Return code */ |
||
7747 | |||
7748 | assert( assert_pager_state(pPager) ); |
||
7749 | assert( pPager.eState==PAGER_OPEN || pbOpen ); |
||
7750 | assert( pPager.eState==PAGER_READER || !pbOpen ); |
||
7751 | assert( pbOpen==0 || *pbOpen==0 ); |
||
7752 | assert( pbOpen!=0 || (!pPager.tempFile && !pPager.pWal) ); |
||
7753 | |||
7754 | if( !pPager.tempFile && !pPager.pWal ){ |
||
7755 | if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; |
||
7756 | |||
7757 | /* Close any rollback journal previously open */ |
||
7758 | sqlite3OsClose(pPager.jfd); |
||
7759 | |||
7760 | rc = pagerOpenWal(pPager); |
||
7761 | if( rc==SQLITE_OK ){ |
||
7762 | pPager.journalMode = PAGER_JOURNALMODE_WAL; |
||
7763 | pPager.eState = PAGER_OPEN; |
||
7764 | } |
||
7765 | }else{ |
||
7766 | *pbOpen = 1; |
||
7767 | } |
||
7768 | |||
7769 | return rc; |
||
7770 | } |
||
7771 | |||
7772 | /* |
||
7773 | ** This function is called to close the connection to the log file prior |
||
7774 | ** to switching from WAL to rollback mode. |
||
7775 | ** |
||
7776 | ** Before closing the log file, this function attempts to take an |
||
7777 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
||
7778 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
||
7779 | ** If successful, the EXCLUSIVE lock is not released before returning. |
||
7780 | */ |
||
7781 | int sqlite3PagerCloseWal(Pager *pPager){ |
||
7782 | int rc = SQLITE_OK; |
||
7783 | |||
7784 | assert( pPager.journalMode==PAGER_JOURNALMODE_WAL ); |
||
7785 | |||
7786 | /* If the log file is not already open, but does exist in the file-system, |
||
7787 | ** it may need to be checkpointed before the connection can switch to |
||
7788 | ** rollback mode. Open it now so this can happen. |
||
7789 | */ |
||
7790 | if( !pPager.pWal ){ |
||
7791 | int logexists = 0; |
||
7792 | rc = pagerLockDb(pPager, SHARED_LOCK); |
||
7793 | if( rc==SQLITE_OK ){ |
||
7794 | rc = sqlite3OsAccess( |
||
7795 | pPager.pVfs, pPager.zWal, SQLITE_ACCESS_EXISTS, &logexists |
||
7796 | ); |
||
7797 | } |
||
7798 | if( rc==SQLITE_OK && logexists ){ |
||
7799 | rc = pagerOpenWal(pPager); |
||
7800 | } |
||
7801 | } |
||
7802 | |||
7803 | /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on |
||
7804 | ** the database file, the log and log-summary files will be deleted. |
||
7805 | */ |
||
7806 | if( rc==SQLITE_OK && pPager.pWal ){ |
||
7807 | rc = pagerExclusiveLock(pPager); |
||
7808 | if( rc==SQLITE_OK ){ |
||
7809 | rc = sqlite3WalClose(pPager.pWal, pPager.ckptSyncFlags, |
||
7810 | pPager.pageSize, (u8*)pPager.pTmpSpace); |
||
7811 | pPager.pWal = 0; |
||
7812 | } |
||
7813 | } |
||
7814 | return rc; |
||
7815 | } |
||
7816 | |||
7817 | #if SQLITE_HAS_CODEC |
||
7818 | /* |
||
7819 | ** This function is called by the wal module when writing page content |
||
7820 | ** into the log file. |
||
7821 | ** |
||
7822 | ** This function returns a pointer to a buffer containing the encrypted |
||
7823 | ** page content. If a malloc fails, this function may return NULL. |
||
7824 | */ |
||
7825 | void sqlite3PagerCodec(PgHdr *pPg){ |
||
7826 | voidaData = 0; |
||
7827 | CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); |
||
7828 | return aData; |
||
7829 | } |
||
7830 | #endif //* SQLITE_HAS_CODEC */ |
||
7831 | |||
7832 | #endif //* !SQLITE_OMIT_WAL */ |
||
7833 | |||
7834 | #endif // * SQLITE_OMIT_DISKIO */ |
||
7835 | } |
||
7836 | } |