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

📄 pager.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef SQLITE_HAS_CODEC  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */  void *pCodecArg;            /* First argument to xCodec() */#endif  int nHash;                  /* Size of the pager hash table */  PgHdr **aHash;              /* Hash table to map page number to PgHdr */#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT  Pager *pNext;               /* Linked list of pagers in this thread */#endif  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */  char dbFileVers[16];        /* Changes whenever database file changes */};/*** The following global variables hold counters used for** testing purposes only.  These variables do not exist in** a non-testing build.  These variables are not thread-safe.*/#ifdef SQLITE_TESTint sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */int sqlite3_pager_pgfree_count = 0;    /* Number of cache pages freed */# define PAGER_INCR(v)  v++#else# define PAGER_INCR(v)#endif/*** Journal files begin with the following magic string.  The data** was obtained from /dev/random.  It is used only as a sanity check.**** Since version 2.8.0, the journal format contains additional sanity** checking information.  If the power fails while the journal is begin** written, semi-random garbage data might appear in the journal** file after power is restored.  If an attempt is then made** to roll the journal back, the database could be corrupted.  The additional** sanity checking data is an attempt to discover the garbage in the** journal and ignore it.**** The sanity checking information for the new journal format consists** of a 32-bit checksum on each page of data.  The checksum covers both** the page number and the pPager->pageSize bytes of data for the page.** This cksum is initialized to a 32-bit random value that appears in the** journal file right after the header.  The random initializer is important,** because garbage data that appears at the end of a journal is likely** data that was once in other files that have now been deleted.  If the** garbage data came from an obsolete journal file, the checksums might** be correct.  But by initializing the checksum to random value which** is different for every journal, we minimize that risk.*/static const unsigned char aJournalMagic[] = {  0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,};/*** The size of the header and of each page in the journal is determined** by the following macros.*/#define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)/*** The journal header size for this pager. In the future, this could be** set to some value read from the disk controller. The important** characteristic is that it is the same size as a disk sector.*/#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)/*** The macro MEMDB is true if we are dealing with an in-memory database.** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,** the value of MEMDB will be a constant and the compiler will optimize** out code that would never execute.*/#ifdef SQLITE_OMIT_MEMORYDB# define MEMDB 0#else# define MEMDB pPager->memDb#endif/*** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is** reserved for working around a windows/posix incompatibility). It is** used in the journal to signify that the remainder of the journal file ** is devoted to storing a master journal name - there are no more pages to** roll back. See comments for function writeMasterJournal() for details.*//* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)/*** The maximum legal page number is (2^31 - 1).*/#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=%-3d total=%d\n",       p->pgno, PGHDR_TO_DATA(p), p->nRef, p->pPager->nRef    );    cnt++;   /* Something to set a breakpoint on */  }# define REFINFO(X)  pager_refinfo(X)#else# define REFINFO(X)#endif/*** Return true if page *pPg has already been written to the statement** journal (or statement snapshot has been created, if *pPg is part** of an in-memory database).*/static int pageInStatement(PgHdr *pPg){  Pager *pPager = pPg->pPager;  if( MEMDB ){    return PGHDR_TO_HIST(pPg, pPager)->inStmt;  }else{    Pgno pgno = pPg->pgno;    u8 *a = pPager->aInStmt;    return (a && (int)pgno<=pPager->stmtSize && (a[pgno/8] & (1<<(pgno&7))));  }}/*** Change the size of the pager hash table to N.  N must be a power** of two.*/static void pager_resize_hash_table(Pager *pPager, int N){  PgHdr **aHash, *pPg;  assert( N>0 && (N&(N-1))==0 );  aHash = sqliteMalloc( sizeof(aHash[0])*N );  if( aHash==0 ){    /* Failure to rehash is not an error.  It is only a performance hit. */    return;  }  sqliteFree(pPager->aHash);  pPager->nHash = N;  pPager->aHash = aHash;  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){    int h;    if( pPg->pgno==0 ){      assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );      continue;    }    h = pPg->pgno & (N-1);    pPg->pNextHash = aHash[h];    if( aHash[h] ){      aHash[h]->pPrevHash = pPg;    }    aHash[h] = pPg;    pPg->pPrevHash = 0;  }}/*** 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){  unsigned char ac[4];  int rc = sqlite3OsRead(fd, ac, sizeof(ac));  if( rc==SQLITE_OK ){    *pRes = sqlite3Get4byte(ac);  }  return rc;}/*** Write a 32-bit integer into a string buffer in big-endian byte order.*/#define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)/*** 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){  char ac[4];  put32bits(ac, val);  return sqlite3OsWrite(fd, ac, 4);}/*** 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. All subsequent API calls on this Pager** will immediately return the same error code.*/static int pager_error(Pager *pPager, int rc){  int rc2 = rc & 0xff;  assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK );  if(    rc2==SQLITE_FULL ||    rc2==SQLITE_IOERR ||    rc2==SQLITE_CORRUPT  ){    pPager->errCode = rc;  }  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 *)PGHDR_TO_DATA(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->dirty ||       pPg->pageHash==pager_pagehash(pPg) );}#else#define pager_datahash(X,Y)  0#define pager_pagehash(X)  0#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.**

⌨️ 快捷键说明

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