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

📄 pager.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/*** This function determines whether or not the atomic-write optimization** can be used with this pager. The optimization can be used if:****  (a) the value returned by OsDeviceCharacteristics() indicates that**      a database page may be written atomically, and**  (b) the value returned by OsSectorSize() is less than or equal**      to the page size.**** If the optimization cannot be used, 0 is returned. If it can be used,** then the value returned is the size of the journal file when it** contains rollback data for exactly one page.*/#ifdef SQLITE_ENABLE_ATOMIC_WRITEstatic int jrnlBufferSize(Pager *pPager){  int dc;           /* Device characteristics */  int nSector;      /* Sector size */  int szPage;        /* Page size */  sqlite3_file *fd = pPager->fd;  if( fd->pMethods ){    dc = sqlite3OsDeviceCharacteristics(fd);    nSector = sqlite3OsSectorSize(fd);    szPage = pPager->pageSize;  }  assert(SQLITE_IOCAP_ATOMIC512==(512>>8));  assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));  if( !fd->pMethods ||        (dc & (SQLITE_IOCAP_ATOMIC|(szPage>>8)) && nSector<=szPage) ){    return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);  }  return 0;}#endif/*** This function should be called when an error occurs within the pager** code. The first argument is a pointer to the pager structure, the** second the error-code about to be returned by a pager API function. ** The value returned is a copy of the second argument to this function. **** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL** the error becomes persistent. Until the persisten error is cleared,** subsequent API calls on this Pager will immediately return the same ** error code.**** A persistent error indicates that the contents of the pager-cache ** cannot be trusted. This state can be cleared by completely discarding ** the contents of the pager-cache. If a transaction was active when** the persistent error occured, then the rollback journal may need** to be replayed.*/static void pager_unlock(Pager *pPager);static int pager_error(Pager *pPager, int rc){  int rc2 = rc & 0xff;  assert(       pPager->errCode==SQLITE_FULL ||       pPager->errCode==SQLITE_OK ||       (pPager->errCode & 0xff)==SQLITE_IOERR  );  if(    rc2==SQLITE_FULL ||    rc2==SQLITE_IOERR ||    rc2==SQLITE_CORRUPT  ){    pPager->errCode = rc;    if( pPager->state==PAGER_UNLOCK      && sqlite3PcacheRefCount(pPager->pPCache)==0     ){      /* If the pager is already unlocked, call pager_unlock() now to      ** clear the error state and ensure that the pager-cache is       ** completely empty.      */      pager_unlock(pPager);    }  }  return rc;}/*** If SQLITE_CHECK_PAGES is defined then we do some sanity checking** on the cache using a hash function.  This is used for testing** and debugging only.*/#ifdef SQLITE_CHECK_PAGES/*** Return a 32-bit hash of the page data for pPage.*/static u32 pager_datahash(int nByte, unsigned char *pData){  u32 hash = 0;  int i;  for(i=0; i<nByte; i++){    hash = (hash*1039) + pData[i];  }  return hash;}static u32 pager_pagehash(PgHdr *pPage){  return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);}static u32 pager_set_pagehash(PgHdr *pPage){  pPage->pageHash = pager_pagehash(pPage);}/*** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES** is defined, and NDEBUG is not defined, an assert() statement checks** that the page is either dirty or still matches the calculated page-hash.*/#define CHECK_PAGE(x) checkPage(x)static void checkPage(PgHdr *pPg){  Pager *pPager = pPg->pPager;  assert( !pPg->pageHash || pPager->errCode || MEMDB       || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );}#else#define pager_datahash(X,Y)  0#define pager_pagehash(X)  0#define CHECK_PAGE(x)#endif  /* SQLITE_CHECK_PAGES *//*** When this is called the journal file for pager pPager must be open.** The master journal file name is read from the end of the file and ** written into memory supplied by the caller. **** zMaster must point to a buffer of at least nMaster bytes allocated by** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is** enough space to write the master journal name). If the master journal** name in the journal is longer than nMaster bytes (including a** nul-terminator), then this is handled as if no master journal name** were present in the journal.**** If no master journal file name is present zMaster[0] is set to 0 and** SQLITE_OK returned.*/static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){  int rc;  u32 len;  i64 szJ;  u32 cksum;  u32 u;                   /* Unsigned loop counter */  unsigned char aMagic[8]; /* A buffer to hold the magic header */  zMaster[0] = '\0';  rc = sqlite3OsFileSize(pJrnl, &szJ);  if( rc!=SQLITE_OK || szJ<16 ) return rc;  rc = read32bits(pJrnl, szJ-16, &len);  if( rc!=SQLITE_OK ) return rc;  if( len>=nMaster ){    return SQLITE_OK;  }  rc = read32bits(pJrnl, szJ-12, &cksum);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8);  if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;  rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len);  if( rc!=SQLITE_OK ){    return rc;  }  zMaster[len] = '\0';  /* See if the checksum matches the master journal name */  for(u=0; u<len; u++){    cksum -= zMaster[u];   }  if( cksum ){    /* If the checksum doesn't add up, then one or more of the disk sectors    ** containing the master journal filename is corrupted. This means    ** definitely roll back, so just return SQLITE_OK and report a (nul)    ** master-journal filename.    */    zMaster[0] = '\0';  }     return SQLITE_OK;}/*** Seek the journal file descriptor to the next sector boundary where a** journal header may be read or written. Pager.journalOff is updated with** the new seek offset.**** i.e for a sector size of 512:**** Input Offset              Output Offset** ---------------------------------------** 0                         0** 512                       512** 100                       512** 2000                      2048** */static void seekJournalHdr(Pager *pPager){  i64 offset = 0;  i64 c = pPager->journalOff;  if( c ){    offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);  }  assert( offset%JOURNAL_HDR_SZ(pPager)==0 );  assert( offset>=c );  assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );  pPager->journalOff = offset;}/*** Write zeros over the header of the journal file.  This has the** effect of invalidating the journal file and committing the** transaction.*/static int zeroJournalHdr(Pager *pPager, int doTruncate){  int rc = SQLITE_OK;  static const char zeroHdr[28];  if( pPager->journalOff ){    i64 iLimit = pPager->journalSizeLimit;    IOTRACE(("JZEROHDR %p\n", pPager))    if( doTruncate || iLimit==0 ){      rc = sqlite3OsTruncate(pPager->jfd, 0);    }else{      rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);    }    if( rc==SQLITE_OK && !pPager->noSync ){      rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags);    }    /* At this point the transaction is committed but the write lock     ** is still held on the file. If there is a size limit configured for     ** the persistent journal and the journal file currently consumes more    ** space than that limit allows for, truncate it now. There is no need    ** to sync the file following this operation.    */    if( rc==SQLITE_OK && iLimit>0 ){      i64 sz;      rc = sqlite3OsFileSize(pPager->jfd, &sz);      if( rc==SQLITE_OK && sz>iLimit ){        rc = sqlite3OsTruncate(pPager->jfd, iLimit);      }    }  }  return rc;}/*** The journal file must be open when this routine is called. A journal** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the** current location.**** The format for the journal header is as follows:** - 8 bytes: Magic identifying journal format.** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.** - 4 bytes: Random number used for page hash.** - 4 bytes: Initial database page count.** - 4 bytes: Sector size used by the process that wrote this journal.** - 4 bytes: Database page size.** ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.*/static int writeJournalHdr(Pager *pPager){  int rc = SQLITE_OK;  char *zHeader = pPager->pTmpSpace;  int nHeader = pPager->pageSize;  int nWrite;  if( nHeader>JOURNAL_HDR_SZ(pPager) ){    nHeader = JOURNAL_HDR_SZ(pPager);  }  if( pPager->stmtHdrOff==0 ){    pPager->stmtHdrOff = pPager->journalOff;  }  seekJournalHdr(pPager);  pPager->journalHdr = pPager->journalOff;  memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));  /*   ** Write the nRec Field - the number of page records that follow this  ** journal header. Normally, zero is written to this value at this time.  ** After the records are added to the journal (and the journal synced,   ** if in full-sync mode), the zero is overwritten with the true number  ** of records (see syncJournal()).  **  ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When  ** reading the journal this value tells SQLite to assume that the  ** rest of the journal file contains valid page records. This assumption  ** is dangerous, as if a failure occured whilst writing to the journal  ** file it may contain some garbage data. There are two scenarios  ** where this risk can be ignored:  **  **   * When the pager is in no-sync mode. Corruption can follow a  **     power failure in this case anyway.  **  **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees  **     that garbage data is never appended to the journal file.  */  assert(pPager->fd->pMethods||pPager->noSync);  if( (pPager->noSync)    || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)   ){    put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);  }else{    put32bits(&zHeader[sizeof(aJournalMagic)], 0);  }  /* The random check-hash initialiser */   sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);  /* The initial database size */  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);  /* The assumed sector size for this process */  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);  if( pPager->journalHdr==0 ){    /* The page size */    put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);  }  for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){    IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))    rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);    pPager->journalOff += nHeader;  }  return rc;}/*** The journal file must be open when this is called. A journal header file** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal** file. See comments above function writeJournalHdr() for a description of** the journal header format.**** If the header is read successfully, *nRec is set to the number of** page records following this header and *dbSize is set to the size of the** database before the transaction began, in pages. Also, pPager->cksumInit** is set to the value read from the journal header. SQLITE_OK is returned** in this case.**** If the journal header file appears to be corrupted, SQLITE_DONE is** returned and *nRec and *dbSize are not set.  If JOURNAL_HDR_SZ bytes** cannot be read from the journal file an error code is returned.*/static int readJournalHdr(  Pager *pPager,   i64 journalSize,  u32 *pNRec, 

⌨️ 快捷键说明

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