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

📄 pager.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
*/static int readJournalHdr(  Pager *pPager,   i64 journalSize,  u32 *pNRec,   u32 *pDbSize){  int rc;  unsigned char aMagic[8]; /* A buffer to hold the magic header */  i64 jrnlOff;  int iPageSize;  seekJournalHdr(pPager);  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){    return SQLITE_DONE;  }  jrnlOff = pPager->journalOff;  rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff);  if( rc ) return rc;  jrnlOff += sizeof(aMagic);  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){    return SQLITE_DONE;  }  rc = read32bits(pPager->jfd, jrnlOff, pNRec);  if( rc ) return rc;  rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);  if( rc ) return rc;  rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);  if( rc ) return rc;  rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize);  if( rc==SQLITE_OK    && iPageSize>=512    && iPageSize<=SQLITE_MAX_PAGE_SIZE    && ((iPageSize-1)&iPageSize)==0   ){    u16 pagesize = iPageSize;    rc = sqlite3PagerSetPagesize(pPager, &pagesize);  }  if( rc ) return rc;  /* 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.  */  rc = read32bits(pPager->jfd, jrnlOff+12, &pPager->sectorSize);  if( rc ) return rc;  if( (pPager->sectorSize & (pPager->sectorSize-1))!=0         || pPager->sectorSize>0x1000000 ){    return SQLITE_DONE;  }  pPager->journalOff += JOURNAL_HDR_SZ(pPager);  return SQLITE_OK;}/*** 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: length of master journal name.** + 4 bytes: N** + 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.**** 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;  int len;   int i;   i64 jrnlOff;  i64 jrnlSize;  u32 cksum = 0;  char zBuf[sizeof(aJournalMagic)+2*4];  if( !zMaster || pPager->setMaster ) return SQLITE_OK;  if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK;  pPager->setMaster = 1;  len = strlen(zMaster);  for(i=0; i<len; i++){    cksum += zMaster[i];  }  /* If in full-sync mode, advance to the next disk sector before writing  ** the master journal name. This is in case the previous page written to  ** the journal has already been synced.  */  if( pPager->fullSync ){    seekJournalHdr(pPager);  }  jrnlOff = pPager->journalOff;  pPager->journalOff += (len+20);  rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager));  if( rc!=SQLITE_OK ) return rc;  jrnlOff += 4;  rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff);  if( rc!=SQLITE_OK ) return rc;  jrnlOff += len;  put32bits(zBuf, len);  put32bits(&zBuf[4], cksum);  memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));  rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff);  jrnlOff += 8+sizeof(aJournalMagic);  pPager->needSync = !pPager->noSync;  /* If the pager is in peristent-journal mode, then the physical   ** journal-file may extend past the end of the master-journal name  ** and 8 bytes of magic data just written to the file. This is   ** dangerous because the code to rollback a hot-journal file  ** will not be able to find the master-journal name to determine   ** whether or not the journal is hot.   **  ** Easiest thing to do in this scenario is to truncate the journal   ** file to the required size.  */   if( (rc==SQLITE_OK)   && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK   && jrnlSize>jrnlOff  ){    rc = sqlite3OsTruncate(pPager->jfd, jrnlOff);  }  return rc;}/*** Find a page in the hash table given its page number.  Return** a pointer to the page or NULL if not found.*/static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){  PgHdr *p;  sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);  return p;}/*** Clear the in-memory cache.  This routine** sets the state of the pager back to what it was when it was first** opened.  Any outstanding pages are invalidated and subsequent attempts** to access those pages will likely result in a coredump.*/static void pager_reset(Pager *pPager){  if( pPager->errCode ) return;  sqlite3PcacheClear(pPager->pPCache);}/*** Unlock the database file. **** If the pager is currently in error state, discard the contents of ** the cache and reset the Pager structure internal state. If there is** an open journal-file, then the next time a shared-lock is obtained** on the pager file (by this or any other process), it will be** treated as a hot-journal and rolled back.*/static void pager_unlock(Pager *pPager){  if( !pPager->exclusiveMode ){    int rc = osUnlock(pPager->fd, NO_LOCK);    if( rc ) pPager->errCode = rc;    pPager->dbSizeValid = 0;    IOTRACE(("UNLOCK %p\n", pPager))    /* Always close the journal file when dropping the database lock.    ** Otherwise, another connection with journal_mode=delete might    ** delete the file out from under us.    */    if( pPager->journalOpen ){      sqlite3OsClose(pPager->jfd);      pPager->journalOpen = 0;      sqlite3BitvecDestroy(pPager->pInJournal);      pPager->pInJournal = 0;      sqlite3BitvecDestroy(pPager->pAlwaysRollback);      pPager->pAlwaysRollback = 0;    }    /* If Pager.errCode is set, the contents of the pager cache cannot be    ** trusted. Now that the pager file is unlocked, the contents of the    ** cache can be discarded and the error code safely cleared.    */    if( pPager->errCode ){      if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;      pager_reset(pPager);      if( pPager->stmtOpen ){        sqlite3OsClose(pPager->stfd);        sqlite3BitvecDestroy(pPager->pInStmt);        pPager->pInStmt = 0;      }      pPager->stmtOpen = 0;      pPager->stmtInUse = 0;      pPager->journalOff = 0;      pPager->journalStarted = 0;      pPager->stmtAutoopen = 0;      pPager->origDbSize = 0;    }    pPager->state = PAGER_UNLOCK;    pPager->changeCountDone = 0;  }}/*** Execute a rollback if a transaction is active and unlock the ** database file. If the pager has already entered the error state, ** do not attempt the rollback.*/static void pagerUnlockAndRollback(Pager *p){  if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){    sqlite3BeginBenignMalloc();    sqlite3PagerRollback(p);    sqlite3EndBenignMalloc();  }  pager_unlock(p);}/*** This routine ends a transaction.  A transaction is ended by either** a COMMIT or a ROLLBACK.**** When this routine is called, the pager has the journal file open and** a RESERVED or EXCLUSIVE lock on the database.  This routine will release** the database lock and acquires a SHARED lock in its place if that is** the appropriate thing to do.  Release locks usually is appropriate,** unless we are in exclusive access mode or unless this is a ** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation.**** The journal file is either deleted or truncated.**** TODO: Consider keeping the journal file open for temporary databases.** This might give a performance improvement on windows where opening** a file is an expensive operation.*/static int pager_end_transaction(Pager *pPager, int hasMaster){  int rc = SQLITE_OK;  int rc2 = SQLITE_OK;  if( pPager->state<PAGER_RESERVED ){    return SQLITE_OK;  }  sqlite3PagerStmtCommit(pPager);  if( pPager->stmtOpen && !pPager->exclusiveMode ){    sqlite3OsClose(pPager->stfd);    pPager->stmtOpen = 0;  }  if( pPager->journalOpen ){    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){      int isMemoryJournal = sqlite3IsMemJournal(pPager->jfd);      sqlite3OsClose(pPager->jfd);      pPager->journalOpen = 0;      if( !isMemoryJournal ){        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);      }    }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE         && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){      pPager->journalOff = 0;      pPager->journalStarted = 0;    }else if( pPager->exclusiveMode      || pPager->journalMode==PAGER_JOURNALMODE_PERSIST    ){      rc = zeroJournalHdr(pPager, hasMaster);      pager_error(pPager, rc);      pPager->journalOff = 0;      pPager->journalStarted = 0;    }else{      assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || rc );      sqlite3OsClose(pPager->jfd);      pPager->journalOpen = 0;      if( rc==SQLITE_OK && !pPager->tempFile ){        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);      }    }    sqlite3BitvecDestroy(pPager->pInJournal);    pPager->pInJournal = 0;    sqlite3BitvecDestroy(pPager->pAlwaysRollback);    pPager->pAlwaysRollback = 0;#ifdef SQLITE_CHECK_PAGES    sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);#endif    sqlite3PcacheCleanAll(pPager->pPCache);    pPager->dirtyCache = 0;    pPager->nRec = 0;  }else{    assert( pPager->pInJournal==0 );  }  if( !pPager->exclusiveMode ){    rc2 = osUnlock(pPager->fd, SHARED_LOCK);    pPager->state = PAGER_SHARED;  }else if( pPager->state==PAGER_SYNCED ){    pPager->state = PAGER_EXCLUSIVE;  }  pPager->origDbSize = 0;  pPager->setMaster = 0;  pPager->needSync = 0;  /* lruListSetFirstSynced(pPager); */  if( !MEMDB ){    pPager->dbSizeValid = 0;  }  pPager->dbModified = 0;  return (rc==SQLITE_OK?rc2:rc);}/*** Compute and return a checksum for the page of data.**** This is not a real checksum.  It is really just the sum of the ** random initial value and the page number.  We experimented with** a checksum of the entire data, but that was found to be too slow.**** Note that the page number is stored at the beginning of data and** the checksum is stored at the end.  This is important.  If journal** corruption occurs due to a power failure, the most likely scenario** is that one end or the other of the record will be changed.  It is** much less likely that the two ends of the journal record will be** correct and the middle be corrupt.  Thus, this "checksum" scheme,** though fast and simple, catches the mostly likely kind of corruption.**** FIX ME:  Consider adding every 200th (or so) byte of the data to the** checksum.  That way if a single page spans 3 or more disk sectors and** only the middle sector is corrupt, we will still have a reasonable** chance of failing the checksum and thus detecting the problem.*/static u32 pager_cksum(Pager *pPager, const u8 *aData){  u32 cksum = pPager->cksumInit;  int i = pPager->pageSize-200;  while( i>0 ){    cksum += aData[i];    i -= 200;  }  return cksum;}/*** Read a single page from the journal file opened on file descriptor** jfd.  Playback this one page.**** The isMainJrnl flag is true if this is the main rollback journal and

⌨️ 快捷键说明

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