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

📄 pager.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
** 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;  }  rc = seekJournalHdr(pPager);  if( rc ) return rc;  pPager->journalHdr = pPager->journalOff;  pPager->journalOff += JOURNAL_HDR_SZ(pPager);  /* FIX ME:   **  ** Possibly for a pager not in no-sync mode, the journal magic should not  ** be written until nRec is filled in as part of next syncJournal().   **  ** Actually maybe the whole journal header should be delayed until that  ** point. Think about this.  */  memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));  /* The nRec Field. 0xFFFFFFFF for no-sync journals. */  put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 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));  /* 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 = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1);    if( rc==SQLITE_OK ){      rc = sqlite3OsWrite(pPager->jfd, "\000", 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(  Pager *pPager,   i64 journalSize,  u32 *pNRec,   u32 *pDbSize){  int rc;  unsigned char aMagic[8]; /* A buffer to hold the magic header */  rc = seekJournalHdr(pPager);  if( rc ) return rc;  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){    return SQLITE_DONE;  }  rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic));  if( rc ) return rc;  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){    return SQLITE_DONE;  }  rc = read32bits(pPager->jfd, pNRec);  if( rc ) return rc;  rc = read32bits(pPager->jfd, &pPager->cksumInit);  if( rc ) return rc;  rc = read32bits(pPager->jfd, pDbSize);  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, (u32 *)&pPager->sectorSize);  if( rc ) return rc;  pPager->journalOff += JOURNAL_HDR_SZ(pPager);  rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff);  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: 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;   u32 cksum = 0;  char zBuf[sizeof(aJournalMagic)+2*4];  if( !zMaster || pPager->setMaster) 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 ){    rc = seekJournalHdr(pPager);    if( rc!=SQLITE_OK ) return rc;  }  pPager->journalOff += (len+20);  rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager));  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3OsWrite(pPager->jfd, zMaster, len);  if( rc!=SQLITE_OK ) return rc;  put32bits(zBuf, len);  put32bits(&zBuf[4], cksum);  memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));  rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic));  pPager->needSync = !pPager->noSync;  return rc;}/*** Add or remove a page from the list of all pages that are in the** statement journal.**** The Pager keeps a separate list of pages that are currently in** the statement journal.  This helps the sqlite3PagerStmtCommit()** routine run MUCH faster for the common case where there are many** pages in memory but only a few are in the statement journal.*/static void page_add_to_stmt_list(PgHdr *pPg){  Pager *pPager = pPg->pPager;  PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);  assert( MEMDB );  if( !pHist->inStmt ){    assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 );    if( pPager->pStmt ){      PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg;    }    pHist->pNextStmt = pPager->pStmt;    pPager->pStmt = pPg;    pHist->inStmt = 1;  }}/*** 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;  if( pPager->aHash==0 ) return 0;  p = pPager->aHash[pgno & (pPager->nHash-1)];  while( p && p->pgno!=pgno ){    p = p->pNextHash;  }  return p;}/*** Unlock the database file.*/static void pager_unlock(Pager *pPager){  if( !pPager->exclusiveMode ){    if( !MEMDB ){      sqlite3OsUnlock(pPager->fd, NO_LOCK);      pPager->dbSize = -1;      IOTRACE(("UNLOCK %p\n", pPager))    }    pPager->state = PAGER_UNLOCK;    pPager->changeCountDone = 0;  }}/*** Execute a rollback if a transaction is active and unlock the ** database file. This is a no-op if the pager has already entered** the error-state.*/static void pagerUnlockAndRollback(Pager *p){  if( p->errCode ) return;  assert( p->state>=PAGER_RESERVED || p->journalOpen==0 );  if( p->state>=PAGER_RESERVED ){    sqlite3PagerRollback(p);  }  pager_unlock(p);  assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );  assert( p->errCode || !p->stmtOpen || p->exclusiveMode );}/*** 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){  PgHdr *pPg, *pNext;  if( pPager->errCode ) return;  for(pPg=pPager->pAll; pPg; pPg=pNext){    IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));    PAGER_INCR(sqlite3_pager_pgfree_count);    pNext = pPg->pNextAll;    sqliteFree(pPg);  }  pPager->pStmt = 0;  pPager->pFirst = 0;  pPager->pFirstSynced = 0;  pPager->pLast = 0;  pPager->pAll = 0;  pPager->nHash = 0;  sqliteFree(pPager->aHash);  pPager->nPage = 0;  pPager->aHash = 0;  pPager->nRef = 0;}/*** 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){  PgHdr *pPg;  int rc = SQLITE_OK;  int rc2 = SQLITE_OK;  assert( !MEMDB );  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->exclusiveMode           && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){;      sqlite3OsSeek(pPager->jfd, 0);      pPager->journalOff = 0;      pPager->journalStarted = 0;    }else{      sqlite3OsClose(&pPager->jfd);      pPager->journalOpen = 0;      if( rc==SQLITE_OK ){        rc = sqlite3OsDelete(pPager->zJournal);      }    }    sqliteFree( pPager->aInJournal );    pPager->aInJournal = 0;    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){      pPg->inJournal = 0;      pPg->dirty = 0;      pPg->needSync = 0;      pPg->alwaysRollback = 0;#ifdef SQLITE_CHECK_PAGES      pPg->pageHash = pager_pagehash(pPg);#endif    }    pPager->pDirty = 0;    pPager->dirtyCache = 0;    pPager->nRec = 0;  }else{    assert( pPager->aInJournal==0 );    assert( pPager->dirtyCache==0 || pPager->useJournal==0 );  }  if( !pPager->exclusiveMode ){    rc2 = sqlite3OsUnlock(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;  pPager->pFirstSynced = pPager->pFirst;  pPager->dbSize = -1;  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.

⌨️ 快捷键说明

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