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

📄 pager.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* isMainJrnl should be true for the main journal and false for  ** statement journals.  Verify that this is always the case  */  assert( jfd == (isMainJrnl ? pPager->jfd : pPager->stfd) );  assert( aData );  rc = read32bits(jfd, offset, &pgno);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4);  if( rc!=SQLITE_OK ) return rc;  pPager->journalOff += pPager->pageSize + 4;  /* Sanity checking on the page.  This is more important that I originally  ** thought.  If a power failure occurs while the journal is being written,  ** it could cause invalid data to be written into the journal.  We need to  ** detect this invalid data (with high probability) and ignore it.  */  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){    return SQLITE_DONE;  }  if( pgno>(unsigned)pPager->dbSize ){    return SQLITE_OK;  }  if( isMainJrnl ){    rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);    if( rc ) return rc;    pPager->journalOff += 4;    if( pager_cksum(pPager, aData)!=cksum ){      return SQLITE_DONE;    }  }  assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );  /* If the pager is in RESERVED state, then there must be a copy of this  ** page in the pager cache. In this case just update the pager cache,  ** not the database file. The page is left marked dirty in this case.  **  ** An exception to the above rule: If the database is in no-sync mode  ** and a page is moved during an incremental vacuum then the page may  ** not be in the pager cache. Later: if a malloc() or IO error occurs  ** during a Movepage() call, then the page may not be in the cache  ** either. So the condition described in the above paragraph is not  ** assert()able.  **  ** If in EXCLUSIVE state, then we update the pager cache if it exists  ** and the main file. The page is then marked not dirty.  **  ** Ticket #1171:  The statement journal might contain page content that is  ** different from the page content at the start of the transaction.  ** This occurs when a page is changed prior to the start of a statement  ** then changed again within the statement.  When rolling back such a  ** statement we must not write to the original database unless we know  ** for certain that original page contents are synced into the main rollback  ** journal.  Otherwise, a power loss might leave modified data in the  ** database file without an entry in the rollback journal that can  ** restore the database to its original form.  Two conditions must be  ** met before writing to the database files. (1) the database must be  ** locked.  (2) we know that the original page content is fully synced  ** in the main journal either because the page is not in cache or else  ** 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);  PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));  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( pPg ){    /* No page should ever be explicitly rolled back that is in use, except    ** for page 1 which is held in use in order to keep the lock on the    ** database active. However such a page may be rolled back as a result    ** of an internal error resulting in an automatic call to    ** sqlite3PagerRollback().    */    void *pData;    pData = pPg->pData;    memcpy(pData, aData, pPager->pageSize);    if( pPager->xReiniter ){      pPager->xReiniter(pPg, pPager->pageSize);    }    if( isMainJrnl ) makeClean(pPg);#ifdef SQLITE_CHECK_PAGES    pPg->pageHash = pager_pagehash(pPg);#endif    /* If this was page 1, then restore the value of Pager.dbFileVers.    ** Do this before any decoding. */    if( pgno==1 ){      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));    }    /* Decode the page just read from disk */    CODEC1(pPager, pData, pPg->pgno, 3);    sqlite3PcacheRelease(pPg);  }  return rc;}/*** Parameter zMaster is the name of a master journal file. A single journal** file that referred to the master journal file has just been rolled back.** This routine checks if it is possible to delete the master journal file,** and does so if it is.**** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not ** available for use within this function.****** The master journal file contains the names of all child journals.** To tell if a master journal can be deleted, check to each of the** children.  If all children are either missing or do not refer to** a different master journal, then this master journal can be deleted.*/static int pager_delmaster(Pager *pPager, const char *zMaster){  sqlite3_vfs *pVfs = pPager->pVfs;  int rc;  int master_open = 0;  sqlite3_file *pMaster;  sqlite3_file *pJournal;  char *zMasterJournal = 0; /* Contents of master journal file */  i64 nMasterJournal;       /* Size of master journal file */  /* Open the master journal file exclusively in case some other process  ** is running this routine also. Not that it makes too much difference.  */  pMaster = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile * 2);  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);  if( !pMaster ){    rc = SQLITE_NOMEM;  }else{    int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);  }  if( rc!=SQLITE_OK ) goto delmaster_out;  master_open = 1;  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);  if( rc!=SQLITE_OK ) goto delmaster_out;  if( nMasterJournal>0 ){    char *zJournal;    char *zMasterPtr = 0;    int nMasterPtr = pPager->pVfs->mxPathname+1;    /* Load the entire master journal file into space obtained from    ** sqlite3_malloc() and pointed to by zMasterJournal.     */    zMasterJournal = (char *)sqlite3Malloc(nMasterJournal + nMasterPtr);    if( !zMasterJournal ){      rc = SQLITE_NOMEM;      goto delmaster_out;    }    zMasterPtr = &zMasterJournal[nMasterJournal];    rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);    if( rc!=SQLITE_OK ) goto delmaster_out;    zJournal = zMasterJournal;    while( (zJournal-zMasterJournal)<nMasterJournal ){      int exists;      rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);      if( rc!=SQLITE_OK ){        goto delmaster_out;      }      if( exists ){        /* One of the journals pointed to by the master journal exists.        ** Open it and check if it points at the master journal. If        ** so, return without deleting the master journal file.        */        int c;        int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);        rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);        if( rc!=SQLITE_OK ){          goto delmaster_out;        }        rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);        sqlite3OsClose(pJournal);        if( rc!=SQLITE_OK ){          goto delmaster_out;        }        c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;        if( c ){          /* We have a match. Do not delete the master journal file. */          goto delmaster_out;        }      }      zJournal += (strlen(zJournal)+1);    }  }    rc = sqlite3OsDelete(pVfs, zMaster, 0);delmaster_out:  if( zMasterJournal ){    sqlite3_free(zMasterJournal);  }    if( master_open ){    sqlite3OsClose(pMaster);  }  sqlite3_free(pMaster);  return rc;}static void pager_truncate_cache(Pager *pPager);/*** Truncate the main file of the given pager to the number of pages** indicated. Also truncate the cached representation of the file.**** Might might be the case that the file on disk is smaller than nPage.** This can happen, for example, if we are in the middle of a transaction** which has extended the file size and the new pages are still all held** in cache, then an INSERT or UPDATE does a statement rollback.  Some** operating system implementations can get confused if you try to** truncate a file to some size that is larger than it currently is,** so detect this case and write a single zero byte to the end of the new** file instead.*/static int pager_truncate(Pager *pPager, int nPage){  int rc = SQLITE_OK;  if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){    i64 currentSize, newSize;    rc = sqlite3OsFileSize(pPager->fd, &currentSize);    newSize = pPager->pageSize*(i64)nPage;    if( rc==SQLITE_OK && currentSize!=newSize ){      if( currentSize>newSize ){        rc = sqlite3OsTruncate(pPager->fd, newSize);      }else{        rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);      }    }  }  if( rc==SQLITE_OK ){    pPager->dbSize = nPage;    pager_truncate_cache(pPager);  }  return rc;}/*** Set the sectorSize for the given pager.**** The sector size is at least as big as the sector size reported** by sqlite3OsSectorSize().  The minimum sector size is 512.*/static void setSectorSize(Pager *pPager){  assert(pPager->fd->pMethods||pPager->tempFile);  if( !pPager->tempFile ){    /* Sector size doesn't matter for temporary files. Also, the file    ** may not have been opened yet, in whcih case the OsSectorSize()    ** call will segfault.    */    pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);  }  if( pPager->sectorSize<512 ){    pPager->sectorSize = 512;  }}/*** 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 big-endian integer which is the sector size.  The header**       is this many bytes in size.**  (6)  4 byte big-endian integer which is the page case.**  (7)  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.)**  (8)  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.**  (9)  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 8 items above.** Each entry in the journal is an instance of the 9th 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, int isHot){  sqlite3_vfs *pVfs = pPager->pVfs;  i64 szJ;                 /* Size of the journal file in bytes */  u32 nRec;                /* Number of Records in the journal */  u32 u;                   /* Unsigned loop counter */  Pgno mxPg = 0;           /* Size of the original file in pages */  int rc;                  /* Result code of a subroutine */  int res = 1;             /* Value returned by sqlite3OsAccess() */  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 || szJ==0 ){    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.  */  zMaster = pPager->pTmpSpace;  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);  if( rc==SQLITE_OK && zMaster[0] ){    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);  }  zMaster = 0;  if( rc!=SQLITE_OK || !res ){    goto end_playback;  }

⌨️ 快捷键说明

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