blob: 2e5f9b8ef49dd798f6512661b90dd1ce3a685986 [file] [log] [blame]
drhed7c8552001-04-11 14:29:21 +00001/*
2** Copyright (c) 2001 D. Richard Hipp
3**
4** This program is free software; you can redistribute it and/or
5** modify it under the terms of the GNU General Public
6** License as published by the Free Software Foundation; either
7** version 2 of the License, or (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12** General Public License for more details.
13**
14** You should have received a copy of the GNU General Public
15** License along with this library; if not, write to the
16** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17** Boston, MA 02111-1307, USA.
18**
19** Author contact information:
20** drh@hwaci.com
21** http://www.hwaci.com/drh/
22**
23*************************************************************************
24** This is the implementation of the page cache subsystem.
25**
26** The page cache is used to access a database file. The pager journals
27** all writes in order to support rollback. Locking is used to limit
28** access to one or more reader or on writer.
29**
drh7e3b0a02001-04-28 16:52:40 +000030** @(#) $Id: pager.c,v 1.5 2001/04/28 16:52:42 drh Exp $
drhed7c8552001-04-11 14:29:21 +000031*/
drhd9b02572001-04-15 00:37:09 +000032#include "sqliteInt.h"
drhed7c8552001-04-11 14:29:21 +000033#include "pager.h"
34#include <fcntl.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <assert.h>
drhd9b02572001-04-15 00:37:09 +000038#include <string.h>
drhed7c8552001-04-11 14:29:21 +000039
40/*
41** The page cache as a whole is always in one of the following
42** states:
43**
44** SQLITE_UNLOCK The page cache is not currently reading or
45** writing the database file. There is no
46** data held in memory. This is the initial
47** state.
48**
49** SQLITE_READLOCK The page cache is reading the database.
50** Writing is not permitted. There can be
51** multiple readers accessing the same database
drh69688d52001-04-14 16:38:23 +000052** file at the same time.
drhed7c8552001-04-11 14:29:21 +000053**
54** SQLITE_WRITELOCK The page cache is writing the database.
55** Access is exclusive. No other processes or
56** threads can be reading or writing while one
57** process is writing.
58**
59** The page cache comes up in PCS_UNLOCK. The first time a
60** sqlite_page_get() occurs, the state transitions to PCS_READLOCK.
61** After all pages have been released using sqlite_page_unref(),
62** the state transitions back to PCS_UNLOCK. The first time
63** that sqlite_page_write() is called, the state transitions to
64** PCS_WRITELOCK. The sqlite_page_rollback() and sqlite_page_commit()
65** functions transition the state back to PCS_READLOCK.
66*/
67#define SQLITE_UNLOCK 0
68#define SQLITE_READLOCK 1
69#define SQLITE_WRITELOCK 2
70
drhd9b02572001-04-15 00:37:09 +000071
drhed7c8552001-04-11 14:29:21 +000072/*
73** Each in-memory image of a page begins with the following header.
74*/
drhd9b02572001-04-15 00:37:09 +000075typedef struct PgHdr PgHdr;
drhed7c8552001-04-11 14:29:21 +000076struct PgHdr {
77 Pager *pPager; /* The pager to which this page belongs */
78 Pgno pgno; /* The page number for this page */
drh69688d52001-04-14 16:38:23 +000079 PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
drhed7c8552001-04-11 14:29:21 +000080 int nRef; /* Number of users of this page */
drhd9b02572001-04-15 00:37:09 +000081 PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */
82 PgHdr *pNextAll, *pPrevAll; /* A list of all pages */
drhed7c8552001-04-11 14:29:21 +000083 char inJournal; /* TRUE if has been written to journal */
84 char dirty; /* TRUE if we need to write back changes */
drh69688d52001-04-14 16:38:23 +000085 /* SQLITE_PAGE_SIZE bytes of page data follow this header */
drh7e3b0a02001-04-28 16:52:40 +000086 /* Pager.nExtra bytes of local data follow the page data */
drhed7c8552001-04-11 14:29:21 +000087};
88
89/*
drh69688d52001-04-14 16:38:23 +000090** Convert a pointer to a PgHdr into a pointer to its data
91** and back again.
drhed7c8552001-04-11 14:29:21 +000092*/
93#define PGHDR_TO_DATA(P) ((void*)(&(P)[1]))
94#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1])
drh7e3b0a02001-04-28 16:52:40 +000095#define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE])
drhed7c8552001-04-11 14:29:21 +000096
97/*
drhed7c8552001-04-11 14:29:21 +000098** How big to make the hash table used for locating in-memory pages
99** by page number.
100*/
drhd9b02572001-04-15 00:37:09 +0000101#define N_PG_HASH 101
drhed7c8552001-04-11 14:29:21 +0000102
103/*
104** A open page cache is an instance of the following structure.
105*/
106struct Pager {
107 char *zFilename; /* Name of the database file */
108 char *zJournal; /* Name of the journal file */
109 int fd, jfd; /* File descriptors for database and journal */
drhed7c8552001-04-11 14:29:21 +0000110 int dbSize; /* Number of pages in the file */
drh69688d52001-04-14 16:38:23 +0000111 int origDbSize; /* dbSize before the current change */
drh7e3b0a02001-04-28 16:52:40 +0000112 int nExtra; /* Add this many bytes to each in-memory page */
drhed7c8552001-04-11 14:29:21 +0000113 int nPage; /* Total number of in-memory pages */
drhd9b02572001-04-15 00:37:09 +0000114 int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
drhed7c8552001-04-11 14:29:21 +0000115 int mxPage; /* Maximum number of pages to hold in cache */
drhd9b02572001-04-15 00:37:09 +0000116 int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
117 unsigned char state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */
118 unsigned char errMask; /* One of several kinds of errors */
drhed7c8552001-04-11 14:29:21 +0000119 PgHdr *pFirst, *pLast; /* List of free pages */
drhd9b02572001-04-15 00:37:09 +0000120 PgHdr *pAll; /* List of all pages */
drhed7c8552001-04-11 14:29:21 +0000121 PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */
drhd9b02572001-04-15 00:37:09 +0000122};
123
124/*
125** These are bits that can be set in Pager.errMask.
126*/
127#define PAGER_ERR_FULL 0x01 /* a write() failed */
128#define PAGER_ERR_MEM 0x02 /* malloc() failed */
129#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */
130#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */
131
132/*
133** The journal file contains page records in the following
134** format.
135*/
136typedef struct PageRecord PageRecord;
137struct PageRecord {
138 Pgno pgno; /* The page number */
139 char aData[SQLITE_PAGE_SIZE]; /* Original data for page pgno */
140};
141
142/*
143** Journal files begin with the following magic string. This data
144** is completely random. It is used only as a sanity check.
145*/
146static const unsigned char aJournalMagic[] = {
147 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4,
drhed7c8552001-04-11 14:29:21 +0000148};
149
150/*
151** Hash a page number
152*/
drhd9b02572001-04-15 00:37:09 +0000153#define pager_hash(PN) ((PN)%N_PG_HASH)
drhed7c8552001-04-11 14:29:21 +0000154
155/*
156** Attempt to acquire a read lock (if wrlock==0) or a write lock (if wrlock==1)
157** on the database file. Return 0 on success and non-zero if the lock
158** could not be acquired.
159*/
drhd9b02572001-04-15 00:37:09 +0000160static int pager_lock(int fd, int wrlock){
161 int rc;
drhed7c8552001-04-11 14:29:21 +0000162 struct flock lock;
drhd9b02572001-04-15 00:37:09 +0000163 lock.l_type = wrlock ? F_WRLCK : F_RDLCK;
164 lock.l_whence = SEEK_SET;
165 lock.l_start = lock.l_len = 0L;
166 rc = fcntl(fd, F_SETLK, &lock);
167 return rc!=0;
drhed7c8552001-04-11 14:29:21 +0000168}
169
170/*
171** Unlock the database file.
172*/
drhd9b02572001-04-15 00:37:09 +0000173static int pager_unlock(fd){
174 int rc;
drhed7c8552001-04-11 14:29:21 +0000175 struct flock lock;
176 lock.l_type = F_UNLCK;
drhd9b02572001-04-15 00:37:09 +0000177 lock.l_whence = SEEK_SET;
178 lock.l_start = lock.l_len = 0L;
179 rc = fcntl(fd, F_SETLK, &lock);
180 return rc!=0;
181}
182
183/*
184** Move the cursor for file descriptor fd to the point whereto from
185** the beginning of the file.
186*/
187static int pager_seek(int fd, off_t whereto){
188 lseek(fd, whereto, SEEK_SET);
189 return SQLITE_OK;
190}
191
192/*
193** Truncate the given file so that it contains exactly mxPg pages
194** of data.
195*/
196static int pager_truncate(int fd, Pgno mxPg){
197 int rc;
198 rc = ftruncate(fd, mxPg*SQLITE_PAGE_SIZE);
199 return rc!=0 ? SQLITE_IOERR : SQLITE_OK;
200}
201
202/*
203** Read nBytes of data from fd into pBuf. If the data cannot be
204** read or only a partial read occurs, then the unread parts of
205** pBuf are filled with zeros and this routine returns SQLITE_IOERR.
206** If the read is completely successful, return SQLITE_OK.
207*/
208static int pager_read(int fd, void *pBuf, int nByte){
209 int rc;
210 rc = read(fd, pBuf, nByte);
211 if( rc<0 ){
212 memset(pBuf, 0, nByte);
213 return SQLITE_IOERR;
214 }
215 if( rc<nByte ){
216 memset(&((char*)pBuf)[rc], 0, nByte - rc);
217 rc = SQLITE_IOERR;
218 }else{
219 rc = SQLITE_OK;
220 }
221 return rc;
222}
223
224/*
225** Write nBytes of data into fd. If any problem occurs or if the
226** write is incomplete, SQLITE_IOERR is returned. SQLITE_OK is
227** returned upon complete success.
228*/
229static int pager_write(int fd, const void *pBuf, int nByte){
230 int rc;
231 rc = write(fd, pBuf, nByte);
232 if( rc<nByte ){
233 return SQLITE_FULL;
234 }else{
235 return SQLITE_OK;
236 }
237}
238
239/*
240** Convert the bits in the pPager->errMask into an approprate
241** return code.
242*/
243static int pager_errcode(Pager *pPager){
244 int rc = SQLITE_OK;
245 if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
246 if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
247 if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM;
248 if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
249 return rc;
drhed7c8552001-04-11 14:29:21 +0000250}
251
252/*
253** Find a page in the hash table given its page number. Return
254** a pointer to the page or NULL if not found.
255*/
drhd9b02572001-04-15 00:37:09 +0000256static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
drhed7c8552001-04-11 14:29:21 +0000257 PgHdr *p = pPager->aHash[pgno % N_PG_HASH];
258 while( p && p->pgno!=pgno ){
259 p = p->pNextHash;
260 }
261 return p;
262}
263
264/*
265** Unlock the database and clear the in-memory cache. This routine
266** sets the state of the pager back to what it was when it was first
267** opened. Any outstanding pages are invalidated and subsequent attempts
268** to access those pages will likely result in a coredump.
269*/
drhd9b02572001-04-15 00:37:09 +0000270static void pager_reset(Pager *pPager){
drhed7c8552001-04-11 14:29:21 +0000271 PgHdr *pPg, *pNext;
drhd9b02572001-04-15 00:37:09 +0000272 for(pPg=pPager->pAll; pPg; pPg=pNext){
273 pNext = pPg->pNextAll;
274 sqliteFree(pPg);
drhed7c8552001-04-11 14:29:21 +0000275 }
276 pPager->pFirst = 0;
drhd9b02572001-04-15 00:37:09 +0000277 pPager->pLast = 0;
278 pPager->pAll = 0;
drhed7c8552001-04-11 14:29:21 +0000279 memset(pPager->aHash, 0, sizeof(pPager->aHash));
280 pPager->nPage = 0;
281 if( pPager->state==SQLITE_WRITELOCK ){
drhd9b02572001-04-15 00:37:09 +0000282 sqlitepager_rollback(pPager);
drhed7c8552001-04-11 14:29:21 +0000283 }
drhd9b02572001-04-15 00:37:09 +0000284 pager_unlock(pPager->fd);
drhed7c8552001-04-11 14:29:21 +0000285 pPager->state = SQLITE_UNLOCK;
drhd9b02572001-04-15 00:37:09 +0000286 pPager->dbSize = -1;
drhed7c8552001-04-11 14:29:21 +0000287 pPager->nRef = 0;
288}
289
290/*
291** When this routine is called, the pager has the journal file open and
292** a write lock on the database. This routine releases the database
293** write lock and acquires a read lock in its place. The journal file
294** is deleted and closed.
295**
296** We have to release the write lock before acquiring the read lock,
297** so there is a race condition where another process can get the lock
298** while we are not holding it. But, no other process should do this
299** because we are also holding a lock on the journal, and no process
300** should get a write lock on the database without first getting a lock
301** on the journal. So this routine should never fail. But it can fail
302** if another process is not playing by the rules. If it does fail,
drhd9b02572001-04-15 00:37:09 +0000303** all in-memory cache pages are invalidated, the PAGER_ERR_LOCK bit
304** is set in pPager->errMask, and this routine returns SQLITE_PROTOCOL.
305** SQLITE_OK is returned on success.
drhed7c8552001-04-11 14:29:21 +0000306*/
drhd9b02572001-04-15 00:37:09 +0000307static int pager_unwritelock(Pager *pPager){
drhed7c8552001-04-11 14:29:21 +0000308 int rc;
drhd9b02572001-04-15 00:37:09 +0000309 PgHdr *pPg;
310 if( pPager->state!=SQLITE_WRITELOCK ) return SQLITE_OK;
311 pager_unlock(pPager->fd);
312 rc = pager_lock(pPager->fd, 0);
drhed7c8552001-04-11 14:29:21 +0000313 unlink(pPager->zJournal);
314 close(pPager->jfd);
315 pPager->jfd = -1;
drhd9b02572001-04-15 00:37:09 +0000316 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
317 pPg->inJournal = 0;
318 pPg->dirty = 0;
319 }
drhed7c8552001-04-11 14:29:21 +0000320 if( rc!=SQLITE_OK ){
321 pPager->state = SQLITE_UNLOCK;
drhed7c8552001-04-11 14:29:21 +0000322 rc = SQLITE_PROTOCOL;
drhd9b02572001-04-15 00:37:09 +0000323 pPager->errMask |= PAGER_ERR_LOCK;
drhed7c8552001-04-11 14:29:21 +0000324 }else{
drhd9b02572001-04-15 00:37:09 +0000325 rc = SQLITE_OK;
drhed7c8552001-04-11 14:29:21 +0000326 pPager->state = SQLITE_READLOCK;
327 }
328 return rc;
329}
330
drhed7c8552001-04-11 14:29:21 +0000331/*
332** Playback the journal and thus restore the database file to
333** the state it was in before we started making changes.
334**
drhd9b02572001-04-15 00:37:09 +0000335** The journal file format is as follows: There is an initial
336** file-type string for sanity checking. Then there is a single
337** Pgno number which is the number of pages in the database before
338** changes were made. The database is truncated to this size.
339** Next come zero or more page records which each page record
340** consists of a Pgno, SQLITE_PAGE_SIZE bytes of data.
drhed7c8552001-04-11 14:29:21 +0000341**
drhd9b02572001-04-15 00:37:09 +0000342** For playback, the pages have to be read from the journal in
343** reverse order and put back into the original database file.
drhed7c8552001-04-11 14:29:21 +0000344**
drhd9b02572001-04-15 00:37:09 +0000345** If the file opened as the journal file is not a well-formed
346** journal file (as determined by looking at the magic number
347** at the beginning) then this routine returns SQLITE_PROTOCOL.
348** If any other errors occur during playback, the database will
349** likely be corrupted, so the PAGER_ERR_CORRUPT bit is set in
350** pPager->errMask and SQLITE_CORRUPT is returned. If it all
351** works, then this routine returns SQLITE_OK.
drhed7c8552001-04-11 14:29:21 +0000352*/
drhd9b02572001-04-15 00:37:09 +0000353static int pager_playback(Pager *pPager){
354 int nRec; /* Number of Records */
355 int i; /* Loop counter */
356 Pgno mxPg = 0; /* Size of the original file in pages */
357 struct stat statbuf; /* Used to size the journal */
358 PgHdr *pPg; /* An existing page in the cache */
359 PageRecord pgRec;
360 unsigned char aMagic[sizeof(aJournalMagic)];
drhed7c8552001-04-11 14:29:21 +0000361 int rc;
362
drhd9b02572001-04-15 00:37:09 +0000363 /* Read the beginning of the journal and truncate the
364 ** database file back to its original size.
drhed7c8552001-04-11 14:29:21 +0000365 */
drhd9b02572001-04-15 00:37:09 +0000366 assert( pPager->jfd>=0 );
367 pager_seek(pPager->jfd, 0);
368 rc = pager_read(pPager->jfd, aMagic, sizeof(aMagic));
369 if( rc!=SQLITE_OK || memcmp(aMagic,aJournalMagic,sizeof(aMagic))!=0 ){
370 return SQLITE_PROTOCOL;
371 }
372 rc = pager_read(pPager->jfd, &mxPg, sizeof(mxPg));
373 if( rc!=SQLITE_OK ){
374 return SQLITE_PROTOCOL;
375 }
376 pager_truncate(pPager->fd, mxPg);
377 pPager->dbSize = mxPg;
378
379 /* Begin reading the journal beginning at the end and moving
380 ** toward the beginning.
381 */
382 if( fstat(pPager->jfd, &statbuf)!=0 ){
drhed7c8552001-04-11 14:29:21 +0000383 return SQLITE_OK;
384 }
drhd9b02572001-04-15 00:37:09 +0000385 nRec = (statbuf.st_size - (sizeof(aMagic)+sizeof(Pgno))) / sizeof(PageRecord);
drhed7c8552001-04-11 14:29:21 +0000386
387 /* Process segments beginning with the last and working backwards
388 ** to the first.
389 */
drhd9b02572001-04-15 00:37:09 +0000390 for(i=nRec-1; i>=0; i--){
drhed7c8552001-04-11 14:29:21 +0000391 /* Seek to the beginning of the segment */
drhd9b02572001-04-15 00:37:09 +0000392 off_t ofst;
393 ofst = i*sizeof(PageRecord) + sizeof(aMagic) + sizeof(Pgno);
394 rc = pager_seek(pPager->jfd, ofst);
395 if( rc!=SQLITE_OK ) break;
396 rc = pager_read(pPager->jfd, &pgRec, sizeof(pgRec));
397 if( rc!=SQLITE_OK ) break;
drhed7c8552001-04-11 14:29:21 +0000398
drhd9b02572001-04-15 00:37:09 +0000399 /* Sanity checking on the page */
400 if( pgRec.pgno>mxPg || pgRec.pgno==0 ){
401 rc = SQLITE_CORRUPT;
402 break;
drhed7c8552001-04-11 14:29:21 +0000403 }
404
drhd9b02572001-04-15 00:37:09 +0000405 /* Playback the page. Update the in-memory copy of the page
406 ** at the same time, if there is one.
drhed7c8552001-04-11 14:29:21 +0000407 */
drhd9b02572001-04-15 00:37:09 +0000408 pPg = pager_lookup(pPager, pgRec.pgno);
409 if( pPg ){
410 memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
drhed7c8552001-04-11 14:29:21 +0000411 }
drhd9b02572001-04-15 00:37:09 +0000412 rc = pager_seek(pPager->fd, (pgRec.pgno-1)*SQLITE_PAGE_SIZE);
413 if( rc!=SQLITE_OK ) break;
414 rc = pager_write(pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
415 if( rc!=SQLITE_OK ) break;
drhed7c8552001-04-11 14:29:21 +0000416 }
drhd9b02572001-04-15 00:37:09 +0000417 if( rc!=SQLITE_OK ){
418 pager_unwritelock(pPager);
419 pPager->errMask |= PAGER_ERR_CORRUPT;
420 rc = SQLITE_CORRUPT;
421 }else{
422 rc = pager_unwritelock(pPager);
drhed7c8552001-04-11 14:29:21 +0000423 }
drhd9b02572001-04-15 00:37:09 +0000424 return rc;
drhed7c8552001-04-11 14:29:21 +0000425}
426
427/*
428** Create a new page cache and put a pointer to the page cache in *ppPager.
429** The file to be cached need not exist. The file is not opened until
drhd9b02572001-04-15 00:37:09 +0000430** the first call to sqlitepager_get() and is only held open until the
431** last page is released using sqlitepager_unref().
drhed7c8552001-04-11 14:29:21 +0000432*/
drh7e3b0a02001-04-28 16:52:40 +0000433int sqlitepager_open(
434 Pager **ppPager, /* Return the Pager structure here */
435 const char *zFilename, /* Name of the database file to open */
436 int mxPage, /* Max number of in-memory cache pages */
437 int nExtra /* Extra bytes append to each in-memory page */
438){
drhed7c8552001-04-11 14:29:21 +0000439 Pager *pPager;
440 int nameLen;
441 int fd;
442
drhd9b02572001-04-15 00:37:09 +0000443 *ppPager = 0;
444 if( sqlite_malloc_failed ){
445 return SQLITE_NOMEM;
446 }
447 fd = open(zFilename, O_RDWR|O_CREAT, 0644);
drhed7c8552001-04-11 14:29:21 +0000448 if( fd<0 ){
449 return SQLITE_CANTOPEN;
450 }
451 nameLen = strlen(zFilename);
452 pPager = sqliteMalloc( sizeof(*pPager) + nameLen*2 + 30 );
drhd9b02572001-04-15 00:37:09 +0000453 if( pPager==0 ){
454 close(fd);
455 return SQLITE_NOMEM;
456 }
drhed7c8552001-04-11 14:29:21 +0000457 pPager->zFilename = (char*)&pPager[1];
458 pPager->zJournal = &pPager->zFilename[nameLen+1];
459 strcpy(pPager->zFilename, zFilename);
460 strcpy(pPager->zJournal, zFilename);
461 strcpy(&pPager->zJournal[nameLen], "-journal");
462 pPager->fd = fd;
463 pPager->jfd = -1;
464 pPager->nRef = 0;
465 pPager->dbSize = -1;
466 pPager->nPage = 0;
drhd79caeb2001-04-15 02:27:24 +0000467 pPager->mxPage = mxPage>5 ? mxPage : 10;
drhed7c8552001-04-11 14:29:21 +0000468 pPager->state = SQLITE_UNLOCK;
drhd9b02572001-04-15 00:37:09 +0000469 pPager->errMask = 0;
drhed7c8552001-04-11 14:29:21 +0000470 pPager->pFirst = 0;
471 pPager->pLast = 0;
472 memset(pPager->aHash, 0, sizeof(pPager->aHash));
473 *ppPager = pPager;
474 return SQLITE_OK;
475}
476
477/*
478** Return the total number of pages in the file opened by pPager.
479*/
drhd9b02572001-04-15 00:37:09 +0000480int sqlitepager_pagecount(Pager *pPager){
drhed7c8552001-04-11 14:29:21 +0000481 int n;
482 struct stat statbuf;
drhd9b02572001-04-15 00:37:09 +0000483 assert( pPager!=0 );
drhed7c8552001-04-11 14:29:21 +0000484 if( pPager->dbSize>=0 ){
485 return pPager->dbSize;
486 }
487 if( fstat(pPager->fd, &statbuf)!=0 ){
488 n = 0;
489 }else{
490 n = statbuf.st_size/SQLITE_PAGE_SIZE;
491 }
drhd9b02572001-04-15 00:37:09 +0000492 if( pPager->state!=SQLITE_UNLOCK ){
drhed7c8552001-04-11 14:29:21 +0000493 pPager->dbSize = n;
494 }
495 return n;
496}
497
498/*
499** Shutdown the page cache. Free all memory and close all files.
500**
501** If a transaction was in progress when this routine is called, that
502** transaction is rolled back. All outstanding pages are invalidated
503** and their memory is freed. Any attempt to use a page associated
504** with this page cache after this function returns will likely
505** result in a coredump.
506*/
drhd9b02572001-04-15 00:37:09 +0000507int sqlitepager_close(Pager *pPager){
508 PgHdr *pPg, *pNext;
drhed7c8552001-04-11 14:29:21 +0000509 switch( pPager->state ){
510 case SQLITE_WRITELOCK: {
drhd9b02572001-04-15 00:37:09 +0000511 sqlitepager_rollback(pPager);
512 pager_unlock(pPager->fd);
drhed7c8552001-04-11 14:29:21 +0000513 break;
514 }
515 case SQLITE_READLOCK: {
drhd9b02572001-04-15 00:37:09 +0000516 pager_unlock(pPager->fd);
drhed7c8552001-04-11 14:29:21 +0000517 break;
518 }
519 default: {
520 /* Do nothing */
521 break;
522 }
523 }
drhd9b02572001-04-15 00:37:09 +0000524 for(pPg=pPager->pAll; pPg; pPg=pNext){
525 pNext = pPg->pNextAll;
526 sqliteFree(pPg);
drhed7c8552001-04-11 14:29:21 +0000527 }
528 if( pPager->fd>=0 ) close(pPager->fd);
529 assert( pPager->jfd<0 );
530 sqliteFree(pPager);
531 return SQLITE_OK;
532}
533
534/*
535** Return the page number for the given page data
536*/
drhd9b02572001-04-15 00:37:09 +0000537Pgno sqlitepager_pagenumber(void *pData){
drhed7c8552001-04-11 14:29:21 +0000538 PgHdr *p = DATA_TO_PGHDR(pData);
539 return p->pgno;
540}
541
542/*
drh7e3b0a02001-04-28 16:52:40 +0000543** Increment the reference count for a page. If the page is
544** currently on the freelist (the reference count is zero) then
545** remove it from the freelist.
546*/
547static void sqlitepager_ref(PgHdr *pPg){
548 if( pPg->nRef==0 ){
549 /* The page is currently on the freelist. Remove it. */
550 if( pPg->pPrevFree ){
551 pPg->pPrevFree->pNextFree = pPg->pNextFree;
552 }else{
553 pPg->pPager->pFirst = pPg->pNextFree;
554 }
555 if( pPg->pNextFree ){
556 pPg->pNextFree->pPrevFree = pPg->pPrevFree;
557 }else{
558 pPg->pPager->pLast = pPg->pPrevFree;
559 }
560 pPg->pPager->nRef++;
561 }
562 pPg->nRef++;
563}
564
565/*
drhd9b02572001-04-15 00:37:09 +0000566** Acquire a page.
567**
568** A read lock is obtained for the first page acquired. The lock
569** is dropped when the last page is released.
570**
571** The acquisition might fail for several reasons. In all cases,
572** an appropriate error code is returned and *ppPage is set to NULL.
drh7e3b0a02001-04-28 16:52:40 +0000573**
574** See also sqlitepager_lookup(). Both this routine and _lookup() attempt
575** to find a page in the in-memory cache first. If the page is not already
576** in cache, this routine goes to disk to read it in whereas _lookup()
577** just returns 0. This routine acquires a read-lock the first time it
578** has to go to disk, and could also playback an old journal if necessary.
579** Since _lookup() never goes to disk, it never has to deal with locks
580** or journal files.
drhed7c8552001-04-11 14:29:21 +0000581*/
drhd9b02572001-04-15 00:37:09 +0000582int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
drhed7c8552001-04-11 14:29:21 +0000583 PgHdr *pPg;
584
drhd9b02572001-04-15 00:37:09 +0000585 /* Make sure we have not hit any critical errors.
586 */
587 if( pPager==0 || pgno==0 ){
588 return SQLITE_ERROR;
589 }
590 if( pPager->errMask & ~(PAGER_ERR_FULL) ){
591 return pager_errcode(pPager);
592 }
593
drhed7c8552001-04-11 14:29:21 +0000594 /* If this is the first page accessed, then get a read lock
595 ** on the database file.
596 */
597 if( pPager->nRef==0 ){
drhd9b02572001-04-15 00:37:09 +0000598 if( pager_lock(pPager->fd, 0)!=0 ){
drhed7c8552001-04-11 14:29:21 +0000599 *ppPage = 0;
600 return SQLITE_BUSY;
601 }
drhd9b02572001-04-15 00:37:09 +0000602 pPager->state = SQLITE_READLOCK;
drhed7c8552001-04-11 14:29:21 +0000603
604 /* If a journal file exists, try to play it back.
605 */
606 if( access(pPager->zJournal,0)==0 ){
607 int rc;
608
609 /* Open the journal for exclusive access. Return SQLITE_BUSY if
610 ** we cannot get exclusive access to the journal file
611 */
612 pPager->jfd = open(pPager->zJournal, O_RDONLY, 0);
drhd9b02572001-04-15 00:37:09 +0000613 if( pPager->jfd<0 || pager_lock(pPager->jfd, 1)!=0 ){
drhed7c8552001-04-11 14:29:21 +0000614 if( pPager->jfd>=0 ){ close(pPager->jfd); pPager->jfd = -1; }
drhd9b02572001-04-15 00:37:09 +0000615 pager_unlock(pPager->fd);
drhed7c8552001-04-11 14:29:21 +0000616 *ppPage = 0;
617 return SQLITE_BUSY;
618 }
619
620 /* Get a write lock on the database */
drhd9b02572001-04-15 00:37:09 +0000621 pager_unlock(pPager->fd);
622 if( pager_lock(pPager->fd, 1)!=0 ){
623 close(pPager->jfd);
624 pPager->jfd = -1;
drhed7c8552001-04-11 14:29:21 +0000625 *ppPage = 0;
626 return SQLITE_PROTOCOL;
627 }
628
629 /* Playback and delete the journal. Drop the database write
630 ** lock and reacquire the read lock.
631 */
drhd9b02572001-04-15 00:37:09 +0000632 rc = pager_playback(pPager);
633 if( rc!=SQLITE_OK ){
634 return rc;
635 }
drhed7c8552001-04-11 14:29:21 +0000636 }
637 pPg = 0;
638 }else{
639 /* Search for page in cache */
drhd9b02572001-04-15 00:37:09 +0000640 pPg = pager_lookup(pPager, pgno);
drhed7c8552001-04-11 14:29:21 +0000641 }
642 if( pPg==0 ){
drhd9b02572001-04-15 00:37:09 +0000643 /* The requested page is not in the page cache. */
drhed7c8552001-04-11 14:29:21 +0000644 int h;
drh7e3b0a02001-04-28 16:52:40 +0000645 pPager->nMiss++;
drhed7c8552001-04-11 14:29:21 +0000646 if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 ){
647 /* Create a new page */
drh7e3b0a02001-04-28 16:52:40 +0000648 pPg = sqliteMalloc( sizeof(*pPg) + SQLITE_PAGE_SIZE + pPager->nExtra );
drhd9b02572001-04-15 00:37:09 +0000649 if( pPg==0 ){
650 *ppPage = 0;
651 pager_unwritelock(pPager);
652 pPager->errMask |= PAGER_ERR_MEM;
653 return SQLITE_NOMEM;
654 }
drhed7c8552001-04-11 14:29:21 +0000655 pPg->pPager = pPager;
drhd9b02572001-04-15 00:37:09 +0000656 pPg->pNextAll = pPager->pAll;
657 if( pPager->pAll ){
658 pPager->pAll->pPrevAll = pPg;
659 }
660 pPg->pPrevAll = 0;
drhd79caeb2001-04-15 02:27:24 +0000661 pPager->pAll = pPg;
drhd9b02572001-04-15 00:37:09 +0000662 pPager->nPage++;
drhed7c8552001-04-11 14:29:21 +0000663 }else{
drhd9b02572001-04-15 00:37:09 +0000664 /* Recycle an older page. First locate the page to be recycled.
665 ** Try to find one that is not dirty and is near the head of
666 ** of the free list */
667 int cnt = 4;
drhed7c8552001-04-11 14:29:21 +0000668 pPg = pPager->pFirst;
drhd9b02572001-04-15 00:37:09 +0000669 while( pPg->dirty && 0<cnt-- ){
670 pPg = pPg->pNextFree;
671 }
672 if( pPg==0 || pPg->dirty ) pPg = pPager->pFirst;
673 assert( pPg->nRef==0 );
674
675 /* If the page to be recycled is dirty, sync the journal and write
676 ** the old page into the database. */
drhed7c8552001-04-11 14:29:21 +0000677 if( pPg->dirty ){
678 int rc;
drhd9b02572001-04-15 00:37:09 +0000679 assert( pPg->inJournal==1 );
680 assert( pPager->state==SQLITE_WRITELOCK );
681 rc = fsync(pPager->jfd);
682 if( rc!=0 ){
683 rc = sqlitepager_rollback(pPager);
drhed7c8552001-04-11 14:29:21 +0000684 *ppPage = 0;
drhd9b02572001-04-15 00:37:09 +0000685 if( rc==SQLITE_OK ) rc = SQLITE_IOERR;
drhed7c8552001-04-11 14:29:21 +0000686 return rc;
687 }
drhd9b02572001-04-15 00:37:09 +0000688 pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
689 rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
690 if( rc!=SQLITE_OK ){
691 rc = sqlitepager_rollback(pPager);
692 *ppPage = 0;
693 if( rc==SQLITE_OK ) rc = SQLITE_FULL;
694 return rc;
695 }
696 }
697
698 /* Unlink the old page from the free list and the hash table
699 */
700 pPager->pFirst = pPg->pNextFree;
drhed7c8552001-04-11 14:29:21 +0000701 if( pPager->pFirst ){
drhd9b02572001-04-15 00:37:09 +0000702 pPager->pFirst->pPrevFree = 0;
drhed7c8552001-04-11 14:29:21 +0000703 }else{
704 pPager->pLast = 0;
705 }
706 if( pPg->pNextHash ){
707 pPg->pNextHash->pPrevHash = pPg->pPrevHash;
708 }
709 if( pPg->pPrevHash ){
710 pPg->pPrevHash->pNextHash = pPg->pNextHash;
711 }else{
drhd9b02572001-04-15 00:37:09 +0000712 h = pager_hash(pPg->pgno);
drhed7c8552001-04-11 14:29:21 +0000713 assert( pPager->aHash[h]==pPg );
714 pPager->aHash[h] = pPg->pNextHash;
715 }
drhd9b02572001-04-15 00:37:09 +0000716 pPager->nOvfl++;
drhed7c8552001-04-11 14:29:21 +0000717 }
718 pPg->pgno = pgno;
719 pPg->inJournal = 0;
720 pPg->dirty = 0;
721 pPg->nRef = 1;
drhd9b02572001-04-15 00:37:09 +0000722 pPager->nRef++;
723 h = pager_hash(pgno);
drhed7c8552001-04-11 14:29:21 +0000724 pPg->pNextHash = pPager->aHash[h];
725 pPager->aHash[h] = pPg;
726 if( pPg->pNextHash ){
727 assert( pPg->pNextHash->pPrevHash==0 );
728 pPg->pNextHash->pPrevHash = pPg;
729 }
drhd9b02572001-04-15 00:37:09 +0000730 pager_seek(pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
731 pager_read(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
drh7e3b0a02001-04-28 16:52:40 +0000732 if( pPager->nExtra>0 ){
733 memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
734 }
drhed7c8552001-04-11 14:29:21 +0000735 }else{
drhd9b02572001-04-15 00:37:09 +0000736 /* The requested page is in the page cache. */
drh7e3b0a02001-04-28 16:52:40 +0000737 pPager->nHit++;
738 sqlitepager_ref(pPg);
drhed7c8552001-04-11 14:29:21 +0000739 }
740 *ppPage = PGHDR_TO_DATA(pPg);
741 return SQLITE_OK;
742}
743
744/*
drh7e3b0a02001-04-28 16:52:40 +0000745** Acquire a page if it is already in the in-memory cache. Do
746** not read the page from disk. Return a pointer to the page,
747** or 0 if the page is not in cache.
748**
749** See also sqlitepager_get(). The difference between this routine
750** and sqlitepager_get() is that _get() will go to the disk and read
751** in the page if the page is not already in cache. This routine
752** returns NULL if the page is not in cache and no disk I/O ever
753** occurs.
754*/
755void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
756 PgHdr *pPg;
757
758 /* Make sure we have not hit any critical errors.
759 */
760 if( pPager==0 || pgno==0 ){
761 return 0;
762 }
763 if( pPager->errMask & ~(PAGER_ERR_FULL) ){
764 return 0;
765 }
766 if( pPager->nRef==0 ){
767 return 0;
768 }
769 pPg = pager_lookup(pPager, pgno);
770 if( pPg==0 ) return 0;
771 sqlitepager_ref(pPg);
772 return PGHDR_TO_DATA(pPg);
773}
774
775/*
drhed7c8552001-04-11 14:29:21 +0000776** Release a page.
777**
778** If the number of references to the page drop to zero, then the
779** page is added to the LRU list. When all references to all pages
drhd9b02572001-04-15 00:37:09 +0000780** are released, a rollback occurs and the lock on the database is
drhed7c8552001-04-11 14:29:21 +0000781** removed.
782*/
drhd9b02572001-04-15 00:37:09 +0000783int sqlitepager_unref(void *pData){
drhed7c8552001-04-11 14:29:21 +0000784 Pager *pPager;
785 PgHdr *pPg;
drhd9b02572001-04-15 00:37:09 +0000786
787 /* Decrement the reference count for this page
788 */
drhed7c8552001-04-11 14:29:21 +0000789 pPg = DATA_TO_PGHDR(pData);
790 assert( pPg->nRef>0 );
791 pPager = pPg->pPager;
792 pPg->nRef--;
drhd9b02572001-04-15 00:37:09 +0000793
794 /* When the number of references to a page reach 0, add the
795 ** page to the freelist.
796 */
drhed7c8552001-04-11 14:29:21 +0000797 if( pPg->nRef==0 ){
drhd9b02572001-04-15 00:37:09 +0000798 pPg->pNextFree = 0;
799 pPg->pPrevFree = pPager->pLast;
drhed7c8552001-04-11 14:29:21 +0000800 pPager->pLast = pPg;
drhd9b02572001-04-15 00:37:09 +0000801 if( pPg->pPrevFree ){
802 pPg->pPrevFree->pNextFree = pPg;
drhed7c8552001-04-11 14:29:21 +0000803 }else{
804 pPager->pFirst = pPg;
805 }
drhd9b02572001-04-15 00:37:09 +0000806
807 /* When all pages reach the freelist, drop the read lock from
808 ** the database file.
809 */
810 pPager->nRef--;
811 assert( pPager->nRef>=0 );
812 if( pPager->nRef==0 ){
813 pager_reset(pPager);
814 }
drhed7c8552001-04-11 14:29:21 +0000815 }
drhd9b02572001-04-15 00:37:09 +0000816 return SQLITE_OK;
drhed7c8552001-04-11 14:29:21 +0000817}
818
819/*
820** Mark a data page as writeable. The page is written into the journal
821** if it is not there already. This routine must be called before making
822** changes to a page.
823**
824** The first time this routine is called, the pager creates a new
825** journal and acquires a write lock on the database. If the write
826** lock could not be acquired, this routine returns SQLITE_BUSY. The
827** calling routine must check for that routine and be careful not to
828** change any page data until this routine returns SQLITE_OK.
drhd9b02572001-04-15 00:37:09 +0000829**
830** If the journal file could not be written because the disk is full,
831** then this routine returns SQLITE_FULL and does an immediate rollback.
832** All subsequent write attempts also return SQLITE_FULL until there
833** is a call to sqlitepager_commit() or sqlitepager_rollback() to
834** reset.
drhed7c8552001-04-11 14:29:21 +0000835*/
drhd9b02572001-04-15 00:37:09 +0000836int sqlitepager_write(void *pData){
drh69688d52001-04-14 16:38:23 +0000837 PgHdr *pPg = DATA_TO_PGHDR(pData);
838 Pager *pPager = pPg->pPager;
drhd79caeb2001-04-15 02:27:24 +0000839 int rc = SQLITE_OK;
drh69688d52001-04-14 16:38:23 +0000840
drhd9b02572001-04-15 00:37:09 +0000841 if( pPager->errMask ){
842 return pager_errcode(pPager);
843 }
844 pPg->dirty = 1;
drh69688d52001-04-14 16:38:23 +0000845 if( pPg->inJournal ){ return SQLITE_OK; }
drhd9b02572001-04-15 00:37:09 +0000846 assert( pPager->state!=SQLITE_UNLOCK );
drhed7c8552001-04-11 14:29:21 +0000847 if( pPager->state==SQLITE_READLOCK ){
848 pPager->jfd = open(pPager->zJournal, O_RDWR|O_CREAT, 0644);
849 if( pPager->jfd<0 ){
850 return SQLITE_CANTOPEN;
851 }
drhd9b02572001-04-15 00:37:09 +0000852 if( pager_lock(pPager->jfd, 1) ){
drhed7c8552001-04-11 14:29:21 +0000853 close(pPager->jfd);
854 pPager->jfd = -1;
855 return SQLITE_BUSY;
856 }
drhd9b02572001-04-15 00:37:09 +0000857 pager_unlock(pPager->fd);
858 if( pager_lock(pPager->fd, 1) ){
drhed7c8552001-04-11 14:29:21 +0000859 close(pPager->jfd);
860 pPager->jfd = -1;
861 pPager->state = SQLITE_UNLOCK;
drhd9b02572001-04-15 00:37:09 +0000862 pPager->errMask |= PAGER_ERR_LOCK;
drhed7c8552001-04-11 14:29:21 +0000863 return SQLITE_PROTOCOL;
864 }
865 pPager->state = SQLITE_WRITELOCK;
drhd9b02572001-04-15 00:37:09 +0000866 sqlitepager_pagecount(pPager);
drh69688d52001-04-14 16:38:23 +0000867 pPager->origDbSize = pPager->dbSize;
drhd9b02572001-04-15 00:37:09 +0000868 rc = pager_write(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
869 if( rc==SQLITE_OK ){
870 rc = pager_write(pPager->jfd, &pPager->dbSize, sizeof(Pgno));
871 }
872 if( rc!=SQLITE_OK ){
873 rc = pager_unwritelock(pPager);
874 if( rc==SQLITE_OK ) rc = SQLITE_FULL;
875 return rc;
876 }
drhed7c8552001-04-11 14:29:21 +0000877 }
drhd9b02572001-04-15 00:37:09 +0000878 assert( pPager->state==SQLITE_WRITELOCK );
drh69688d52001-04-14 16:38:23 +0000879 assert( pPager->jfd>=0 );
drhd9b02572001-04-15 00:37:09 +0000880 if( pPg->pgno <= pPager->origDbSize ){
881 rc = pager_write(pPager->jfd, &pPg->pgno, sizeof(Pgno));
882 if( rc==SQLITE_OK ){
883 rc = pager_write(pPager->jfd, pData, SQLITE_PAGE_SIZE);
884 }
885 if( rc!=SQLITE_OK ){
886 sqlitepager_rollback(pPager);
887 pPager->errMask |= PAGER_ERR_FULL;
888 return rc;
889 }
drh69688d52001-04-14 16:38:23 +0000890 }
drh69688d52001-04-14 16:38:23 +0000891 pPg->inJournal = 1;
drh69688d52001-04-14 16:38:23 +0000892 return rc;
drhed7c8552001-04-11 14:29:21 +0000893}
894
895/*
896** Commit all changes to the database and release the write lock.
drhd9b02572001-04-15 00:37:09 +0000897**
898** If the commit fails for any reason, a rollback attempt is made
899** and an error code is returned. If the commit worked, SQLITE_OK
900** is returned.
drhed7c8552001-04-11 14:29:21 +0000901*/
drhd9b02572001-04-15 00:37:09 +0000902int sqlitepager_commit(Pager *pPager){
drhed7c8552001-04-11 14:29:21 +0000903 int i, rc;
904 PgHdr *pPg;
drhd9b02572001-04-15 00:37:09 +0000905
906 if( pPager->errMask==PAGER_ERR_FULL ){
907 rc = sqlitepager_rollback(pPager);
908 if( rc==SQLITE_OK ) rc = SQLITE_FULL;
909 return rc;
910 }
911 if( pPager->errMask!=0 ){
912 rc = pager_errcode(pPager);
913 return rc;
914 }
915 if( pPager->state!=SQLITE_WRITELOCK ){
916 return SQLITE_ERROR;
917 }
drhed7c8552001-04-11 14:29:21 +0000918 assert( pPager->jfd>=0 );
919 if( fsync(pPager->jfd) ){
drhd9b02572001-04-15 00:37:09 +0000920 goto commit_abort;
drhed7c8552001-04-11 14:29:21 +0000921 }
922 for(i=0; i<N_PG_HASH; i++){
923 for(pPg=pPager->aHash[i]; pPg; pPg=pPg->pNextHash){
924 if( pPg->dirty==0 ) continue;
drhd9b02572001-04-15 00:37:09 +0000925 rc = pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
926 if( rc!=SQLITE_OK ) goto commit_abort;
927 rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
928 if( rc!=SQLITE_OK ) goto commit_abort;
drhed7c8552001-04-11 14:29:21 +0000929 }
930 }
drhd9b02572001-04-15 00:37:09 +0000931 if( fsync(pPager->fd) ) goto commit_abort;
932 rc = pager_unwritelock(pPager);
933 pPager->dbSize = -1;
934 return rc;
935
936 /* Jump here if anything goes wrong during the commit process.
937 */
938commit_abort:
939 rc = sqlitepager_rollback(pPager);
940 if( rc==SQLITE_OK ){
941 rc = SQLITE_FULL;
drhed7c8552001-04-11 14:29:21 +0000942 }
drhed7c8552001-04-11 14:29:21 +0000943 return rc;
944}
945
946/*
947** Rollback all changes. The database falls back to read-only mode.
948** All in-memory cache pages revert to their original data contents.
949** The journal is deleted.
drhd9b02572001-04-15 00:37:09 +0000950**
951** This routine cannot fail unless some other process is not following
952** the correct locking protocol (SQLITE_PROTOCOL) or unless some other
953** process is writing trash into the journal file (SQLITE_CORRUPT) or
954** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error
955** codes are returned for all these occasions. Otherwise,
956** SQLITE_OK is returned.
drhed7c8552001-04-11 14:29:21 +0000957*/
drhd9b02572001-04-15 00:37:09 +0000958int sqlitepager_rollback(Pager *pPager){
drhed7c8552001-04-11 14:29:21 +0000959 int rc;
drhd9b02572001-04-15 00:37:09 +0000960 if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
961 return pager_errcode(pPager);
drhed7c8552001-04-11 14:29:21 +0000962 }
drhd9b02572001-04-15 00:37:09 +0000963 if( pPager->state!=SQLITE_WRITELOCK ){
964 return SQLITE_OK;
965 }
966 rc = pager_playback(pPager);
967 if( rc!=SQLITE_OK ){
968 rc = SQLITE_CORRUPT;
969 pPager->errMask |= PAGER_ERR_CORRUPT;
970 }
971 pPager->dbSize = -1;
drhed7c8552001-04-11 14:29:21 +0000972 return rc;
973};
drhd9b02572001-04-15 00:37:09 +0000974
975/*
976** This routine is used for testing and analysis only.
977*/
978int *sqlitepager_stats(Pager *pPager){
979 static int a[9];
980 a[0] = pPager->nRef;
981 a[1] = pPager->nPage;
982 a[2] = pPager->mxPage;
983 a[3] = pPager->dbSize;
984 a[4] = pPager->state;
985 a[5] = pPager->errMask;
986 a[6] = pPager->nHit;
987 a[7] = pPager->nMiss;
988 a[8] = pPager->nOvfl;
989 return a;
990}