/ Check-in [ee7b4b60]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Cleanup of the PAGERTRACE macro. Other comment changes in pager.c. (CVS 6122)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ee7b4b60880e80e6fb0b2f93ebc6ee5ad6917f9d
User & Date: drh 2009-01-06 15:58:57
Context
2009-01-06
17:52
Modify test_journal.c to verify the page data being written to the journal file. (CVS 6123) check-in: 0d258956 user: danielk1977 tags: trunk
15:58
Cleanup of the PAGERTRACE macro. Other comment changes in pager.c. (CVS 6122) check-in: ee7b4b60 user: drh tags: trunk
15:28
The fix in (6120) wasn't quite right. This fixes it. (CVS 6121) check-in: ddc2ebfa user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
....
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
....
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
....
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
....
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
....
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
....
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
....
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
....
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
....
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
....
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
....
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
....
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
....
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
....
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
....
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
....
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
....
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.533 2009/01/06 15:28:35 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
#if 0
int sqlite3PagerTrace=1;  /* True to enable tracing */
#define sqlite3DebugPrintf printf
#define PAGERTRACE1(X)       if( sqlite3PagerTrace ) sqlite3DebugPrintf(X)
#define PAGERTRACE2(X,Y)     if( sqlite3PagerTrace ) sqlite3DebugPrintf(X,Y)
#define PAGERTRACE3(X,Y,Z)   if( sqlite3PagerTrace ) sqlite3DebugPrintf(X,Y,Z)
#define PAGERTRACE4(X,Y,Z,W) if( sqlite3PagerTrace ) sqlite3DebugPrintf(X,Y,Z,W)
#define PAGERTRACE5(X,Y,Z,W,V) if( sqlite3PagerTrace ) sqlite3DebugPrintf(X,Y,Z,W,V)
#else
#define PAGERTRACE1(X)
#define PAGERTRACE2(X,Y)
#define PAGERTRACE3(X,Y,Z)
#define PAGERTRACE4(X,Y,Z,W)
#define PAGERTRACE5(X,Y,Z,W,V)
#endif

/*
** The following two macros are used within the PAGERTRACEX() macros above
** to print out file-descriptors. 
**
** PAGERID() takes a pointer to a Pager struct as its argument. The
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** struct as its argument.
*/
#define PAGERID(p) ((int)(p->fd))
................................................................................
*/
#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

/*
** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time,
** then failed attempts to get a reserved lock will invoke the busy callback.
** This is off by default.  To see why, consider the following scenario:
** 
** Suppose thread A already has a shared lock and wants a reserved lock.
** Thread B already has a reserved lock and wants an exclusive lock.  If
** both threads are using their busy callbacks, it might be a long time
** be for one of the threads give up and allows the other to proceed.
** But if the thread trying to get the reserved lock gives up quickly
** (if it never invokes its busy callback) then the contention will be
** resolved quickly.
*/
#ifndef SQLITE_BUSY_RESERVED_LOCK
# define SQLITE_BUSY_RESERVED_LOCK 0
#endif

/*
** This macro rounds values up so that if the value is an address it
** is guaranteed to be an address that is aligned to an 8-byte boundary.
*/
#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)

/*
................................................................................


/*
** Journal files begin with the following magic string.  The data
** was obtained from /dev/random.  It is used only as a sanity check.
**
** Since version 2.8.0, the journal format contains additional sanity
** checking information.  If the power fails while the journal is begin
** written, semi-random garbage data might appear in the journal
** file after power is restored.  If an attempt is then made
** to roll the journal back, the database could be corrupted.  The additional
** sanity checking data is an attempt to discover the garbage in the
** journal and ignore it.
**
** The sanity checking information for the new journal format consists
................................................................................
  ** the page is marked as needSync==0.
  **
  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
  ** is possible to fail a statement on a database that does not yet exist.
  ** Do not attempt to write if database file has never been opened.
  */
  pPg = pager_lookup(pPager, pgno);
  PAGERTRACE5("PLAYBACK %d page %d hash(%08x) %s\n",
               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData),
               (isMainJrnl?"main-journal":"sub-journal")
  );
  if( (pPager->state>=PAGER_EXCLUSIVE)
   && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
   && (pPager->fd->pMethods)
  ){
    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
    rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
    if( pgno>pPager->dbFileSize ){
................................................................................
    sqlite3_free(pPager);
    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
  }
  nExtra = FORCE_ALIGNMENT(nExtra);
  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);

  PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
  for(i=sqlite3Strlen30(pPager->zDirectory); 
      i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;
................................................................................
    ** this is happening, the database may become corrupt.
    */
    pPager->journalHdr = -1;
    pagerUnlockAndRollback(pPager);
  }
  enable_simulated_io_errors();
  sqlite3EndBenignMalloc();
  PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
  IOTRACE(("CLOSE %p\n", pPager))
  if( pPager->journalOpen ){
    sqlite3OsClose(pPager->jfd);
  }
  sqlite3BitvecDestroy(pPager->pInJournal);
  sqlite3BitvecDestroy(pPager->pAlwaysRollback);
  releaseAllSavepoint(pPager);
................................................................................
        ** SAFE_APPEND property. Because in this case it is not possible 
        ** for garbage data to be appended to the file, the nRec field
        ** is populated with 0xFFFFFFFF when the journal header is written
        ** and never needs to be updated.
        */
        i64 jrnlOff;
        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
          PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
          IOTRACE(("JSYNC %p\n", pPager))
          rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags);
          if( rc!=0 ) return rc;
        }

        jrnlOff = pPager->journalHdr + sizeof(aJournalMagic);
        IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4));
        rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
        if( rc ) return rc;
      }
      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
        PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
        IOTRACE(("JSYNC %p\n", pPager))
        rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| 
          (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
        );
        if( rc!=0 ) return rc;
      }
      pPager->journalStarted = 1;
................................................................................
    ** make the file smaller (presumably by auto-vacuum code). Do not write
    ** any such pages to the file.
    */
    if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
      i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
      char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);

      PAGERTRACE4("STORE %d page %d hash(%08x)\n",
                   PAGERID(pPager), pList->pgno, pager_pagehash(pList));
      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
      PAGER_INCR(sqlite3_pager_writedb_count);
      PAGER_INCR(pPager->nWrite);
      if( pList->pgno==1 ){
        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
      }
      if( pList->pgno>pPager->dbFileSize ){
        pPager->dbFileSize = pList->pgno;
      }
    }
#ifndef NDEBUG
    else{
      PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
    }
#endif
    if( rc ) return rc;
#ifdef SQLITE_CHECK_PAGES
    pList->pageHash = pager_pagehash(pList);
#endif
    pList = pList->pDirty;
................................................................................
static int subjournalPage(PgHdr *pPg){
  int rc;
  void *pData = pPg->pData;
  Pager *pPager = pPg->pPager;
  i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
  char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);

  PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);

  assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
  rc = write32bits(pPager->sjfd, offset, pPg->pgno);
  if( rc==SQLITE_OK ){
    rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
  }
  if( rc==SQLITE_OK ){
................................................................................
    }
    if( rc!=SQLITE_OK ){
      pager_error(pPager, rc);
    }
  }

  if( rc==SQLITE_OK ){
    PAGERTRACE3("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno);
    sqlite3PcacheMakeClean(pPg);
  }
  return rc;
}


/*
................................................................................
  PAGER_INCR(pPager->nRead);
  IOTRACE(("PGIN %p %d\n", pPager, pgno));
  if( pgno==1 ){
    memcpy(&pPager->dbFileVers, &((u8*)pPg->pData)[24],
                                              sizeof(pPager->dbFileVers));
  }
  CODEC1(pPager, pPg->pData, pPg->pgno, 3);
  PAGERTRACE4("FETCH %d page %d hash(%08x)\n",
               PAGERID(pPager), pPg->pgno, pager_pagehash(pPg));
  return rc;
}


/*
** This function is called to obtain the shared lock required before
** data may be read from the pager cache. If the shared lock has already
................................................................................
        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
      }
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
    pPager->dirtyCache = 0;
    PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
    if( pPager->useJournal && !pPager->tempFile
           && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
      rc = pager_open_journal(pPager);
    }
  }else if( pPager->journalOpen && pPager->journalOff==0 ){
    /* This happens when the pager was in exclusive-access mode the last
    ** time a (read or write) transaction was successfully concluded
................................................................................
        if( rc==SQLITE_OK ){
          rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
          pPager->journalOff += 4;
        }
        IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
                 pPager->journalOff, pPager->pageSize));
        PAGER_INCR(sqlite3_pager_writej_count);
        PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
             PAGERID(pPager), pPg->pgno, 
             ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg));

        /* Even if an IO or diskfull error occurred while journalling the
        ** page in the block above, set the need-sync flag for the page.
        ** Otherwise, when the transaction is rolled back, the logic in
        ** playback_one_page() will think that the page needs to be restored
        ** in the database file. And if an IO error occurs while doing so,
        ** then corruption may follow.
................................................................................
          return rc;
        }
      }else{
        if( !pPager->journalStarted && !pPager->noSync ){
          pPg->flags |= PGHDR_NEED_SYNC;
          pPager->needSync = 1;
        }
        PAGERTRACE4("APPEND %d page %d needSync=%d\n",
                PAGERID(pPager), pPg->pgno,
               ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
      }
    }
  
    /* If the statement journal is open and the page is not in it,
    ** then write the current page to the statement journal.  Note that
    ** the statement journal format differs from the standard journal format
    ** in that it omits the checksums and the header.
................................................................................
      ** When the database file grows, we must make sure that the last page
      ** gets written at least once so that the disk file will be the correct
      ** size. If you do not write this page and the size of the file
      ** on the disk ends up being too small, that can lead to database
      ** corruption during the next transaction.
      */
    }else{
      PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager));
      IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
      pPg->flags |= PGHDR_DONT_WRITE;
#ifdef SQLITE_CHECK_PAGES
      pPg->pageHash = pager_pagehash(pPg);
#endif
    }
  }
................................................................................
  TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  TESTONLY( rc = ) addToSavepointBitvecs(pPager, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  sqlite3EndBenignMalloc();


  PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
}


/*
** This routine is called to increment the database file change-counter,
** stored at byte 24 of the pager file.
................................................................................
  if( pPager->dbModified==0 &&
        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
          pPager->exclusiveMode!=0) ){
    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
    return SQLITE_OK;
  }

  PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize);

  /* If this is an in-memory db, or no pages have been written to, or this
  ** function has already been called, it is a no-op.
  */
  if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
    PgHdr *pPg;

................................................................................
          ** being discarded by the truncation must be written to the journal
          ** file.
          */
          Pgno i;
          Pgno iSkip = PAGER_MJ_PGNO(pPager);
          Pgno dbSize = pPager->dbSize;
          pPager->dbSize = pPager->dbOrigSize;
          for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
            if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
              rc = sqlite3PagerGet(pPager, i, &pPg);
              if( rc!=SQLITE_OK ) goto sync_exit;
              rc = sqlite3PagerWrite(pPg);
              sqlite3PagerUnref(pPg);
              if( rc!=SQLITE_OK ) goto sync_exit;
            }
................................................................................
  }
  if( pPager->dbModified==0 &&
        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
          pPager->exclusiveMode!=0) ){
    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
    return SQLITE_OK;
  }
  PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
  assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
  rc = pager_end_transaction(pPager, pPager->setMaster);
  rc = pager_error(pPager, rc);
  return rc;
}

/*
................................................................................
** process is writing trash into the journal file (SQLITE_CORRUPT) or
** unless a prior malloc() failed (SQLITE_NOMEM).  Appropriate error
** codes are returned for all these occasions.  Otherwise,
** SQLITE_OK is returned.
*/
int sqlite3PagerRollback(Pager *pPager){
  int rc = SQLITE_OK;
  PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
  if( !pPager->dirtyCache || !pPager->journalOpen ){
    rc = pager_end_transaction(pPager, pPager->setMaster);
  }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
    if( pPager->state>=PAGER_EXCLUSIVE ){
      pager_playback(pPager, 0);
    }
    rc = pPager->errCode;
................................................................................
*/
int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
  PgHdr *pPgOld;  /* The page being overwritten. */
  Pgno needSyncPgno = 0;

  assert( pPg->nRef>0 );

  PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", 
      PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno);
  IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))

  pager_get_content(pPg);

  /* If the journal needs to be sync()ed before page pPg->pgno can
  ** be written to, store pPg->pgno in local variable needSyncPgno.
  **







|










<
|
<
<
<

|
<
<
<
<



|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|


|







 







|







 







|







 







|











|







 







|
|













|







 







|







 







|







 







|
|







 







|







 







|

|







 







|

|







 







|







 







|







 







|
|







 







|







 







|







 







|







 







|
|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32



33
34




35
36
37
38
39
40
41
42
43
44
45
..
95
96
97
98
99
100
101

















102
103
104
105
106
107
108
...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
....
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
....
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
....
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
....
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
....
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
....
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
....
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
....
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
....
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
....
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
....
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
....
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
....
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
....
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
....
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
....
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
....
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
....
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.534 2009/01/06 15:58:57 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
#if 0
int sqlite3PagerTrace=1;  /* True to enable tracing */
#define sqlite3DebugPrintf printf

#define PAGERTRACE(X)     if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }



#else
#define PAGERTRACE(X)




#endif

/*
** The following two macros are used within the PAGERTRACE() macros above
** to print out file-descriptors. 
**
** PAGERID() takes a pointer to a Pager struct as its argument. The
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** struct as its argument.
*/
#define PAGERID(p) ((int)(p->fd))
................................................................................
*/
#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


















/*
** This macro rounds values up so that if the value is an address it
** is guaranteed to be an address that is aligned to an 8-byte boundary.
*/
#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)

/*
................................................................................


/*
** Journal files begin with the following magic string.  The data
** was obtained from /dev/random.  It is used only as a sanity check.
**
** Since version 2.8.0, the journal format contains additional sanity
** checking information.  If the power fails while the journal is being
** written, semi-random garbage data might appear in the journal
** file after power is restored.  If an attempt is then made
** to roll the journal back, the database could be corrupted.  The additional
** sanity checking data is an attempt to discover the garbage in the
** journal and ignore it.
**
** The sanity checking information for the new journal format consists
................................................................................
  ** the page is marked as needSync==0.
  **
  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
  ** is possible to fail a statement on a database that does not yet exist.
  ** Do not attempt to write if database file has never been opened.
  */
  pPg = pager_lookup(pPager, pgno);
  PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData),
               (isMainJrnl?"main-journal":"sub-journal")
  ));
  if( (pPager->state>=PAGER_EXCLUSIVE)
   && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
   && (pPager->fd->pMethods)
  ){
    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
    rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
    if( pgno>pPager->dbFileSize ){
................................................................................
    sqlite3_free(pPager);
    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
  }
  nExtra = FORCE_ALIGNMENT(nExtra);
  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);

  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
  for(i=sqlite3Strlen30(pPager->zDirectory); 
      i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;
................................................................................
    ** this is happening, the database may become corrupt.
    */
    pPager->journalHdr = -1;
    pagerUnlockAndRollback(pPager);
  }
  enable_simulated_io_errors();
  sqlite3EndBenignMalloc();
  PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
  IOTRACE(("CLOSE %p\n", pPager))
  if( pPager->journalOpen ){
    sqlite3OsClose(pPager->jfd);
  }
  sqlite3BitvecDestroy(pPager->pInJournal);
  sqlite3BitvecDestroy(pPager->pAlwaysRollback);
  releaseAllSavepoint(pPager);
................................................................................
        ** SAFE_APPEND property. Because in this case it is not possible 
        ** for garbage data to be appended to the file, the nRec field
        ** is populated with 0xFFFFFFFF when the journal header is written
        ** and never needs to be updated.
        */
        i64 jrnlOff;
        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
          PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
          IOTRACE(("JSYNC %p\n", pPager))
          rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags);
          if( rc!=0 ) return rc;
        }

        jrnlOff = pPager->journalHdr + sizeof(aJournalMagic);
        IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4));
        rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
        if( rc ) return rc;
      }
      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
        PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
        IOTRACE(("JSYNC %p\n", pPager))
        rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| 
          (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
        );
        if( rc!=0 ) return rc;
      }
      pPager->journalStarted = 1;
................................................................................
    ** make the file smaller (presumably by auto-vacuum code). Do not write
    ** any such pages to the file.
    */
    if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
      i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
      char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);

      PAGERTRACE(("STORE %d page %d hash(%08x)\n",
                   PAGERID(pPager), pList->pgno, pager_pagehash(pList)));
      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
      PAGER_INCR(sqlite3_pager_writedb_count);
      PAGER_INCR(pPager->nWrite);
      if( pList->pgno==1 ){
        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
      }
      if( pList->pgno>pPager->dbFileSize ){
        pPager->dbFileSize = pList->pgno;
      }
    }
#ifndef NDEBUG
    else{
      PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno));
    }
#endif
    if( rc ) return rc;
#ifdef SQLITE_CHECK_PAGES
    pList->pageHash = pager_pagehash(pList);
#endif
    pList = pList->pDirty;
................................................................................
static int subjournalPage(PgHdr *pPg){
  int rc;
  void *pData = pPg->pData;
  Pager *pPager = pPg->pPager;
  i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
  char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);

  PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));

  assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
  rc = write32bits(pPager->sjfd, offset, pPg->pgno);
  if( rc==SQLITE_OK ){
    rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
  }
  if( rc==SQLITE_OK ){
................................................................................
    }
    if( rc!=SQLITE_OK ){
      pager_error(pPager, rc);
    }
  }

  if( rc==SQLITE_OK ){
    PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
    sqlite3PcacheMakeClean(pPg);
  }
  return rc;
}


/*
................................................................................
  PAGER_INCR(pPager->nRead);
  IOTRACE(("PGIN %p %d\n", pPager, pgno));
  if( pgno==1 ){
    memcpy(&pPager->dbFileVers, &((u8*)pPg->pData)[24],
                                              sizeof(pPager->dbFileVers));
  }
  CODEC1(pPager, pPg->pData, pPg->pgno, 3);
  PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
               PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));
  return rc;
}


/*
** This function is called to obtain the shared lock required before
** data may be read from the pager cache. If the shared lock has already
................................................................................
        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
      }
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
    pPager->dirtyCache = 0;
    PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
    if( pPager->useJournal && !pPager->tempFile
           && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
      rc = pager_open_journal(pPager);
    }
  }else if( pPager->journalOpen && pPager->journalOff==0 ){
    /* This happens when the pager was in exclusive-access mode the last
    ** time a (read or write) transaction was successfully concluded
................................................................................
        if( rc==SQLITE_OK ){
          rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
          pPager->journalOff += 4;
        }
        IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
                 pPager->journalOff, pPager->pageSize));
        PAGER_INCR(sqlite3_pager_writej_count);
        PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
             PAGERID(pPager), pPg->pgno, 
             ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));

        /* Even if an IO or diskfull error occurred while journalling the
        ** page in the block above, set the need-sync flag for the page.
        ** Otherwise, when the transaction is rolled back, the logic in
        ** playback_one_page() will think that the page needs to be restored
        ** in the database file. And if an IO error occurs while doing so,
        ** then corruption may follow.
................................................................................
          return rc;
        }
      }else{
        if( !pPager->journalStarted && !pPager->noSync ){
          pPg->flags |= PGHDR_NEED_SYNC;
          pPager->needSync = 1;
        }
        PAGERTRACE(("APPEND %d page %d needSync=%d\n",
                PAGERID(pPager), pPg->pgno,
               ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
      }
    }
  
    /* If the statement journal is open and the page is not in it,
    ** then write the current page to the statement journal.  Note that
    ** the statement journal format differs from the standard journal format
    ** in that it omits the checksums and the header.
................................................................................
      ** When the database file grows, we must make sure that the last page
      ** gets written at least once so that the disk file will be the correct
      ** size. If you do not write this page and the size of the file
      ** on the disk ends up being too small, that can lead to database
      ** corruption during the next transaction.
      */
    }else{
      PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
      IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
      pPg->flags |= PGHDR_DONT_WRITE;
#ifdef SQLITE_CHECK_PAGES
      pPg->pageHash = pager_pagehash(pPg);
#endif
    }
  }
................................................................................
  TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  TESTONLY( rc = ) addToSavepointBitvecs(pPager, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  sqlite3EndBenignMalloc();


  PAGERTRACE(("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)));
  IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
}


/*
** This routine is called to increment the database file change-counter,
** stored at byte 24 of the pager file.
................................................................................
  if( pPager->dbModified==0 &&
        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
          pPager->exclusiveMode!=0) ){
    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
    return SQLITE_OK;
  }

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));

  /* If this is an in-memory db, or no pages have been written to, or this
  ** function has already been called, it is a no-op.
  */
  if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
    PgHdr *pPg;

................................................................................
          ** being discarded by the truncation must be written to the journal
          ** file.
          */
          Pgno i;
          Pgno iSkip = PAGER_MJ_PGNO(pPager);
          Pgno dbSize = pPager->dbSize;
          pPager->dbSize = pPager->dbOrigSize;
          for( i=pPager->dbSize+1; i<=pPager->dbOrigSize; i++ ){
            if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
              rc = sqlite3PagerGet(pPager, i, &pPg);
              if( rc!=SQLITE_OK ) goto sync_exit;
              rc = sqlite3PagerWrite(pPg);
              sqlite3PagerUnref(pPg);
              if( rc!=SQLITE_OK ) goto sync_exit;
            }
................................................................................
  }
  if( pPager->dbModified==0 &&
        (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
          pPager->exclusiveMode!=0) ){
    assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
    return SQLITE_OK;
  }
  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
  assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
  rc = pager_end_transaction(pPager, pPager->setMaster);
  rc = pager_error(pPager, rc);
  return rc;
}

/*
................................................................................
** process is writing trash into the journal file (SQLITE_CORRUPT) or
** unless a prior malloc() failed (SQLITE_NOMEM).  Appropriate error
** codes are returned for all these occasions.  Otherwise,
** SQLITE_OK is returned.
*/
int sqlite3PagerRollback(Pager *pPager){
  int rc = SQLITE_OK;
  PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
  if( !pPager->dirtyCache || !pPager->journalOpen ){
    rc = pager_end_transaction(pPager, pPager->setMaster);
  }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
    if( pPager->state>=PAGER_EXCLUSIVE ){
      pager_playback(pPager, 0);
    }
    rc = pPager->errCode;
................................................................................
*/
int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
  PgHdr *pPgOld;  /* The page being overwritten. */
  Pgno needSyncPgno = 0;

  assert( pPg->nRef>0 );

  PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", 
      PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
  IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))

  pager_get_content(pPg);

  /* If the journal needs to be sync()ed before page pPg->pgno can
  ** be written to, store pPg->pgno in local variable needSyncPgno.
  **