⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pager.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/*** Make every page in the cache agree with what is on disk.  In other words,** reread the disk to reset the state of the cache.**** This routine is called after a rollback in which some of the dirty cache** pages had never been written out to disk.  We need to roll back the** cache content and the easiest way to do that is to reread the old content** back from the disk.*/static int pager_reload_cache(Pager *pPager){  PgHdr *pPg;  int rc = SQLITE_OK;  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){    char zBuf[SQLITE_MAX_PAGE_SIZE];    if( !pPg->dirty ) continue;    if( (int)pPg->pgno <= pPager->origDbSize ){      sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));      rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize);      TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);      if( rc ) break;      CODEC(pPager, zBuf, pPg->pgno, 2);    }else{      memset(zBuf, 0, pPager->pageSize);    }    if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){      memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize);      if( pPager->xReiniter ){        pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize);      }else{        memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);      }    }    pPg->needSync = 0;    pPg->dirty = 0;#ifdef SQLITE_CHECK_PAGES    pPg->pageHash = pager_pagehash(pPg);#endif  }  return rc;}/*** Truncate the main file of the given pager to the number of pages** indicated.*/static int pager_truncate(Pager *pPager, int nPage){  assert( pPager->state>=PAGER_EXCLUSIVE );  return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage);}/*** Playback the journal and thus restore the database file to** the state it was in before we started making changes.  **** The journal file format is as follows: ****  (1)  8 byte prefix.  A copy of aJournalMagic[].**  (2)  4 byte big-endian integer which is the number of valid page records**       in the journal.  If this value is 0xffffffff, then compute the**       number of page records from the journal size.**  (3)  4 byte big-endian integer which is the initial value for the **       sanity checksum.**  (4)  4 byte integer which is the number of pages to truncate the**       database to during a rollback.**  (5)  4 byte integer which is the number of bytes in the master journal**       name.  The value may be zero (indicate that there is no master**       journal.)**  (6)  N bytes of the master journal name.  The name will be nul-terminated**       and might be shorter than the value read from (5).  If the first byte**       of the name is \000 then there is no master journal.  The master**       journal name is stored in UTF-8.**  (7)  Zero or more pages instances, each as follows:**        +  4 byte page number.**        +  pPager->pageSize bytes of data.**        +  4 byte checksum**** When we speak of the journal header, we mean the first 6 items above.** Each entry in the journal is an instance of the 7th item.**** Call the value from the second bullet "nRec".  nRec is the number of** valid page entries in the journal.  In most cases, you can compute the** value of nRec from the size of the journal file.  But if a power** failure occurred while the journal was being written, it could be the** case that the size of the journal file had already been increased but** the extra entries had not yet made it safely to disk.  In such a case,** the value of nRec computed from the file size would be too large.  For** that reason, we always use the nRec value in the header.**** If the nRec value is 0xffffffff it means that nRec should be computed** from the file size.  This value is used when the user selects the** no-sync option for the journal.  A power failure could lead to corruption** in this case.  But for things like temporary table (which will be** deleted when the power is restored) we don't care.  **** If the file opened as the journal file is not a well-formed** journal file then all pages up to the first corrupted page are rolled** back (or no pages if the journal header is corrupted). The journal file** is then deleted and SQLITE_OK returned, just as if no corruption had** been encountered.**** If an I/O or malloc() error occurs, the journal-file is not deleted** and an error code is returned.*/static int pager_playback(Pager *pPager){  i64 szJ;                 /* Size of the journal file in bytes */  u32 nRec;                /* Number of Records in the journal */  int i;                   /* Loop counter */  Pgno mxPg = 0;           /* Size of the original file in pages */  int rc;                  /* Result code of a subroutine */  char *zMaster = 0;       /* Name of master journal file if any */  /* Figure out how many records are in the journal.  Abort early if  ** the journal is empty.  */  assert( pPager->journalOpen );  rc = sqlite3OsFileSize(&pPager->jfd, &szJ);  if( rc!=SQLITE_OK ){    goto end_playback;  }  /* Read the master journal name from the journal, if it is present.  ** If a master journal file name is specified, but the file is not  ** present on disk, then the journal is not hot and does not need to be  ** played back.  */  rc = readMasterJournal(&pPager->jfd, &zMaster);  assert( rc!=SQLITE_DONE );  if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){    sqliteFree(zMaster);    zMaster = 0;    if( rc==SQLITE_DONE ) rc = SQLITE_OK;    goto end_playback;  }  sqlite3OsSeek(&pPager->jfd, 0);  pPager->journalOff = 0;  /* This loop terminates either when the readJournalHdr() call returns  ** SQLITE_DONE or an IO error occurs. */  while( 1 ){    /* Read the next journal header from the journal file.  If there are    ** not enough bytes left in the journal file for a complete header, or    ** it is corrupted, then a process must of failed while writing it.    ** This indicates nothing more needs to be rolled back.    */    rc = readJournalHdr(pPager, szJ, &nRec, &mxPg);    if( rc!=SQLITE_OK ){       if( rc==SQLITE_DONE ){        rc = SQLITE_OK;      }      goto end_playback;    }    /* If nRec is 0xffffffff, then this journal was created by a process    ** working in no-sync mode. This means that the rest of the journal    ** file consists of pages, there are no more journal headers. Compute    ** the value of nRec based on this assumption.    */    if( nRec==0xffffffff ){      assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );      nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager);    }    /* If this is the first header read from the journal, truncate the    ** database file back to it's original size.    */    if( pPager->state>=PAGER_EXCLUSIVE &&         pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){      assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );      rc = pager_truncate(pPager, mxPg);      if( rc!=SQLITE_OK ){        goto end_playback;      }      pPager->dbSize = mxPg;    }    /* rc = sqlite3OsSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */    if( rc!=SQLITE_OK ) goto end_playback;      /* Copy original pages out of the journal and back into the database file.    */    for(i=0; i<nRec; i++){      rc = pager_playback_one_page(pPager, &pPager->jfd, 1);      if( rc!=SQLITE_OK ){        if( rc==SQLITE_DONE ){          rc = SQLITE_OK;          pPager->journalOff = szJ;          break;        }else{          goto end_playback;        }      }    }  }  /* Pages that have been written to the journal but never synced  ** where not restored by the loop above.  We have to restore those  ** pages by reading them back from the original database.  */  assert( rc==SQLITE_OK );  pager_reload_cache(pPager);end_playback:  if( rc==SQLITE_OK ){    rc = pager_unwritelock(pPager);  }  if( zMaster ){    /* If there was a master journal and this routine will return true,    ** see if it is possible to delete the master journal.    */    if( rc==SQLITE_OK ){      rc = pager_delmaster(zMaster);    }    sqliteFree(zMaster);  }  /* The Pager.sectorSize variable may have been updated while rolling  ** back a journal created by a process with a different PAGER_SECTOR_SIZE  ** value. Reset it to the correct value for this process.  */  pPager->sectorSize = PAGER_SECTOR_SIZE;  return rc;}/*** Playback the statement journal.**** This is similar to playing back the transaction journal but with** a few extra twists.****    (1)  The number of pages in the database file at the start of**         the statement is stored in pPager->stmtSize, not in the**         journal file itself.****    (2)  In addition to playing back the statement journal, also**         playback all pages of the transaction journal beginning**         at offset pPager->stmtJSize.*/static int pager_stmt_playback(Pager *pPager){  i64 szJ;                 /* Size of the full journal */  i64 hdrOff;  int nRec;                /* Number of Records */  int i;                   /* Loop counter */  int rc;  szJ = pPager->journalOff;#ifndef NDEBUG   {    i64 os_szJ;    rc = sqlite3OsFileSize(&pPager->jfd, &os_szJ);    if( rc!=SQLITE_OK ) return rc;    assert( szJ==os_szJ );  }#endif  /* Set hdrOff to be the offset to the first journal header written  ** this statement transaction, or the end of the file if no journal  ** header was written.  */  hdrOff = pPager->stmtHdrOff;  assert( pPager->fullSync || !hdrOff );  if( !hdrOff ){    hdrOff = szJ;  }    /* Truncate the database back to its original size.  */  if( pPager->state>=PAGER_EXCLUSIVE ){    rc = pager_truncate(pPager, pPager->stmtSize);  }  pPager->dbSize = pPager->stmtSize;  /* Figure out how many records are in the statement journal.  */  assert( pPager->stmtInUse && pPager->journalOpen );  sqlite3OsSeek(&pPager->stfd, 0);  nRec = pPager->stmtNRec;    /* Copy original pages out of the statement journal and back into the  ** database file.  Note that the statement journal omits checksums from  ** each record since power-failure recovery is not important to statement  ** journals.  */  for(i=nRec-1; i>=0; i--){    rc = pager_playback_one_page(pPager, &pPager->stfd, 0);    assert( rc!=SQLITE_DONE );    if( rc!=SQLITE_OK ) goto end_stmt_playback;  }  /* Now roll some pages back from the transaction journal. Pager.stmtJSize  ** was the size of the journal file when this statement was started, so  ** everything after that needs to be rolled back, either into the  ** database, the memory cache, or both.  **  ** If it is not zero, then Pager.stmtHdrOff is the offset to the start  ** of the first journal header written during this statement transaction.  */  rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize);  if( rc!=SQLITE_OK ){    goto end_stmt_playback;  }  pPager->journalOff = pPager->stmtJSize;  pPager->cksumInit = pPager->stmtCksum;  assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) );  while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){    rc = pager_playback_one_page(pPager, &pPager->jfd, 1);    assert( rc!=SQLITE_DONE );    if( rc!=SQLITE_OK ) goto end_stmt_playback;  }  while( pPager->journalOff < szJ ){    u32 nRec;    u32 dummy;    rc = readJournalHdr(pPager, szJ, &nRec, &dummy);    if( rc!=SQLITE_OK ){      assert( rc!=SQLITE_DONE );      goto end_stmt_playback;    }    if( nRec==0 ){      nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);    }    for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){      rc = pager_playback_one_page(pPager, &pPager->jfd, 1);      assert( rc!=SQLITE_DONE );      if( rc!=SQLITE_OK ) goto end_stmt_playback;    }  }  pPager->journalOff = szJ;  end_stmt_playback:  if( rc!=SQLITE_OK ){    pPager->errMask |= PAGER_ERR_CORRUPT;    rc = SQLITE_CORRUPT;  /* bkpt-CORRUPT */  }else{    pPager->journalOff = szJ;    /* pager_reload_cache(pPager); */  }  return rc;}/*** Change the maximum number of in-memory pages that are allowed.*/void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){  if( mxPage>10 ){    pPager->mxPage = mxPage;  }else{    pPager->mxPage = 10;  }}/*** Adjust the robustness of the database to damage due to OS crashes** or power failures by changing the number of syncs()s when writing** the rollback journal.  There are three levels:****    OFF       sqlite3OsSync() is never called.  This is the default**              for temporary and transient files.****    NORMAL    The journal is synced once before writes begin on the**              database.  This is normally adequate protection, but**              it is theoretically possible, though very unlikely,**              that an inopertune power failure could leave the journal**              in a state which would cause damage to the database**              when it is rolled back.****    FULL      The journal is synced twice before writes begin on the**              database (with some additional information - the nRec field**              of the journal header - being written in between the two**              syncs).  If we assume that writing a**              single disk sector is atomic, then this mode provides**              assurance that the journal will not be corrupted to the**              point of causing damage to the database during rollback.**** Numeric values associated with these states are OFF==1, NORMAL=2,** and FULL=3.*/#ifndef SQLITE_OMIT_PAGER_PRAGMASvoid sqlite3pager_set_safety_level(Pager *pPager, int level){  pPager->noSync =  level==1 || pPager->tempFile;  pPager->fullSync = level==3 && !pPager->tempFile;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -