/ Check-in [54eff6de]
Login
Overview
Comment:Add comments describing UNKNOWN_LOCK to pager.c. Improve some other comments in the same file.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:54eff6de9d8d87f33192c192ca91907c4c090988
User & Date: dan 2010-08-05 18:53:27
Original Comment: Add comments describing UNKNOWN_LOCK to pager.c. Improve some other comments i the same file.
Context
2010-08-06
06:54
Fix a bug to do with deleting the journal file when exiting exclusive-locking mode. check-in: 6217b607 user: dan tags: experimental
2010-08-05
18:53
Add comments describing UNKNOWN_LOCK to pager.c. Improve some other comments in the same file. check-in: 54eff6de user: dan tags: experimental
16:22
Merge trunk changes with experimental branch. check-in: acd26b8b user: dan tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

159
160
161
162
163
164
165
166








167
168
169
170
171



172
173
174
175
176
177
178
...
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302



303
304
305
306

307
308
309
310
311
312
313
314


315
316
317
318

319
320
321
322
323
324
325


326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
...
394
395
396
397
398
399
400


401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
715
716
717
718
719
720
721

722
723
724
725
726
727
728
...
895
896
897
898
899
900
901
902

903
904




905
906
907

908


909
910
911
912
913
914
915
916
917
918
919
920










921
922

923
924
925
926

927
928
929
930
931
932
933
....
1579
1580
1581
1582
1583
1584
1585





1586
1587
1588
1589
1590
1591
1592
....
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
....
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
....
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
....
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
....
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
**
**  READER:
**
**    In this state all the requirements for reading the database in 
**    rollback (non-WAL) mode are met. Unless the pager is (or recently
**    was) in exclusive-locking mode, a user-level read transaction is 
**    open. The database size is known in this state.
** 








**    * A read transaction may be active.
**    * A SHARED or greater lock is held on the database file.
**    * The dbSize variable may be trusted (even if a user-level read 
**      transaction is not active). The dbOrigSize and dbFileSize variables
**      may not be trusted at this point.



**
**  WRITER_INITIAL:
**
**    * A write transaction is active.
**    * A RESERVED or greater lock is held on the database file.
**    * The dbSize, dbOrigSize and dbFileSize variables are all valid.
**    * The contents of the pager cache have not been modified.
................................................................................
#define PAGER_READER                1
#define PAGER_WRITER_INITIAL        2
#define PAGER_WRITER_CACHEMOD       3
#define PAGER_WRITER_DBMOD          4
#define PAGER_WRITER_FINISHED       5
#define PAGER_ERROR                 6


/*

** The page cache as a whole is always in one of the following
** states:
**
**   PAGER_UNLOCK        The page cache is not currently reading or 
**                       writing the database file.  There is no
**                       data held in memory.  This is the initial
**                       state.
**



**   PAGER_SHARED        The page cache is reading the database.
**                       Writing is not permitted.  There can be
**                       multiple readers accessing the same database
**                       file at the same time.

**
**   PAGER_RESERVED      This process has reserved the database for writing
**                       but has not yet made any changes.  Only one process
**                       at a time can reserve the database.  The original
**                       database file has not been modified so other
**                       processes may still be reading the on-disk
**                       database file.
**


**   PAGER_EXCLUSIVE     The page cache is writing the database.
**                       Access is exclusive.  No other processes or
**                       threads can be reading or writing while one
**                       process is writing.

**
**   PAGER_SYNCED        The pager moves to this state from PAGER_EXCLUSIVE
**                       after all dirty pages have been written to the
**                       database file and the file has been synced to
**                       disk. All that remains to do is to remove or
**                       truncate the journal file and the transaction 
**                       will be committed.


**
** The page cache comes up in PAGER_UNLOCK.  The first time a
** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED.
** After all pages have been released using sqlite_page_unref(),
** the state transitions back to PAGER_UNLOCK.  The first time
** that sqlite3PagerWrite() is called, the state transitions to
** PAGER_RESERVED.  (Note that sqlite3PagerWrite() can only be
** called on an outstanding page which means that the pager must
** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
** PAGER_RESERVED means that there is an open rollback journal.
** The transition to PAGER_EXCLUSIVE occurs before any changes
** are made to the database file, though writes to the rollback
** journal occurs with just PAGER_RESERVED.  After an sqlite3PagerRollback()
** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED,
** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode.
*/
#define PAGER_UNLOCK      0
#define PAGER_SHARED      1   /* same as SHARED_LOCK */
#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
#define PAGER_SYNCED      5

#define UNKNOWN_LOCK      (EXCLUSIVE_LOCK+1)

/*
** A macro used for invoking the codec if there is one
*/
#ifdef SQLITE_HAS_CODEC
# define CODEC1(P,D,N,X,E) \
    if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
................................................................................
#endif
};

/*
** A open page cache is an instance of the following structure.
**
** errCode


**
**   Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or
**   or SQLITE_FULL. Once one of the first three errors occurs, it persists
**   and is returned as the result of every major pager API call.  The
**   SQLITE_FULL return code is slightly different. It persists only until the
**   next successful rollback is performed on the pager cache. Also,
**   SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup()
**   APIs, they may still be used successfully.
**
** dbSize, dbOrigSize, dbFileSize
**
**   Managing the size of the database file in pages is a little complicated.
**   The variable Pager.dbSize contains the number of pages that the database
**   image currently contains. As the database image grows or shrinks this
**   variable is updated. The variable Pager.dbFileSize contains the number
**   of pages in the database file. This may be different from Pager.dbSize
**   if some pages have been appended to the database image but not yet written
**   out from the cache to the actual file on disk. Or if the image has been
**   truncated by an incremental-vacuum operation. The Pager.dbOrigSize variable
**   contains the number of pages in the database image when the current
**   transaction was opened. The contents of all three of these variables is
**   only guaranteed to be correct if the boolean Pager.dbSizeValid is true.
**
**   TODO: Under what conditions is dbSizeValid set? Cleared?
**
** changeCountDone
**
**   This boolean variable is used to make sure that the change-counter 
**   (the 4-byte header field at byte offset 24 of the database file) is 
**   not updated more often than necessary. 
**
................................................................................
  /* Check that MEMDB implies noSync. */
  assert( !MEMDB || p->noSync );

  /* If changeCountDone is set, a RESERVED lock or greater must be held
  ** on the file.
  */
  assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );


  switch( p->eState ){
    case PAGER_NONE:
      assert( !MEMDB );
      assert( pPager->errCode==SQLITE_OK );
      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
      break;
................................................................................
static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
  char ac[4];
  put32bits(ac, val);
  return sqlite3OsWrite(fd, ac, 4, offset);
}

/*
** This function and pagerLockDb() are wrappers around sqlite3OsLock() and

** sqlite3OsUnlock() that set the Pager.eLock variable to reflect the
** current lock held on the database file.




*/
static int pagerUnlockDb(Pager *pPager, int eLock){
  int rc = SQLITE_OK;

  assert( !pPager->exclusiveMode );


  if( isOpen(pPager->fd) ){
    assert( pPager->eLock>=eLock );
    assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
    rc = sqlite3OsUnlock(pPager->fd, eLock);
    if( pPager->eLock!=UNKNOWN_LOCK ){
      pPager->eLock = eLock;
    }
    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
  }
  return rc;
}











static int pagerLockDb(Pager *pPager, int eLock){
  int rc;

  assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
  if( pPager->eLock>=eLock && pPager->eLock!=UNKNOWN_LOCK ){
    rc = SQLITE_OK;
  }else{

    rc = sqlite3OsLock(pPager->fd, eLock);
    if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
      pPager->eLock = eLock;
      IOTRACE(("LOCK %p %d\n", pPager, eLock))
    }
  }
  return rc;
................................................................................
    assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
    if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
     || 1!=(pPager->journalMode & 5)
    ){
      sqlite3OsClose(pPager->jfd);
    }






    rc = pagerUnlockDb(pPager, NO_LOCK);
    if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
      pPager->eLock = UNKNOWN_LOCK;
    }

    /* The pager state may be changed from PAGER_ERROR to PAGER_NONE here
    ** without clearing the error code. This is intentional - the error
................................................................................
** other writers or checkpointers.
*/
static int pagerBeginReadTransaction(Pager *pPager){
  int rc;                         /* Return code */
  int changed = 0;                /* True if cache must be reset */

  assert( pagerUseWal(pPager) );
  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_SHARED );

  /* sqlite3WalEndReadTransaction() was not called for the previous
  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  ** are in locking_mode=NORMAL and EndRead() was previously called,
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pPager->pWal);
................................................................................
** This function may only be called when a read-transaction is open on
** the pager. It returns the total number of pages in the database.
**
** However, if the file is between 1 and <page-size> bytes in size, then 
** this is considered a 1 page file.
*/
int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
  assert( pPager->eState>=PAGER_SHARED );
  assert( pPager->eState!=PAGER_WRITER_FINISHED );
  *pnPage = (int)pPager->dbSize;
  return SQLITE_OK;
}


/*
................................................................................
** Return SQLITE_OK on success and an error code if we cannot obtain
** the lock. If the lock is obtained successfully, set the Pager.state 
** variable to locktype before returning.
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
  int rc;                              /* Return code */

  /* The OS lock values must be the same as the Pager lock values */
  assert( PAGER_SHARED==SHARED_LOCK );
  assert( PAGER_RESERVED==RESERVED_LOCK );
  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );

  /* Check that this is either a no-op (because the requested lock is 
  ** already held, or one of the transistions that the busy-handler
  ** may be invoked during, according to the comment above
  ** sqlite3PagerSetBusyhandler().
  */
  assert( (pPager->eLock>=locktype)
       || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
................................................................................

    assert( !MEMDB );
    assert( pPager->noReadlock==0 || pPager->readOnly );

    if( pPager->noReadlock==0 ){
      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
      if( rc!=SQLITE_OK ){
        assert( pPager->eLock==PAGER_UNLOCK );
        goto failed;
      }
    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
    */
................................................................................
  int rc = SQLITE_OK;
  assert( pPager->eState==PAGER_WRITER_CACHEMOD 
       || pPager->eState==PAGER_WRITER_DBMOD 
       || pPager->eState==PAGER_WRITER_INITIAL 
  );
  assert( assert_pager_state(pPager) );
  if( 0==pagerUseWal(pPager) ){
    rc = pager_wait_on_lock(pPager, PAGER_EXCLUSIVE);
  }
  return rc;
}

/*
** Sync the database file for the pager pPager. zMaster points to the name
** of a master journal file that should be written into the individual







|
>
>
>
>
>
>
>
>
|




>
>
>







 







<

>
|
|
|
|
<
<
<

>
>
>
|
|
|
|
>

<
|
|
|
<
<

>
>
|
|
|
|
>

<
|
|
|
|
|
>
>

<
<
|
|
|
|
|
|
|
|
|
|
|
<

<
<
<
<
<
<
|







 







>
>

|
<
<
|
<
<
<












|
<
<
<







 







>







 







|
>
|
<
>
>
>
>



>

>
>


<









>
>
>
>
>
>
>
>
>
>

|
>

<
<
<
>







 







>
>
>
>
>







 







|







 







|







 







<
<
<
<
<







 







|







 







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
297
298
299
300
301
302
303

304
305
306
307
308
309



310
311
312
313
314
315
316
317
318
319

320
321
322


323
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
339


340
341
342
343
344
345
346
347
348
349
350

351






352
353
354
355
356
357
358
359
...
398
399
400
401
402
403
404
405
406
407
408


409



410
411
412
413
414
415
416
417
418
419
420
421
422



423
424
425
426
427
428
429
...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
...
894
895
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939



940
941
942
943
944
945
946
947
....
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
....
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
....
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
....
3323
3324
3325
3326
3327
3328
3329





3330
3331
3332
3333
3334
3335
3336
....
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
....
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
**
**  READER:
**
**    In this state all the requirements for reading the database in 
**    rollback (non-WAL) mode are met. Unless the pager is (or recently
**    was) in exclusive-locking mode, a user-level read transaction is 
**    open. The database size is known in this state.
**
**    A connection running with locking_mode=normal enters this state when
**    it opens a read-transaction on the database and returns to state
**    NONE after the read-transaction is completed. However a connection
**    running in locking_mode=exclusive (including temp databases) remains in
**    this state even after the read-transaction is closed. The only way
**    a locking_mode=exclusive connection can transition from READER to NONE
**    is via the ERROR state (see below).
** 
**    * A read transaction may be active (but a write-transaction cannot).
**    * A SHARED or greater lock is held on the database file.
**    * The dbSize variable may be trusted (even if a user-level read 
**      transaction is not active). The dbOrigSize and dbFileSize variables
**      may not be trusted at this point.
**    * If the database is a WAL database, then the WAL connection is open.
**    * Even if a read-transaction is not open, it is guaranteed that 
**      there is no hot-journal in the file-system.
**
**  WRITER_INITIAL:
**
**    * A write transaction is active.
**    * A RESERVED or greater lock is held on the database file.
**    * The dbSize, dbOrigSize and dbFileSize variables are all valid.
**    * The contents of the pager cache have not been modified.
................................................................................
#define PAGER_READER                1
#define PAGER_WRITER_INITIAL        2
#define PAGER_WRITER_CACHEMOD       3
#define PAGER_WRITER_DBMOD          4
#define PAGER_WRITER_FINISHED       5
#define PAGER_ERROR                 6


/*
** The Pager.eLock variable is almost always set to one of the 
** following locking-states, according to the lock currently held on
** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
** This variable is kept up to date as locks are taken and released by
** the pagerLockDb() and pagerUnlockDb() wrappers.



**
** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
** the operation was successful. In these circumstances pagerLockDb() and
** pagerUnlockDb() take a conservative approach - eLock is always updated
** when unlocking the file, and only updated when locking the file if the
** VFS call is successful. This way, the Pager.eLock variable may be set
** to a less exclusive (lower) value than the lock that is actually held
** at the system level, but it is never set to a more exclusive value.
**

** This is usually safe. If an xUnlock fails or appears to fail, there may 
** be a few redundant xLock() calls or a lock may be held for longer than
** required, but nothing really goes wrong.


**
** The exception is when the database file is unlocked as the pager moves
** from ERROR to NONE state. At this point there may be a hot-journal file 
** in the file-system that needs to be rolled back (as part of a NONE->SHARED
** transition, by the same pager or any other). If the call to xUnlock()
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
** can confuse the call to xCheckReservedLock() call made later as part
** of hot-journal detection.
**

** xCheckReservedLock() is defined as returning true "if there is a RESERVED 
** lock held by this process or any others". So xCheckReservedLock may 
** return true because the caller itself is holding an EXCLUSIVE lock (but
** doesn't know it because of a previous error in xUnlock). If this happens
** a hot-journal may be mistaken for a journal being created by an active
** transaction in another process, causing SQLite to read from the database
** without rolling it back.
**


** To work around this, if a call to xUnlock() fails when unlocking the
** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
** is only changed back to a real locking state after a successful call
** to xLock(EXCLUSIVE). Also, the code to do the NONE->SHARED state transition
** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK 
** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
** lock on the database file before attempting to roll it back. See function
** PagerSharedLock() for more detail.
**
** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in 
** PAGER_NONE state.

*/






#define UNKNOWN_LOCK                (EXCLUSIVE_LOCK+1)

/*
** A macro used for invoking the codec if there is one
*/
#ifdef SQLITE_HAS_CODEC
# define CODEC1(P,D,N,X,E) \
    if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
................................................................................
#endif
};

/*
** A open page cache is an instance of the following structure.
**
** errCode
**   The Pager.errCode variable is only ever non-zero when the condition
**   (Pager.eState==PAGER_ERROR) is true. 
**
**   Pager.errCode may be set to SQLITE_FULL, SQLITE_IOERR or one of the


**   SQLITE_IOERR_XXX sub-codes.



**
** dbSize, dbOrigSize, dbFileSize
**
**   Managing the size of the database file in pages is a little complicated.
**   The variable Pager.dbSize contains the number of pages that the database
**   image currently contains. As the database image grows or shrinks this
**   variable is updated. The variable Pager.dbFileSize contains the number
**   of pages in the database file. This may be different from Pager.dbSize
**   if some pages have been appended to the database image but not yet written
**   out from the cache to the actual file on disk. Or if the image has been
**   truncated by an incremental-vacuum operation. The Pager.dbOrigSize variable
**   contains the number of pages in the database image when the current
**   transaction was opened. 



**
** changeCountDone
**
**   This boolean variable is used to make sure that the change-counter 
**   (the 4-byte header field at byte offset 24 of the database file) is 
**   not updated more often than necessary. 
**
................................................................................
  /* Check that MEMDB implies noSync. */
  assert( !MEMDB || p->noSync );

  /* If changeCountDone is set, a RESERVED lock or greater must be held
  ** on the file.
  */
  assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
  assert( p->eLock!=PENDING_LOCK );

  switch( p->eState ){
    case PAGER_NONE:
      assert( !MEMDB );
      assert( pPager->errCode==SQLITE_OK );
      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
      break;
................................................................................
static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
  char ac[4];
  put32bits(ac, val);
  return sqlite3OsWrite(fd, ac, 4, offset);
}

/*
** Unlock the database file to level eLock, which must be either NO_LOCK
** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
** succeeds, set the Pager.eLock variable to match the (attempted) new lock.

**
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
** called, do not modify it. See the comment above the #define of 
** UNKNOWN_LOCK for an explanation of this.
*/
static int pagerUnlockDb(Pager *pPager, int eLock){
  int rc = SQLITE_OK;

  assert( !pPager->exclusiveMode );
  assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
  assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
  if( isOpen(pPager->fd) ){
    assert( pPager->eLock>=eLock );

    rc = sqlite3OsUnlock(pPager->fd, eLock);
    if( pPager->eLock!=UNKNOWN_LOCK ){
      pPager->eLock = eLock;
    }
    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
  }
  return rc;
}

/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
** Pager.eLock variable to the new locking state. 
**
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is 
** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. 
** See the comment above the #define of UNKNOWN_LOCK for an explanation 
** of this.
*/
static int pagerLockDb(Pager *pPager, int eLock){
  int rc = SQLITE_OK;

  assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );



  if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
    rc = sqlite3OsLock(pPager->fd, eLock);
    if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
      pPager->eLock = eLock;
      IOTRACE(("LOCK %p %d\n", pPager, eLock))
    }
  }
  return rc;
................................................................................
    assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
    if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
     || 1!=(pPager->journalMode & 5)
    ){
      sqlite3OsClose(pPager->jfd);
    }

    /* If the pager is in the ERROR state and the call to unlock the database
    ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
    ** above the #define for UNKNOWN_LOCK for an explanation of why this
    ** is necessary.
    */
    rc = pagerUnlockDb(pPager, NO_LOCK);
    if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
      pPager->eLock = UNKNOWN_LOCK;
    }

    /* The pager state may be changed from PAGER_ERROR to PAGER_NONE here
    ** without clearing the error code. This is intentional - the error
................................................................................
** other writers or checkpointers.
*/
static int pagerBeginReadTransaction(Pager *pPager){
  int rc;                         /* Return code */
  int changed = 0;                /* True if cache must be reset */

  assert( pagerUseWal(pPager) );
  assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );

  /* sqlite3WalEndReadTransaction() was not called for the previous
  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  ** are in locking_mode=NORMAL and EndRead() was previously called,
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pPager->pWal);
................................................................................
** This function may only be called when a read-transaction is open on
** the pager. It returns the total number of pages in the database.
**
** However, if the file is between 1 and <page-size> bytes in size, then 
** this is considered a 1 page file.
*/
int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
  assert( pPager->eState>=PAGER_READER );
  assert( pPager->eState!=PAGER_WRITER_FINISHED );
  *pnPage = (int)pPager->dbSize;
  return SQLITE_OK;
}


/*
................................................................................
** Return SQLITE_OK on success and an error code if we cannot obtain
** the lock. If the lock is obtained successfully, set the Pager.state 
** variable to locktype before returning.
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
  int rc;                              /* Return code */






  /* Check that this is either a no-op (because the requested lock is 
  ** already held, or one of the transistions that the busy-handler
  ** may be invoked during, according to the comment above
  ** sqlite3PagerSetBusyhandler().
  */
  assert( (pPager->eLock>=locktype)
       || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
................................................................................

    assert( !MEMDB );
    assert( pPager->noReadlock==0 || pPager->readOnly );

    if( pPager->noReadlock==0 ){
      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
      if( rc!=SQLITE_OK ){
        assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
        goto failed;
      }
    }

    /* If a journal file exists, and there is no RESERVED lock on the
    ** database file, then it either needs to be played back or deleted.
    */
................................................................................
  int rc = SQLITE_OK;
  assert( pPager->eState==PAGER_WRITER_CACHEMOD 
       || pPager->eState==PAGER_WRITER_DBMOD 
       || pPager->eState==PAGER_WRITER_INITIAL 
  );
  assert( assert_pager_state(pPager) );
  if( 0==pagerUseWal(pPager) ){
    rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
  }
  return rc;
}

/*
** Sync the database file for the pager pPager. zMaster points to the name
** of a master journal file that should be written into the individual