📄 pager.c
字号:
pagerEnter(pPager); if( aHash==0 ){ /* Failure to rehash is not an error. It is only a performance hit. */ return; } sqlite3_free(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(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);}/*** If file pFd is open, call sqlite3OsUnlock() on it.*/static int osUnlock(sqlite3_file *pFd, int eLock){ if( !pFd->pMethods ){ 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.**** 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 nPage; /* Page size */ sqlite3_file *fd = pPager->fd; if( fd->pMethods ){ dc = sqlite3OsDeviceCharacteristics(fd); nSector = sqlite3OsSectorSize(fd); nPage = pPager->pageSize; } assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); if( !fd->pMethods || (dc&(SQLITE_IOCAP_ATOMIC|(nPage>>8))&&nSector<=nPage) ){ 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. 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 || (pPager->errCode & 0xff)==SQLITE_IOERR ); 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 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; int i; 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(i=0; i<len; i++){ cksum -= zMaster[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. */ 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;}/*** 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){ char zHeader[sizeof(aJournalMagic)+16]; int rc; 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 */ sqlite3Randomness(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); IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader))) rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff); pPager->journalOff += JOURNAL_HDR_SZ(pPager); /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1)) rc = sqlite3OsWrite(pPager->jfd, "\000", 1, pPager->journalOff-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(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -