Back to index

lightning-sunbird  0.9+nobinonly
Defines | Typedefs | Functions
pager.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define SQLITE_DEFAULT_PAGE_SIZE   1024
#define SQLITE_MAX_PAGE_SIZE   32768
#define SQLITE_MAX_PAGE   1073741823
#define PAGER_OMIT_JOURNAL   0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK   0x0002 /* Omit readlocks on readonly files */

Typedefs

typedef unsigned int Pgno
typedef struct Pager

Functions

int sqlite3pager_open (Pager **ppPager, const char *zFilename, int nExtra, int flags)
void sqlite3pager_set_busyhandler (Pager *, BusyHandler *pBusyHandler)
void sqlite3pager_set_destructor (Pager *, void(*)(void *, int))
void sqlite3pager_set_reiniter (Pager *, void(*)(void *, int))
int sqlite3pager_set_pagesize (Pager *, int)
void sqlite3pager_read_fileheader (Pager *, int, unsigned char *)
void sqlite3pager_set_cachesize (Pager *, int)
int sqlite3pager_close (Pager *pPager)
int sqlite3pager_get (Pager *pPager, Pgno pgno, void **ppPage)
voidsqlite3pager_lookup (Pager *pPager, Pgno pgno)
int sqlite3pager_ref (void *)
int sqlite3pager_unref (void *)
Pgno sqlite3pager_pagenumber (void *)
int sqlite3pager_write (void *)
int sqlite3pager_iswriteable (void *)
int sqlite3pager_overwrite (Pager *pPager, Pgno pgno, void *)
int sqlite3pager_pagecount (Pager *)
int sqlite3pager_truncate (Pager *, Pgno)
int sqlite3pager_begin (void *, int exFlag)
int sqlite3pager_commit (Pager *)
int sqlite3pager_sync (Pager *, const char *zMaster, Pgno)
int sqlite3pager_rollback (Pager *)
int sqlite3pager_isreadonly (Pager *)
int sqlite3pager_stmt_begin (Pager *)
int sqlite3pager_stmt_commit (Pager *)
int sqlite3pager_stmt_rollback (Pager *)
void sqlite3pager_dont_rollback (void *)
void sqlite3pager_dont_write (Pager *, Pgno)
intsqlite3pager_stats (Pager *)
void sqlite3pager_set_safety_level (Pager *, int, int)
const char * sqlite3pager_filename (Pager *)
const char * sqlite3pager_dirname (Pager *)
const char * sqlite3pager_journalname (Pager *)
int sqlite3pager_nosync (Pager *)
int sqlite3pager_rename (Pager *, const char *zNewName)
void sqlite3pager_set_codec (Pager *, void *(*)(void *, void *, Pgno, int), void *)
int sqlite3pager_movepage (Pager *, void *, Pgno)
int sqlite3pager_reset (Pager *)
int sqlite3pager_release_memory (int)
int sqlite3pager_loadall (Pager *)
 Addition for Mozilla: This will attempt to populate the database cache with the first N bytes of the file, where N is the total size of the cache.

Define Documentation

#define PAGER_NO_READLOCK   0x0002 /* Omit readlocks on readonly files */

Definition at line 65 of file pager.h.

#define PAGER_OMIT_JOURNAL   0x0001 /* Do not use a rollback journal */

Definition at line 64 of file pager.h.

Definition at line 26 of file pager.h.

#define SQLITE_MAX_PAGE   1073741823

Definition at line 46 of file pager.h.

Definition at line 40 of file pager.h.


Typedef Documentation

typedef struct Pager

Definition at line 57 of file pager.h.

typedef unsigned int Pgno

Definition at line 52 of file pager.h.


Function Documentation

int sqlite3pager_begin ( void ,
int  exFlag 
)

Definition at line 2952 of file pager.c.

                                               {
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;
  int rc = SQLITE_OK;
  assert( pPg->nRef>0 );
  assert( pPager->state!=PAGER_UNLOCK );
  if( pPager->state==PAGER_SHARED ){
    assert( pPager->aInJournal==0 );
    if( MEMDB ){
      pPager->state = PAGER_EXCLUSIVE;
      pPager->origDbSize = pPager->dbSize;
    }else{
      rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
      if( rc==SQLITE_OK ){
        pPager->state = PAGER_RESERVED;
        if( exFlag ){
          rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
        }
      }
      if( rc!=SQLITE_OK ){
        return rc;
      }
      pPager->dirtyCache = 0;
      TRACE2("TRANSACTION %d\n", PAGERID(pPager));
      if( pPager->useJournal && !pPager->tempFile ){
        rc = pager_open_journal(pPager);
      }
    }
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sqlite3pager_close ( Pager pPager)

Definition at line 2020 of file pager.c.

                                     {
  PgHdr *pPg, *pNext;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
  ** malloc() must have already been made by this thread before it gets
  ** to this point. This means the ThreadData must have been allocated already
  ** so that ThreadData.nAlloc can be set.
  */
  ThreadData *pTsd = sqlite3ThreadData();
  assert( pPager );
  assert( pTsd && pTsd->nAlloc );
#endif

  switch( pPager->state ){
    case PAGER_RESERVED:
    case PAGER_SYNCED: 
    case PAGER_EXCLUSIVE: {
      /* We ignore any IO errors that occur during the rollback
      ** operation. So disable IO error simulation so that testing
      ** works more easily.
      */
      disable_simulated_io_errors();
      sqlite3pager_rollback(pPager);
      enable_simulated_io_errors();
      if( !MEMDB ){
        sqlite3OsUnlock(pPager->fd, NO_LOCK);
      }
      assert( pPager->errCode || pPager->journalOpen==0 );
      break;
    }
    case PAGER_SHARED: {
      if( !MEMDB ){
        sqlite3OsUnlock(pPager->fd, NO_LOCK);
      }
      break;
    }
    default: {
      /* Do nothing */
      break;
    }
  }
  for(pPg=pPager->pAll; pPg; pPg=pNext){
#ifndef NDEBUG
    if( MEMDB ){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( !pPg->alwaysRollback );
      assert( !pHist->pOrig );
      assert( !pHist->pStmt );
    }
#endif
    pNext = pPg->pNextAll;
    sqliteFree(pPg);
  }
  TRACE2("CLOSE %d\n", PAGERID(pPager));
  assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
  if( pPager->journalOpen ){
    sqlite3OsClose(&pPager->jfd);
  }
  sqliteFree(pPager->aInJournal);
  if( pPager->stmtOpen ){
    sqlite3OsClose(&pPager->stfd);
  }
  sqlite3OsClose(&pPager->fd);
  /* Temp files are automatically deleted by the OS
  ** if( pPager->tempFile ){
  **   sqlite3OsDelete(pPager->zFilename);
  ** }
  */

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  /* Remove the pager from the linked list of pagers starting at 
  ** ThreadData.pPager if memory-management is enabled.
  */
  if( pPager==pTsd->pPager ){
    pTsd->pPager = pPager->pNext;
  }else{
    Pager *pTmp;
    for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){}
    pTmp->pNext = pPager->pNext;
  }
#endif
  sqliteFree(pPager->aHash);
  sqliteFree(pPager);
  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3311 of file pager.c.

                                      {
  int rc;
  PgHdr *pPg;

  if( pPager->errCode ){
    return pPager->errCode;
  }
  if( pPager->state<PAGER_RESERVED ){
    return SQLITE_ERROR;
  }
  TRACE2("COMMIT %d\n", PAGERID(pPager));
  if( MEMDB ){
    pPg = pager_get_all_dirty_pages(pPager);
    while( pPg ){
      clearHistory(PGHDR_TO_HIST(pPg, pPager));
      pPg->dirty = 0;
      pPg->inJournal = 0;
      pPg->inStmt = 0;
      pPg->needSync = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
      pPg = pPg->pDirty;
    }
    pPager->pDirty = 0;
#ifndef NDEBUG
    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
      assert( !pPg->alwaysRollback );
      assert( !pHist->pOrig );
      assert( !pHist->pStmt );
    }
#endif
    pPager->pStmt = 0;
    pPager->state = PAGER_SHARED;
    return SQLITE_OK;
  }
  if( pPager->dirtyCache==0 ){
    /* Exit early (without doing the time-consuming sqlite3OsSync() calls)
    ** if there have been no changes to the database file. */
    assert( pPager->needSync==0 );
    rc = pager_unwritelock(pPager);
    pPager->dbSize = -1;
    return rc;
  }
  assert( pPager->journalOpen );
  rc = sqlite3pager_sync(pPager, 0, 0);
  if( rc==SQLITE_OK ){
    rc = pager_unwritelock(pPager);
    pPager->dbSize = -1;
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3601 of file pager.c.

                                               {
  return pPager->zDirectory;
}

Here is the caller graph for this function:

Definition at line 3279 of file pager.c.

                                            {
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;

  if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
  if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
  if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
    assert( pPager->aInJournal!=0 );
    pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    pPg->inJournal = 1;
    if( pPager->stmtInUse ){
      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
      page_add_to_stmt_list(pPg);
    }
    TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  }
  if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
    assert( pPager->aInStmt!=0 );
    pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    page_add_to_stmt_list(pPg);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3245 of file pager.c.

                                                      {
  PgHdr *pPg;

  if( MEMDB ) return;

  pPg = pager_lookup(pPager, pgno);
  assert( pPg!=0 );  /* We never call _dont_write unless the page is in mem */
  pPg->alwaysRollback = 1;
  if( pPg->dirty && !pPager->stmtInUse ){
    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
      /* If this pages is the last page in the file and the file has grown
      ** during the current transaction, then do NOT mark the page as clean.
      ** When the database file grows, we must make sure that the last page
      ** gets written at least once so that the disk file will be the correct
      ** size. If you do not write this page and the size of the file
      ** on the disk ends up being too small, that can lead to database
      ** corruption during the next transaction.
      */
    }else{
      TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
      makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
      pPg->pageHash = pager_pagehash(pPg);
#endif
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3594 of file pager.c.

                                                {
  return pPager->zFilename;
}

Here is the caller graph for this function:

int sqlite3pager_get ( Pager pPager,
Pgno  pgno,
void **  ppPage 
)

Definition at line 2544 of file pager.c.

                                                             {
  /* This just passes through to our modified version with a NULL data pointer */
  return sqlite3pager_get2(pPager, pgno, ppPage, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3449 of file pager.c.

                                          {
  return pPager->readOnly;
}

Here is the caller graph for this function:

Here is the caller graph for this function:

Definition at line 3608 of file pager.c.

                                                   {
  return pPager->zJournal;
}

Here is the caller graph for this function:

Addition for Mozilla: This will attempt to populate the database cache with the first N bytes of the file, where N is the total size of the cache.

Because we can load this as one chunk from the disk, this is much faster than loading a subset of the pages one at a time in random order.

The pager must be initialized before this function is called. This means a statement must be open that has initialized the pager and is keeping the cache in memory.

Definition at line 3860 of file pager.c.

{
  int i;
  int rc;
  int loadSize;
  int loadPages;
  unsigned char* fileData;

  if (pPager->dbSize < 0 || pPager->pageSize < 0) {
    /* pager not initialized, this means a statement is not open */
    return SQLITE_MISUSE;
  }

  /* compute sizes */
  if (pPager->mxPage < pPager->dbSize)
    loadPages = pPager->mxPage;
  else
    loadPages = pPager->dbSize;
  loadSize = loadPages * pPager->pageSize;

  rc = sqlite3OsSeek(pPager->fd, 0);
  if (rc != SQLITE_OK)
    return rc;

  /* load the file as one chunk */
  fileData = sqliteMallocRaw(loadSize);
  if (! fileData)
    return SQLITE_NOMEM;
  rc = sqlite3OsRead(pPager->fd, fileData, loadSize);
  if (rc != SQLITE_OK) {
    sqliteFree(fileData);
    return rc;
  }

  /* Copy the data to each page. Note that the page numbers we pass to _get
   * are one-based, 0 is a marker for no page. We also need to check that we
   * haven't loaded more pages than the cache can hold total. There may have
   * already been a few pages loaded before, so we may fill the cache before
   * loading all of the pages we want to.
   */
  for (i = 1; i <= loadPages && pPager->nPage < pPager->mxPage; i ++) {
    void *pPage;
    rc = sqlite3pager_get2(pPager, 1, &pPage,
                           &fileData[(i-1)*(i64)pPager->pageSize]);
    if (rc != SQLITE_OK)
      break;
    sqlite3pager_unref(pPage);
  }
  sqliteFree(fileData);
  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* sqlite3pager_lookup ( Pager pPager,
Pgno  pgno 
)

Definition at line 2786 of file pager.c.

                                                   {
  PgHdr *pPg;

  assert( pPager!=0 );
  assert( pgno!=0 );
  if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
    return 0;
  }
  pPg = pager_lookup(pPager, pgno);
  if( pPg==0 ) return 0;
  page_ref(pPg);
  return PGHDR_TO_DATA(pPg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sqlite3pager_movepage ( Pager ,
void ,
Pgno   
)

Definition at line 3770 of file pager.c.

                                                                {
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  PgHdr *pPgOld; 
  int h;
  Pgno needSyncPgno = 0;

  assert( pPg->nRef>0 );

  TRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", 
      PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);

  if( pPg->needSync ){
    needSyncPgno = pPg->pgno;
    assert( pPg->inJournal );
    assert( pPg->dirty );
    assert( pPager->needSync );
  }

  /* Unlink pPg from it's hash-chain */
  unlinkHashChain(pPager, pPg);

  /* If the cache contains a page with page-number pgno, remove it
  ** from it's hash chain. Also, if the PgHdr.needSync was set for 
  ** page pgno before the 'move' operation, it needs to be retained 
  ** for the page moved there.
  */
  pPgOld = pager_lookup(pPager, pgno);
  if( pPgOld ){
    assert( pPgOld->nRef==0 );
    unlinkHashChain(pPager, pPgOld);
    makeClean(pPgOld);
    if( pPgOld->needSync ){
      assert( pPgOld->inJournal );
      pPg->inJournal = 1;
      pPg->needSync = 1;
      assert( pPager->needSync );
    }
  }

  /* Change the page number for pPg and insert it into the new hash-chain. */
  pPg->pgno = pgno;
  h = pgno & (pPager->nHash-1);
  if( pPager->aHash[h] ){
    assert( pPager->aHash[h]->pPrevHash==0 );
    pPager->aHash[h]->pPrevHash = pPg;
  }
  pPg->pNextHash = pPager->aHash[h];
  pPager->aHash[h] = pPg;
  pPg->pPrevHash = 0;

  makeDirty(pPg);
  pPager->dirtyCache = 1;

  if( needSyncPgno ){
    /* If needSyncPgno is non-zero, then the journal file needs to be 
    ** sync()ed before any data is written to database file page needSyncPgno.
    ** Currently, no such page exists in the page-cache and the 
    ** Pager.aInJournal bit has been set. This needs to be remedied by loading
    ** the page into the pager-cache and setting the PgHdr.needSync flag.
    **
    ** The sqlite3pager_get() call may cause the journal to sync. So make
    ** sure the Pager.needSync flag is set too.
    */
    int rc;
    void *pNeedSync;
    assert( pPager->needSync );
    rc = sqlite3pager_get(pPager, needSyncPgno, &pNeedSync);
    if( rc!=SQLITE_OK ) return rc;
    pPager->needSync = 1;
    DATA_TO_PGHDR(pNeedSync)->needSync = 1;
    DATA_TO_PGHDR(pNeedSync)->inJournal = 1;
    makeDirty(DATA_TO_PGHDR(pNeedSync));
    sqlite3pager_unref(pNeedSync);
  }

  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3616 of file pager.c.

                                      {
  return pPager->noSync;
}

Here is the caller graph for this function:

int sqlite3pager_open ( Pager **  ppPager,
const char *  zFilename,
int  nExtra,
int  flags 
)

Definition at line 1570 of file pager.c.

 {
  Pager *pPager = 0;
  char *zFullPathname = 0;
  int nameLen;  /* Compiler is wrong. This is always initialized before use */
  OsFile *fd;
  int rc = SQLITE_OK;
  int i;
  int tempFile = 0;
  int memDb = 0;
  int readOnly = 0;
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
  char zTemp[SQLITE_TEMPNAME_SIZE];
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
  ** malloc() must have already been made by this thread before it gets
  ** to this point. This means the ThreadData must have been allocated already
  ** so that ThreadData.nAlloc can be set. It would be nice to assert
  ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases 
  ** written to invoke the pager directly.
  */
  ThreadData *pTsd = sqlite3ThreadData();
  assert( pTsd );
#endif

  /* If malloc() has already failed return SQLITE_NOMEM. Before even
  ** testing for this, set *ppPager to NULL so the caller knows the pager
  ** structure was never allocated. 
  */
  *ppPager = 0;
  if( sqlite3MallocFailed() ){
    return SQLITE_NOMEM;
  }
  memset(&fd, 0, sizeof(fd));

  /* Open the pager file and set zFullPathname to point at malloc()ed 
  ** memory containing the complete filename (i.e. including the directory).
  */
  if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zFullPathname = sqliteStrDup("");
    }else
#endif
    {
      zFullPathname = sqlite3OsFullPathname(zFilename);
      if( zFullPathname ){
        rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
      }
    }
  }else{
    rc = sqlite3pager_opentemp(zTemp, &fd);
    zFilename = zTemp;
    zFullPathname = sqlite3OsFullPathname(zFilename);
    if( rc==SQLITE_OK ){
      tempFile = 1;
    }
  }

  /* Allocate the Pager structure. As part of the same allocation, allocate
  ** space for the full paths of the file, directory and journal 
  ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal).
  */
  if( zFullPathname ){
    nameLen = strlen(zFullPathname);
    pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
  }

  /* If an error occured in either of the blocks above, free the memory 
  ** pointed to by zFullPathname, free the Pager structure and close the 
  ** file. Since the pager is not allocated there is no need to set 
  ** any Pager.errMask variables.
  */
  if( !pPager || !zFullPathname || rc!=SQLITE_OK ){
    sqlite3OsClose(&fd);
    sqliteFree(zFullPathname);
    sqliteFree(pPager);
    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
  }

  TRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname);
  pPager->zFilename = (char*)&pPager[1];
  pPager->zDirectory = &pPager->zFilename[nameLen+1];
  pPager->zJournal = &pPager->zDirectory[nameLen+1];
  strcpy(pPager->zFilename, zFullPathname);
  strcpy(pPager->zDirectory, zFullPathname);

  for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;
  strcpy(pPager->zJournal, zFullPathname);
  sqliteFree(zFullPathname);
  strcpy(&pPager->zJournal[nameLen], "-journal");
  pPager->fd = fd;
  /* pPager->journalOpen = 0; */
  pPager->useJournal = useJournal && !memDb;
  pPager->noReadlock = noReadlock && readOnly;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
  pPager->dbSize = memDb-1;
  pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
  /* pPager->stmtSize = 0; */
  /* pPager->stmtJSize = 0; */
  /* pPager->nPage = 0; */
  /* pPager->nMaxPage = 0; */
  pPager->mxPage = 100;
  assert( PAGER_UNLOCK==0 );
  /* pPager->state = PAGER_UNLOCK; */
  /* pPager->errMask = 0; */
  pPager->tempFile = tempFile;
  pPager->memDb = memDb;
  pPager->readOnly = readOnly;
  /* pPager->needSync = 0; */
  pPager->noSync = pPager->tempFile || !useJournal;
  pPager->fullSync = (pPager->noSync?0:1);
  /* pPager->pFirst = 0; */
  /* pPager->pFirstSynced = 0; */
  /* pPager->pLast = 0; */
  pPager->nExtra = FORCE_ALIGNMENT(nExtra);
  pPager->sectorSize = PAGER_SECTOR_SIZE;
  /* pPager->pBusyHandler = 0; */
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  *ppPager = pPager;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  pPager->pNext = pTsd->pPager;
  pTsd->pPager = pPager;
#endif
  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sqlite3pager_overwrite ( Pager pPager,
Pgno  pgno,
void  
)

Definition at line 3205 of file pager.c.

                                                                 {
  void *pPage;
  int rc;

  rc = sqlite3pager_get(pPager, pgno, &pPage);
  if( rc==SQLITE_OK ){
    rc = sqlite3pager_write(pPage);
    if( rc==SQLITE_OK ){
      memcpy(pPage, pData, pPager->pageSize);
    }
    sqlite3pager_unref(pPage);
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1806 of file pager.c.

                                         {
  i64 n;
  assert( pPager!=0 );
  if( pPager->dbSize>=0 ){
    n = pPager->dbSize;
  } else {
    if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){
      pager_error(pPager, SQLITE_IOERR);
      return 0;
    }
    if( n>0 && n<pPager->pageSize ){
      n = 1;
    }else{
      n /= pPager->pageSize;
    }
    if( pPager->state!=PAGER_UNLOCK ){
      pPager->dbSize = n;
    }
  }
  if( n==(PENDING_BYTE/pPager->pageSize) ){
    n++;
  }
  return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2109 of file pager.c.

                                         {
  PgHdr *p = DATA_TO_PGHDR(pData);
  return p->pgno;
}

Here is the caller graph for this function:

void sqlite3pager_read_fileheader ( Pager ,
int  ,
unsigned char *   
)

Definition at line 1787 of file pager.c.

                                                                             {
  memset(pDest, 0, N);
  if( MEMDB==0 ){
    disable_simulated_io_errors();
    sqlite3OsSeek(pPager->fd, 0);
    sqlite3OsRead(pPager->fd, pDest, N);
    enable_simulated_io_errors();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2163 of file pager.c.

                                 {
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  page_ref(pPg);
  return SQLITE_OK;
}

Here is the caller graph for this function:

int sqlite3pager_rename ( Pager ,
const char *  zNewName 
)

Definition at line 3375 of file pager.c.

                                        {
  int rc;
  TRACE2("ROLLBACK %d\n", PAGERID(pPager));
  if( MEMDB ){
    PgHdr *p;
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      assert( !p->alwaysRollback );
      if( !p->dirty ){
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
        continue;
      }

      pHist = PGHDR_TO_HIST(p, pPager);
      if( pHist->pOrig ){
        memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
        TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
      }else{
        TRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
      }
      clearHistory(pHist);
      p->dirty = 0;
      p->inJournal = 0;
      p->inStmt = 0;
      p->pPrevStmt = p->pNextStmt = 0;
      if( pPager->xReiniter ){
        pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize);
      }
    }
    pPager->pDirty = 0;
    pPager->pStmt = 0;
    pPager->dbSize = pPager->origDbSize;
    memoryTruncate(pPager);
    pPager->stmtInUse = 0;
    pPager->state = PAGER_SHARED;
    return SQLITE_OK;
  }

  if( !pPager->dirtyCache || !pPager->journalOpen ){
    rc = pager_unwritelock(pPager);
    pPager->dbSize = -1;
    return rc;
  }

  if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
    if( pPager->state>=PAGER_EXCLUSIVE ){
      pager_playback(pPager);
    }
    return pPager->errCode;
  }
  if( pPager->state==PAGER_RESERVED ){
    int rc2;
    rc = pager_reload_cache(pPager);
    rc2 = pager_unwritelock(pPager);
    if( rc==SQLITE_OK ){
      rc = rc2;
    }
  }else{
    rc = pager_playback(pPager);
  }
  pPager->dbSize = -1;

  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
  ** cache. So call pager_error() on the way out to make any error 
  ** persistent.
  */
  return pager_error(pPager, rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sqlite3pager_set_busyhandler ( Pager ,
BusyHandler pBusyHandler 
)

Definition at line 1709 of file pager.c.

                                                                           {
  pPager->pBusyHandler = pBusyHandler;
}

Here is the caller graph for this function:

Definition at line 1485 of file pager.c.

                                                          {
  if( mxPage>10 ){
    pPager->mxPage = mxPage;
  }else{
    pPager->mxPage = 10;
  }
}

Here is the caller graph for this function:

void sqlite3pager_set_codec ( Pager ,
void *)(void *, void *, Pgno, int,
void  
)

Definition at line 1721 of file pager.c.

                                                                         {
  pPager->xDestructor = xDesc;
}

Here is the caller graph for this function:

Definition at line 1741 of file pager.c.

                                                          {
  assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
  if( !pPager->memDb ){
    pPager->pageSize = pageSize;
  }
  return pPager->pageSize;
}

Here is the caller graph for this function:

Definition at line 1732 of file pager.c.

                                                                         {
  pPager->xReiniter = xReinit;
}

Here is the caller graph for this function:

Definition at line 1520 of file pager.c.

                                                                            {
  pPager->noSync =  level==1 || pPager->tempFile;
  pPager->fullSync = level==3 && !pPager->tempFile;
  pPager->full_fsync = full_fsync;
  if( pPager->noSync ) pPager->needSync = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3456 of file pager.c.

                                      {
  static int a[11];
  a[0] = pPager->nRef;
  a[1] = pPager->nPage;
  a[2] = pPager->mxPage;
  a[3] = pPager->dbSize;
  a[4] = pPager->state;
  a[5] = pPager->errCode;
#ifdef SQLITE_TEST
  a[6] = pPager->nHit;
  a[7] = pPager->nMiss;
  a[8] = pPager->nOvfl;
  a[9] = pPager->nRead;
  a[10] = pPager->nWrite;
#endif
  return a;
}

Here is the caller graph for this function:

Definition at line 3481 of file pager.c.

                                          {
  int rc;
  char zTemp[SQLITE_TEMPNAME_SIZE];
  assert( !pPager->stmtInUse );
  assert( pPager->dbSize>=0 );
  TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
  if( MEMDB ){
    pPager->stmtInUse = 1;
    pPager->stmtSize = pPager->dbSize;
    return SQLITE_OK;
  }
  if( !pPager->journalOpen ){
    pPager->stmtAutoopen = 1;
    return SQLITE_OK;
  }
  assert( pPager->journalOpen );
  pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 );
  if( pPager->aInStmt==0 ){
    /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
    return SQLITE_NOMEM;
  }
#ifndef NDEBUG
  rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize);
  if( rc ) goto stmt_begin_failed;
  assert( pPager->stmtJSize == pPager->journalOff );
#endif
  pPager->stmtJSize = pPager->journalOff;
  pPager->stmtSize = pPager->dbSize;
  pPager->stmtHdrOff = 0;
  pPager->stmtCksum = pPager->cksumInit;
  if( !pPager->stmtOpen ){
    rc = sqlite3pager_opentemp(zTemp, &pPager->stfd);
    if( rc ) goto stmt_begin_failed;
    pPager->stmtOpen = 1;
    pPager->stmtNRec = 0;
  }
  pPager->stmtInUse = 1;
  return SQLITE_OK;
 
stmt_begin_failed:
  if( pPager->aInStmt ){
    sqliteFree(pPager->aInStmt);
    pPager->aInStmt = 0;
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3531 of file pager.c.

                                           {
  if( pPager->stmtInUse ){
    PgHdr *pPg, *pNext;
    TRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
    if( !MEMDB ){
      sqlite3OsSeek(pPager->stfd, 0);
      /* sqlite3OsTruncate(pPager->stfd, 0); */
      sqliteFree( pPager->aInStmt );
      pPager->aInStmt = 0;
    }
    for(pPg=pPager->pStmt; pPg; pPg=pNext){
      pNext = pPg->pNextStmt;
      assert( pPg->inStmt );
      pPg->inStmt = 0;
      pPg->pPrevStmt = pPg->pNextStmt = 0;
      if( MEMDB ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        sqliteFree(pHist->pStmt);
        pHist->pStmt = 0;
      }
    }
    pPager->stmtNRec = 0;
    pPager->stmtInUse = 0;
    pPager->pStmt = 0;
  }
  pPager->stmtAutoopen = 0;
  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3563 of file pager.c.

                                             {
  int rc;
  if( pPager->stmtInUse ){
    TRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
    if( MEMDB ){
      PgHdr *pPg;
      for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        if( pHist->pStmt ){
          memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
          sqliteFree(pHist->pStmt);
          pHist->pStmt = 0;
        }
      }
      pPager->dbSize = pPager->stmtSize;
      memoryTruncate(pPager);
      rc = SQLITE_OK;
    }else{
      rc = pager_stmt_playback(pPager);
    }
    sqlite3pager_stmt_commit(pPager);
  }else{
    rc = SQLITE_OK;
  }
  pPager->stmtAutoopen = 0;
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sqlite3pager_sync ( Pager ,
const char *  zMaster,
Pgno   
)

Definition at line 3678 of file pager.c.

                                                                      {
  int rc = SQLITE_OK;

  TRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", 
      pPager->zFilename, zMaster, nTrunc);

  /* If this is an in-memory db, or no pages have been written to, or this
  ** function has already been called, it is a no-op.
  */
  if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
    PgHdr *pPg;
    assert( pPager->journalOpen );

    /* If a master journal file name has already been written to the
    ** journal file, then no sync is required. This happens when it is
    ** written, then the process fails to upgrade from a RESERVED to an
    ** EXCLUSIVE lock. The next time the process tries to commit the
    ** transaction the m-j name will have already been written.
    */
    if( !pPager->setMaster ){
      rc = pager_incr_changecounter(pPager);
      if( rc!=SQLITE_OK ) goto sync_exit;
#ifndef SQLITE_OMIT_AUTOVACUUM
      if( nTrunc!=0 ){
        /* If this transaction has made the database smaller, then all pages
        ** being discarded by the truncation must be written to the journal
        ** file.
        */
        Pgno i;
        void *pPage;
        int iSkip = PAGER_MJ_PGNO(pPager);
        for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
          if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){
            rc = sqlite3pager_get(pPager, i, &pPage);
            if( rc!=SQLITE_OK ) goto sync_exit;
            rc = sqlite3pager_write(pPage);
            sqlite3pager_unref(pPage);
            if( rc!=SQLITE_OK ) goto sync_exit;
          }
        } 
      }
#endif
      rc = writeMasterJournal(pPager, zMaster);
      if( rc!=SQLITE_OK ) goto sync_exit;
      rc = syncJournal(pPager);
      if( rc!=SQLITE_OK ) goto sync_exit;
    }

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( nTrunc!=0 ){
      rc = sqlite3pager_truncate(pPager, nTrunc);
      if( rc!=SQLITE_OK ) goto sync_exit;
    }
#endif

    /* Write all dirty pages to the database file */
    pPg = pager_get_all_dirty_pages(pPager);
    rc = pager_write_pagelist(pPg);
    if( rc!=SQLITE_OK ) goto sync_exit;

    /* Sync the database file. */
    if( !pPager->noSync ){
      rc = sqlite3OsSync(pPager->fd, 0);
    }

    pPager->state = PAGER_SYNCED;
  }else if( MEMDB && nTrunc!=0 ){
    rc = sqlite3pager_truncate(pPager, nTrunc);
  }

sync_exit:
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1973 of file pager.c.

                                                    {
  int rc;
  sqlite3pager_pagecount(pPager);
  if( pPager->errCode ){
    rc = pPager->errCode;
    return rc;
  }
  if( nPage>=(unsigned)pPager->dbSize ){
    return SQLITE_OK;
  }
  if( MEMDB ){
    pPager->dbSize = nPage;
    memoryTruncate(pPager);
    return SQLITE_OK;
  }
  rc = syncJournal(pPager);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* Get an exclusive lock on the database before truncating. */
  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  rc = pager_truncate(pPager, nPage);
  if( rc==SQLITE_OK ){
    pPager->dbSize = nPage;
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2808 of file pager.c.

                                   {
  PgHdr *pPg;

  /* Decrement the reference count for this page
  */
  pPg = DATA_TO_PGHDR(pData);
  assert( pPg->nRef>0 );
  pPg->nRef--;
  REFINFO(pPg);

  CHECK_PAGE(pPg);

  /* When the number of references to a page reach 0, call the
  ** destructor and add the page to the freelist.
  */
  if( pPg->nRef==0 ){
    Pager *pPager;
    pPager = pPg->pPager;
    pPg->pNextFree = 0;
    pPg->pPrevFree = pPager->pLast;
    pPager->pLast = pPg;
    if( pPg->pPrevFree ){
      pPg->pPrevFree->pNextFree = pPg;
    }else{
      pPager->pFirst = pPg;
    }
    if( pPg->needSync==0 && pPager->pFirstSynced==0 ){
      pPager->pFirstSynced = pPg;
    }
    if( pPager->xDestructor ){
      pPager->xDestructor(pData, pPager->pageSize);
    }
  
    /* When all pages reach the freelist, drop the read lock from
    ** the database file.
    */
    pPager->nRef--;
    assert( pPager->nRef>=0 );
    if( pPager->nRef==0 && !MEMDB ){
      pager_reset(pPager);
    }
  }
  return SQLITE_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3037 of file pager.c.

                                   {
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  Pager *pPager = pPg->pPager;
  int rc = SQLITE_OK;

  /* Check for errors
  */
  if( pPager->errCode ){ 
    return pPager->errCode;
  }
  if( pPager->readOnly ){
    return SQLITE_PERM;
  }

  assert( !pPager->setMaster );

  CHECK_PAGE(pPg);

  /* Mark the page as dirty.  If the page has already been written
  ** to the journal then we can return right away.
  */
  makeDirty(pPg);
  if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
    pPager->dirtyCache = 1;
  }else{

    /* If we get this far, it means that the page needs to be
    ** written to the transaction journal or the ckeckpoint journal
    ** or both.
    **
    ** First check to see that the transaction journal exists and
    ** create it if it does not.
    */
    assert( pPager->state!=PAGER_UNLOCK );
    rc = sqlite3pager_begin(pData, 0);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    assert( pPager->state>=PAGER_RESERVED );
    if( !pPager->journalOpen && pPager->useJournal ){
      rc = pager_open_journal(pPager);
      if( rc!=SQLITE_OK ) return rc;
    }
    assert( pPager->journalOpen || !pPager->useJournal );
    pPager->dirtyCache = 1;
  
    /* The transaction journal now exists and we have a RESERVED or an
    ** EXCLUSIVE lock on the main database file.  Write the current page to
    ** the transaction journal if it is not there already.
    */
    if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){
      if( (int)pPg->pgno <= pPager->origDbSize ){
        int szPg;
        if( MEMDB ){
          PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
          TRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
          assert( pHist->pOrig==0 );
          pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
          if( pHist->pOrig ){
            memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
          }
        }else{
          u32 cksum, saved;
          char *pData2, *pEnd;
          /* We should never write to the journal file the page that
          ** contains the database locks.  The following assert verifies
          ** that we do not. */
          assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
          pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
          cksum = pager_cksum(pPager, (u8*)pData2);
          pEnd = pData2 + pPager->pageSize;
          pData2 -= 4;
          saved = *(u32*)pEnd;
          put32bits(pEnd, cksum);
          szPg = pPager->pageSize+8;
          put32bits(pData2, pPg->pgno);
          rc = sqlite3OsWrite(pPager->jfd, pData2, szPg);
          pPager->journalOff += szPg;
          TRACE4("JOURNAL %d page %d needSync=%d\n",
                  PAGERID(pPager), pPg->pgno, pPg->needSync);
          *(u32*)pEnd = saved;

         /* An error has occured writing to the journal file. The 
          ** transaction will be rolled back by the layer above.
          */
          if( rc!=SQLITE_OK ){
            return rc;
          }

          pPager->nRec++;
          assert( pPager->aInJournal!=0 );
          pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
          pPg->needSync = !pPager->noSync;
          if( pPager->stmtInUse ){
            pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
            page_add_to_stmt_list(pPg);
          }
        }
      }else{
        pPg->needSync = !pPager->journalStarted && !pPager->noSync;
        TRACE4("APPEND %d page %d needSync=%d\n",
                PAGERID(pPager), pPg->pgno, pPg->needSync);
      }
      if( pPg->needSync ){
        pPager->needSync = 1;
      }
      pPg->inJournal = 1;
    }
  
    /* If the statement journal is open and the page is not in it,
    ** then write the current page to the statement journal.  Note that
    ** the statement journal format differs from the standard journal format
    ** in that it omits the checksums and the header.
    */
    if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
      assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
      if( MEMDB ){
        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
        assert( pHist->pStmt==0 );
        pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
        if( pHist->pStmt ){
          memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
        }
        TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
      }else{
        char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4;
        put32bits(pData2, pPg->pgno);
        rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4);
        TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        pPager->stmtNRec++;
        assert( pPager->aInStmt!=0 );
        pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
      }
      page_add_to_stmt_list(pPg);
    }
  }

  /* Update the database size and return.
  */
  if( pPager->dbSize<(int)pPg->pgno ){
    pPager->dbSize = pPg->pgno;
    if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
      pPager->dbSize++;
    }
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function: