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

📄 pager.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define PAGER_MAX_PGNO 2147483647/*** Enable reference count tracking (for debugging) here:*/#ifdef SQLITE_DEBUG  int pager3_refinfo_enable = 0;  static void pager_refinfo(PgHdr *p){    static int cnt = 0;    if( !pager3_refinfo_enable ) return;    sqlite3DebugPrintf(       "REFCNT: %4d addr=%p nRef=%d\n",       p->pgno, PGHDR_TO_DATA(p), p->nRef    );    cnt++;   /* Something to set a breakpoint on */  }# define REFINFO(X)  pager_refinfo(X)#else# define REFINFO(X)#endif/*** Read a 32-bit integer from the given file descriptor.  Store the integer** that is read in *pRes.  Return SQLITE_OK if everything worked, or an** error code is something goes wrong.**** All values are stored on disk as big-endian.*/static int read32bits(OsFile *fd, u32 *pRes){  u32 res;  int rc;  rc = sqlite3OsRead(fd, &res, sizeof(res));  if( rc==SQLITE_OK ){    unsigned char ac[4];    memcpy(ac, &res, 4);    res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];  }  *pRes = res;  return rc;}/*** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK** on success or an error code is something goes wrong.*/static int write32bits(OsFile *fd, u32 val){  unsigned char ac[4];  ac[0] = (val>>24) & 0xff;  ac[1] = (val>>16) & 0xff;  ac[2] = (val>>8) & 0xff;  ac[3] = val & 0xff;  return sqlite3OsWrite(fd, ac, 4);}/*** Write the 32-bit integer 'val' into the page identified by page header** 'p' at offset 'offset'.*/static void store32bits(u32 val, PgHdr *p, int offset){  unsigned char *ac;  ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];  ac[0] = (val>>24) & 0xff;  ac[1] = (val>>16) & 0xff;  ac[2] = (val>>8) & 0xff;  ac[3] = val & 0xff;}/*** Read a 32-bit integer at offset 'offset' from the page identified by** page header 'p'.*/static u32 retrieve32bits(PgHdr *p, int offset){  unsigned char *ac;  ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];  return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];}/*** Convert the bits in the pPager->errMask into an approprate** return code.*/static int pager_errcode(Pager *pPager){  int rc = SQLITE_OK;  if( pPager->errMask & PAGER_ERR_LOCK )    rc = SQLITE_PROTOCOL;  if( pPager->errMask & PAGER_ERR_DISK )    rc = SQLITE_IOERR;  if( pPager->errMask & PAGER_ERR_FULL )    rc = SQLITE_FULL;  if( pPager->errMask & PAGER_ERR_MEM )     rc = SQLITE_NOMEM;  if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;  return rc;}#ifdef SQLITE_CHECK_PAGES/*** Return a 32-bit hash of the page data for pPage.*/static u32 pager_pagehash(PgHdr *pPage){  u32 hash = 0;  int i;  unsigned char *pData = (unsigned char *)PGHDR_TO_DATA(pPage);  for(i=0; i<pPage->pPager->pageSize; i++){    hash = (hash+i)^pData[i];  }  return hash;}/*** 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->errMask || MEMDB || pPg->dirty ||       pPg->pageHash==pager_pagehash(pPg) );}#else#define CHECK_PAGE(x)#endif/*** 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 obtained from sqliteMalloc(). *pzMaster is** set to point at the memory and SQLITE_OK returned. The caller must** sqliteFree() *pzMaster.**** If no master journal file name is present *pzMaster is set to 0 and** SQLITE_OK returned.*/static int readMasterJournal(OsFile *pJrnl, char **pzMaster){  int rc;  u32 len;  i64 szJ;  u32 cksum;  int i;  unsigned char aMagic[8]; /* A buffer to hold the magic header */  *pzMaster = 0;  rc = sqlite3OsFileSize(pJrnl, &szJ);  if( rc!=SQLITE_OK || szJ<16 ) return rc;  rc = sqlite3OsSeek(pJrnl, szJ-16);  if( rc!=SQLITE_OK ) return rc;   rc = read32bits(pJrnl, &len);  if( rc!=SQLITE_OK ) return rc;  rc = read32bits(pJrnl, &cksum);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3OsRead(pJrnl, aMagic, 8);  if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;  rc = sqlite3OsSeek(pJrnl, szJ-16-len);  if( rc!=SQLITE_OK ) return rc;  *pzMaster = (char *)sqliteMalloc(len+1);  if( !*pzMaster ){    return SQLITE_NOMEM;  }  rc = sqlite3OsRead(pJrnl, *pzMaster, len);  if( rc!=SQLITE_OK ){    sqliteFree(*pzMaster);    *pzMaster = 0;    return rc;  }  /* See if the checksum matches the master journal name */  for(i=0; i<len; i++){    cksum -= (*pzMaster)[i];  }  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.    */    sqliteFree(*pzMaster);    *pzMaster = 0;  }else{    (*pzMaster)[len] = '\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 int 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;  return sqlite3OsSeek(&pPager->jfd, pPager->journalOff);}/*** 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.** ** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space.*/static int writeJournalHdr(Pager *pPager){  int rc = seekJournalHdr(pPager);  if( rc ) return rc;  pPager->journalHdr = pPager->journalOff;  if( pPager->stmtHdrOff==0 ){    pPager->stmtHdrOff = pPager->journalHdr;  }  pPager->journalOff += JOURNAL_HDR_SZ(pPager);  /* FIX ME:   **  ** Possibly for a pager not in no-sync mode, the journal magic should not  ** be written until nRec is filled in as part of next syncJournal().   **  ** Actually maybe the whole journal header should be delayed until that  ** point. Think about this.  */  rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));  if( rc==SQLITE_OK ){    /* The nRec Field. 0xFFFFFFFF for no-sync journals. */    rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0);  }  if( rc==SQLITE_OK ){    /* The random check-hash initialiser */     sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);    rc = write32bits(&pPager->jfd, pPager->cksumInit);  }  if( rc==SQLITE_OK ){    /* The initial database size */    rc = write32bits(&pPager->jfd, pPager->dbSize);  }  if( rc==SQLITE_OK ){    /* The assumed sector size for this process */    rc = write32bits(&pPager->jfd, pPager->sectorSize);  }  /* The journal header has been written successfully. Seek the journal  ** file descriptor to the end of the journal header sector.  */  if( rc==SQLITE_OK ){    sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1);    rc = sqlite3OsWrite(&pPager->jfd, "\000", 1);  }  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,   u32 *pDbSize){  int rc;  unsigned char aMagic[8]; /* A buffer to hold the magic header */  rc = seekJournalHdr(pPager);  if( rc ) return rc;  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){    return SQLITE_DONE;  }  rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic));  if( rc ) return rc;  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){    return SQLITE_DONE;  }  rc = read32bits(&pPager->jfd, pNRec);  if( rc ) return rc;  rc = read32bits(&pPager->jfd, &pPager->cksumInit);  if( rc ) return rc;  rc = read32bits(&pPager->jfd, pDbSize);  if( rc ) return rc;  /* Update the assumed sector-size to match the value used by   ** the process that created this journal. If this journal was  ** created by a process other than this one, then this routine  ** is being called from within pager_playback(). The local value  ** of Pager.sectorSize is restored at the end of that routine.  */  rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize);  if( rc ) return rc;  pPager->journalOff += JOURNAL_HDR_SZ(pPager);  rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff);  return rc;}/*** Write the supplied master journal name into the journal file for pager** pPager at the current location. The master journal name must be the last** thing written to a journal file. If the pager is in full-sync mode, the** journal file descriptor is advanced to the next sector boundary before** anything is written. The format is:**** + 4 bytes: PAGER_MJ_PGNO.** + N bytes: length of master journal name.** + 4 bytes: N** + 4 bytes: Master journal name checksum.** + 8 bytes: aJournalMagic[].**** The master journal page checksum is the sum of the bytes in the master** journal name.*/static int writeMasterJournal(Pager *pPager, const char *zMaster){  int rc;  int len;   int i;   u32 cksum = 0;   if( !zMaster || pPager->setMaster) return SQLITE_OK;  pPager->setMaster = 1;  len = strlen(zMaster);  for(i=0; i<len; i++){    cksum += zMaster[i];  }  /* If in full-sync mode, advance to the next disk sector before writing  ** the master journal name. This is in case the previous page written to  ** the journal has already been synced.  */  if( pPager->fullSync ){    rc = seekJournalHdr(pPager);    if( rc!=SQLITE_OK ) return rc;  }  pPager->journalOff += (len+20);

⌨️ 快捷键说明

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