/ Check-in [771c5411]
Login

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

Overview
Comment:Remove the unused PGHDR_NEED_READ flag. Add invariant checking (during SQLITE_DEBUG builds only) for the PgHdr object.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 771c5411e9ebcad00fb4b97556b519488284b87b
User & Date: drh 2016-05-13 15:22:06
Context
2016-05-13
17:22
Improvements to a comment in the pcache.c file. No changes to code. check-in: b369980f user: drh tags: trunk
15:22
Remove the unused PGHDR_NEED_READ flag. Add invariant checking (during SQLITE_DEBUG builds only) for the PgHdr object. check-in: 771c5411 user: drh tags: trunk
12:12
Clarification of the pagerFlushOnCommit() logic. check-in: 3401d9dc user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  2373   2373       assert( isSavepnt );
  2374   2374       assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
  2375   2375       pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
  2376   2376       rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
  2377   2377       assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
  2378   2378       pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
  2379   2379       if( rc!=SQLITE_OK ) return rc;
  2380         -    pPg->flags &= ~PGHDR_NEED_READ;
  2381   2380       sqlite3PcacheMakeDirty(pPg);
  2382   2381     }
  2383   2382     if( pPg ){
  2384   2383       /* No page should ever be explicitly rolled back that is in use, except
  2385   2384       ** for page 1 which is held in use in order to keep the lock on the
  2386   2385       ** database active. However such a page may be rolled back as a result
  2387   2386       ** of an internal error resulting in an automatic call to
................................................................................
  6001   6000   void sqlite3PagerDontWrite(PgHdr *pPg){
  6002   6001     Pager *pPager = pPg->pPager;
  6003   6002     if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
  6004   6003       PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
  6005   6004       IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
  6006   6005       pPg->flags |= PGHDR_DONT_WRITE;
  6007   6006       pPg->flags &= ~PGHDR_WRITEABLE;
         6007  +    testcase( pPg->flags & PGHDR_NEED_SYNC );
  6008   6008       pager_set_pagehash(pPg);
  6009   6009     }
  6010   6010   }
  6011   6011   
  6012   6012   /*
  6013   6013   ** This routine is called to increment the value of the database file 
  6014   6014   ** change-counter, stored as a 4-byte big-endian integer starting at 

Changes to src/pcache.c.

    49     49     u8 bPurgeable;                      /* True if pages are on backing store */
    50     50     u8 eCreate;                         /* eCreate value for for xFetch() */
    51     51     int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
    52     52     void *pStress;                      /* Argument to xStress */
    53     53     sqlite3_pcache *pCache;             /* Pluggable cache module */
    54     54   };
    55     55   
           56  +/********************************** Test and Debug Logic **********************/
    56     57   /*
    57         -** Debug tracing macros
           58  +** Debug tracing macros.  Enable by by changing the "0" to "1" and
           59  +** recompiling.
           60  +**
           61  +** When sqlite3PcacheTrace is 1, single line trace messages are issued.
           62  +** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries
           63  +** is displayed for many operations, resulting in a lot of output.
    58     64   */
    59     65   #if defined(SQLITE_DEBUG) && 0
    60         -  int sqlite3PcacheTrace = 2;
           66  +  int sqlite3PcacheTrace = 2;       /* 0: off  1: simple  2: cache dumps */
           67  +  int sqlite3PcacheMxDump = 9999;   /* Max cache entries for pcacheDump() */
    61     68   # define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
    62     69     void pcacheDump(PCache *pCache){
    63     70       int N;
    64     71       int i, j;
    65     72       sqlite3_pcache_page *pLower;
    66     73       PgHdr *pPg;
    67     74       unsigned char *a;
    68     75     
    69     76       if( sqlite3PcacheTrace<2 ) return;
    70     77       if( pCache->pCache==0 ) return;
    71     78       N = sqlite3PcachePagecount(pCache);
    72         -    if( N>5 ) N = 5;
           79  +    if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
    73     80       for(i=1; i<=N; i++){
    74     81          pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
    75     82          if( pLower==0 ) continue;
    76     83          pPg = (PgHdr*)pLower->pExtra;
    77     84          printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
    78     85          a = (unsigned char *)pLower->pBuf;
    79     86          for(j=0; j<12; j++) printf("%02x", a[j]);
................................................................................
    83     90          }
    84     91       }
    85     92     }
    86     93     #else
    87     94   # define pcacheTrace(X)
    88     95   # define pcacheDump(X)
    89     96   #endif
           97  +
           98  +/*
           99  +** Check invariants on a PgHdr entry.  Return true if everything is OK.
          100  +** Return false if any invariant is violated.
          101  +**
          102  +** This routine is for use inside of assert() statements only.  For
          103  +** example:
          104  +**
          105  +**          assert( sqlite3PcachePageSanity(pPg) );
          106  +*/
          107  +#if SQLITE_DEBUG
          108  +int sqlite3PcachePageSanity(PgHdr *pPg){
          109  +  PCache *pCache;
          110  +  assert( pPg!=0 );
          111  +  assert( pPg->pgno>0 );    /* Page number is 1 or more */
          112  +  pCache = pPg->pCache;
          113  +  assert( pCache!=0 );      /* Every page has an associated PCache */
          114  +  if( pPg->flags & PGHDR_CLEAN ){
          115  +    assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
          116  +    assert( pCache->pDirty!=pPg );          /* CLEAN pages not on dirty list */
          117  +    assert( pCache->pDirtyTail!=pPg );
          118  +  }
          119  +  /* WRITEABLE pages must also be DIRTY */
          120  +  if( pPg->flags & PGHDR_WRITEABLE ){
          121  +    assert( pPg->flags & PGHDR_DIRTY );     /* WRITEABLE implies DIRTY */
          122  +  }
          123  +  /* NEED_SYNC can be set independently of WRITEABLE.  This can happen,
          124  +  ** for example, when using the sqlite3PagerDontWrite() optimization:
          125  +  **    (1)  Page X is journalled, and gets WRITEABLE and NEED_SEEK.
          126  +  **    (2)  Page X moved to freelist, WRITEABLE is cleared
          127  +  **    (3)  Page X reused, WRITEABLE is set again
          128  +  ** If NEED_SYNC had been cleared in step 2, then it would not be reset
          129  +  ** in step 3, and page might be written into the database without first
          130  +  ** syncing the rollback journal, which might cause corruption on a power
          131  +  ** loss.
          132  +  */
          133  +  return 1;
          134  +}
          135  +#endif /* SQLITE_DEBUG */
          136  +
    90    137   
    91    138   /********************************** Linked List Management ********************/
    92    139   
    93    140   /* Allowed values for second argument to pcacheManageDirtyList() */
    94    141   #define PCACHE_DIRTYLIST_REMOVE   1    /* Remove pPage from dirty list */
    95    142   #define PCACHE_DIRTYLIST_ADD      2    /* Add pPage to the dirty list */
    96    143   #define PCACHE_DIRTYLIST_FRONT    3    /* Move pPage to the front of the list */
................................................................................
   435    482     pPgHdr = (PgHdr *)pPage->pExtra;
   436    483   
   437    484     if( !pPgHdr->pPage ){
   438    485       return pcacheFetchFinishWithInit(pCache, pgno, pPage);
   439    486     }
   440    487     pCache->nRefSum++;
   441    488     pPgHdr->nRef++;
          489  +  assert( sqlite3PcachePageSanity(pPgHdr) );
   442    490     return pPgHdr;
   443    491   }
   444    492   
   445    493   /*
   446    494   ** Decrement the reference count on a page. If the page is clean and the
   447    495   ** reference count drops to 0, then it is made eligible for recycling.
   448    496   */
................................................................................
   463    511   }
   464    512   
   465    513   /*
   466    514   ** Increase the reference count of a supplied page by 1.
   467    515   */
   468    516   void sqlite3PcacheRef(PgHdr *p){
   469    517     assert(p->nRef>0);
          518  +  assert( sqlite3PcachePageSanity(p) );
   470    519     p->nRef++;
   471    520     p->pCache->nRefSum++;
   472    521   }
   473    522   
   474    523   /*
   475    524   ** Drop a page from the cache. There must be exactly one reference to the
   476    525   ** page. This function deletes that reference, so after it returns the
   477    526   ** page pointed to by p is invalid.
   478    527   */
   479    528   void sqlite3PcacheDrop(PgHdr *p){
   480    529     assert( p->nRef==1 );
          530  +  assert( sqlite3PcachePageSanity(p) );
   481    531     if( p->flags&PGHDR_DIRTY ){
   482    532       pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
   483    533     }
   484    534     p->pCache->nRefSum--;
   485    535     sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
   486    536   }
   487    537   
   488    538   /*
   489    539   ** Make sure the page is marked as dirty. If it isn't dirty already,
   490    540   ** make it so.
   491    541   */
   492    542   void sqlite3PcacheMakeDirty(PgHdr *p){
   493    543     assert( p->nRef>0 );
          544  +  assert( sqlite3PcachePageSanity(p) );
   494    545     if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){    /*OPTIMIZATION-IF-FALSE*/
   495    546       p->flags &= ~PGHDR_DONT_WRITE;
   496    547       if( p->flags & PGHDR_CLEAN ){
   497    548         p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN);
   498    549         pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
   499    550         assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
   500    551         pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
   501    552       }
          553  +    assert( sqlite3PcachePageSanity(p) );
   502    554     }
   503    555   }
   504    556   
   505    557   /*
   506    558   ** Make sure the page is marked as clean. If it isn't clean already,
   507    559   ** make it so.
   508    560   */
   509    561   void sqlite3PcacheMakeClean(PgHdr *p){
          562  +  assert( sqlite3PcachePageSanity(p) );
   510    563     if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){
   511    564       assert( (p->flags & PGHDR_CLEAN)==0 );
   512    565       pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
   513    566       p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
   514    567       p->flags |= PGHDR_CLEAN;
   515    568       pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
          569  +    assert( sqlite3PcachePageSanity(p) );
   516    570       if( p->nRef==0 ){
   517    571         pcacheUnpin(p);
   518    572       }
   519    573     }
   520    574   }
   521    575   
   522    576   /*
................................................................................
   556    610   /*
   557    611   ** Change the page number of page p to newPgno. 
   558    612   */
   559    613   void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
   560    614     PCache *pCache = p->pCache;
   561    615     assert( p->nRef>0 );
   562    616     assert( newPgno>0 );
          617  +  assert( sqlite3PcachePageSanity(p) );
   563    618     pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
   564    619     sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
   565    620     p->pgno = newPgno;
   566    621     if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
   567    622       pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
   568    623     }
   569    624   }

Changes to src/pcache.h.

    47     47   
    48     48   /* Bit values for PgHdr.flags */
    49     49   #define PGHDR_CLEAN           0x001  /* Page not on the PCache.pDirty list */
    50     50   #define PGHDR_DIRTY           0x002  /* Page is on the PCache.pDirty list */
    51     51   #define PGHDR_WRITEABLE       0x004  /* Journaled and ready to modify */
    52     52   #define PGHDR_NEED_SYNC       0x008  /* Fsync the rollback journal before
    53     53                                        ** writing this page to the database */
    54         -#define PGHDR_NEED_READ       0x010  /* Content is unread */
    55         -#define PGHDR_DONT_WRITE      0x020  /* Do not write content to disk */
    56         -#define PGHDR_MMAP            0x040  /* This is an mmap page object */
           54  +#define PGHDR_DONT_WRITE      0x010  /* Do not write content to disk */
           55  +#define PGHDR_MMAP            0x020  /* This is an mmap page object */
    57     56   
    58         -#define PGHDR_WAL_APPEND      0x080  /* Appended to wal file */
           57  +#define PGHDR_WAL_APPEND      0x040  /* Appended to wal file */
    59     58   
    60     59   /* Initialize and shutdown the page cache subsystem */
    61     60   int sqlite3PcacheInitialize(void);
    62     61   void sqlite3PcacheShutdown(void);
    63     62   
    64     63   /* Page cache buffer management:
    65     64   ** These routines implement SQLITE_CONFIG_PAGECACHE.
................................................................................
   133    132   #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
   134    133   /* Iterate through all dirty pages currently stored in the cache. This
   135    134   ** interface is only available if SQLITE_CHECK_PAGES is defined when the 
   136    135   ** library is built.
   137    136   */
   138    137   void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
   139    138   #endif
          139  +
          140  +#if defined(SQLITE_DEBUG)
          141  +/* Check invariants on a PgHdr object */
          142  +int sqlite3PcachePageSanity(PgHdr*);
          143  +#endif
   140    144   
   141    145   /* Set and get the suggested cache-size for the specified pager-cache.
   142    146   **
   143    147   ** If no global maximum is configured, then the system attempts to limit
   144    148   ** the total number of pages cached by purgeable pager-caches to the sum
   145    149   ** of the suggested cache-sizes.
   146    150   */