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 + -
显示快捷键?