pager.c
来自「sqlite最新源码」· C语言 代码 · 共 1,620 行 · 第 1/5 页
C
1,620 行
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) ); return offset;}/*** The journal file must be open when this function is called.**** This function is a no-op if the journal file has not been written to** within the current transaction (i.e. if Pager.journalOff==0).**** If doTruncate is non-zero or the Pager.journalSizeLimit variable is** set to 0, then truncate the journal file to zero bytes in size. Otherwise,** zero the 28-byte header at the start of the journal file. In either case, ** if the pager is not in no-sync mode, sync the journal file immediately ** after writing or truncating it.**** If Pager.journalSizeLimit is set to a positive, non-zero value, and** following the truncation or zeroing described above the size of the ** journal file in bytes is larger than this value, then truncate the** journal file to Pager.journalSizeLimit bytes. The journal file does** not need to be synced following this operation.**** If an IO error occurs, abandon processing and return the IO error code.** Otherwise, return SQLITE_OK.*/static int zeroJournalHdr(Pager *pPager, int doTruncate){ int rc = SQLITE_OK; /* Return code */ assert( isOpen(pPager->jfd) ); if( pPager->journalOff ){ const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */ IOTRACE(("JZEROHDR %p\n", pPager)) if( doTruncate || iLimit==0 ){ rc = sqlite3OsTruncate(pPager->jfd, 0); }else{ static const char zeroHdr[28] = {0}; 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; /* Return code */ char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ u32 nHeader = pPager->pageSize; /* Size of buffer pointed to by zHeader */ u32 nWrite; /* Bytes of header sector written */ int ii; /* Loop counter */ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ if( nHeader>JOURNAL_HDR_SZ(pPager) ){ nHeader = JOURNAL_HDR_SZ(pPager); } /* If there are active savepoints and any of them were created ** since the most recent journal header was written, update the ** PagerSavepoint.iHdrOffset fields now. */ for(ii=0; ii<pPager->nSavepoint; ii++){ if( pPager->aSavepoint[ii].iHdrOffset==0 ){ pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; } } pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); 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( isOpen(pPager->fd) || pPager->noSync ); if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) || (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->dbOrigSize); /* The assumed sector size for this process */ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); /* The page size */ put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); /* Initializing the tail of the buffer is not necessary. Everything ** works find if the following memset() is omitted. But initializing ** the memory prevents valgrind from complaining, so we are willing to ** take the performance hit. */ memset(&zHeader[sizeof(aJournalMagic)+20], 0, nHeader-(sizeof(aJournalMagic)+20)); /* In theory, it is only necessary to write the 28 bytes that the ** journal header consumes to the journal file here. Then increment the ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next ** record is written to the following sector (leaving a gap in the file ** that will be implicitly filled in by the OS). ** ** However it has been discovered that on some systems this pattern can ** be significantly slower than contiguously writing data to the file, ** even if that means explicitly writing data to the block of ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what ** is done. ** ** The loop is required here in case the sector-size is larger than the ** database page size. Since the zHeader buffer is only Pager.pageSize ** bytes in size, more than one call to sqlite3OsWrite() may be required ** to populate the entire journal header sector. */ 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. The current location in the journal file is given by** pPager->journalOff. See comments above function writeJournalHdr() for** a description of the journal header format.**** If the header is read successfully, *pNRec is set to the number of** page records following this header and *pDbSize 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 *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes** cannot be read from the journal file an error code is returned.*/static int readJournalHdr( Pager *pPager, /* Pager object */ i64 journalSize, /* Size of the open journal file in bytes */ u32 *pNRec, /* OUT: Value read from the nRec field */ u32 *pDbSize /* OUT: Value of original database size field */){ int rc; /* Return code */ unsigned char aMagic[8]; /* A buffer to hold the magic header */ i64 iHdrOff; /* Offset of journal header being read */ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ /* Advance Pager.journalOff to the start of the next sector. If the ** journal file is too small for there to be a header stored at this ** point, return SQLITE_DONE. */ pPager->journalOff = journalHdrOffset(pPager); if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ return SQLITE_DONE; } iHdrOff = pPager->journalOff; /* Read in the first 8 bytes of the journal header. If they do not match ** the magic string found at the start of each journal header, return ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, ** proceed. */ rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); if( rc ){ return rc; } if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ return SQLITE_DONE; } /* Read the first three 32-bit fields of the journal header: The nRec ** field, the checksum-initializer and the database size at the start ** of the transaction. Return an error code if anything goes wrong. */ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec)) || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit)) || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize)) ){ return rc; } if( pPager->journalOff==0 ){ u32 iPageSize; /* Page-size field of journal header */ u32 iSectorSize; /* Sector-size field of journal header */ u16 iPageSize16; /* Copy of iPageSize in 16-bit variable */ /* Read the page-size and sector-size journal header fields. */ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) ){ return rc; } /* Check that the values read from the page-size and sector-size fields ** are within range. To be 'in range', both values need to be a power ** of two greater than or equal to 512, and not greater than their ** respective compile time maximum limits. */ if( iPageSize<512 || iSectorSize<512 || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 ){ /* If the either the page-size or sector-size in the journal-header is ** invalid, then the process that wrote the journal-header must have ** crashed before the header was synced. In this case stop reading ** the journal file here. */ return SQLITE_DONE; } /* Update the page-size to match the value read from the journal. ** Use a testcase() macro to make sure that malloc failure within ** PagerSetPagesize() is tested. */ iPageSize16 = (u16)iPageSize; rc = sqlite3PagerSetPagesize(pPager, &iPageSize16); testcase( rc!=SQLITE_OK ); assert( rc!=SQLITE_OK || iPageSize16==(u16)iPageSize ); /* 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. */ pPager->sectorSize = iSectorSize; } pPager->journalOff += JOURNAL_HDR_SZ(pPager); 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: Master journal filename in utf-8.** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).** + 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, where each byte is interpreted as a signed 8-bit integer.**** If zMaster is a NULL pointer (occurs for a single database transaction), ** this call is a no-op.*/static int writeMasterJournal(Pager *pPager, const char *zMaster){ int rc; /* Return code */ int nMaster; /* Length of string zMaster */ i64 iHdrOff; /* Offset of header in journal file */ i64 jrnlSize; /* Size of journal file on disk */ u32 cksum = 0; /* Checksum of string zMaster */ if( !zMaster || pPager->setMaster || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_OFF
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?