pager.c
来自「sqlite最新源码」· C语言 代码 · 共 1,620 行 · 第 1/5 页
C
1,620 行
/*** 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 being** 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 of each page record in the journal is given by** the following macro.*/#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)/*** The journal header size for this pager. This is usually the same ** size as a single disk sector. See also setSectorSize().*/#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/*** The maximum legal page number is (2^31 - 1).*/#define PAGER_MAX_PGNO 2147483647#ifndef NDEBUG /*** Usage:**** assert( assert_pager_state(pPager) );*/static int assert_pager_state(Pager *pPager){ /* A temp-file is always in PAGER_EXCLUSIVE or PAGER_SYNCED state. */ assert( pPager->tempFile==0 || pPager->state>=PAGER_EXCLUSIVE ); /* The changeCountDone flag is always set for temp-files */ assert( pPager->tempFile==0 || pPager->changeCountDone ); return 1;}#endif/*** Return true if it is necessary to write page *pPg into the sub-journal.** A page needs to be written into the sub-journal if there exists one** or more open savepoints for which:**** * The page-number is less than or equal to PagerSavepoint.nOrig, and** * The bit corresponding to the page-number is not set in** PagerSavepoint.pInSavepoint.*/static int subjRequiresPage(PgHdr *pPg){ Pgno pgno = pPg->pgno; Pager *pPager = pPg->pPager; int i; for(i=0; i<pPager->nSavepoint; i++){ PagerSavepoint *p = &pPager->aSavepoint[i]; if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ return 1; } } return 0;}/*** Return true if the page is already in the journal file.*/static int pageInJournal(PgHdr *pPg){ return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);}/*** 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(sqlite3_file *fd, i64 offset, u32 *pRes){ unsigned char ac[4]; int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); 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(sqlite3_file *fd, i64 offset, u32 val){ char ac[4]; put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4, offset);}/*** The argument to this macro is a file descriptor (type sqlite3_file*).** Return 0 if it is not open, or non-zero (but not 1) if it is.**** This is so that expressions can be written as:**** if( isOpen(pPager->jfd) ){ ...**** instead of**** if( pPager->jfd->pMethods ){ ...*/#define isOpen(pFd) ((pFd)->pMethods)/*** If file pFd is open, call sqlite3OsUnlock() on it.*/static int osUnlock(sqlite3_file *pFd, int eLock){ if( !isOpen(pFd) ){ return SQLITE_OK; } return sqlite3OsUnlock(pFd, eLock);}/*** 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.**** The optimization is also always enabled for temporary files. It is** an error to call this function if pPager is opened on an in-memory** database.**** 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){ assert( !MEMDB ); if( !pPager->tempFile ){ int dc; /* Device characteristics */ int nSector; /* Sector size */ int szPage; /* Page size */ assert( isOpen(pPager->fd) ); dc = sqlite3OsDeviceCharacteristics(pPager->fd); nSector = pPager->sectorSize; szPage = pPager->pageSize; assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ return 0; } } return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);}#endif/*** 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 void 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 || (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.** This function attempts to read a master journal file name from the ** end of the file and, if successful, copies it into memory supplied ** by the caller. See comments above writeMasterJournal() for the format** used to store a master journal file name at the end of a journal file.**** 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 a master journal file name is present at the end of the journal** file, then it is copied into the buffer pointed to by zMaster. A** nul-terminator byte is appended to the buffer following the master** journal file name.**** If it is determined that no master journal file name is present ** zMaster[0] is set to 0 and SQLITE_OK returned.**** If an error occurs while reading from the journal file, an SQLite** error code is returned.*/static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ int rc; /* Return code */ u32 len; /* Length in bytes of master journal name */ i64 szJ; /* Total size in bytes of journal file pJrnl */ u32 cksum; /* MJ checksum value read from journal */ u32 u; /* Unsigned loop counter */ unsigned char aMagic[8]; /* A buffer to hold the magic header */ zMaster[0] = '\0'; if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) || len>=nMaster || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) || memcmp(aMagic, aJournalMagic, 8) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len)) ){ return rc; } /* 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. */ len = 0; } zMaster[len] = '\0'; return SQLITE_OK;}/*** Return the offset of the sector boundary at or immediately ** following the value in pPager->journalOff, assuming a sector ** size of pPager->sectorSize bytes.**** i.e for a sector size of 512:**** Pager.journalOff Return value** ---------------------------------------** 0 0** 512 512** 100 512** 2000 2048** */static i64 journalHdrOffset(Pager *pPager){ i64 offset = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?