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

📄 pager.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  if( pPager->noSync ) pPager->needSync = 0;}#endif/*** The following global variable is incremented whenever the library** attempts to open a temporary file.  This information is used for** testing and analysis only.  */int sqlite3_opentemp_count = 0;/*** Open a temporary file.  Write the name of the file into zFile** (zFile must be at least SQLITE_TEMPNAME_SIZE bytes long.)  Write** the file descriptor into *fd.  Return SQLITE_OK on success or some** other error code if we fail.**** The OS will automatically delete the temporary file when it is** closed.*/static int sqlite3pager_opentemp(char *zFile, OsFile *fd){  int cnt = 8;  int rc;  sqlite3_opentemp_count++;  /* Used for testing and analysis only */  do{    cnt--;    sqlite3OsTempFileName(zFile);    rc = sqlite3OsOpenExclusive(zFile, fd, 1);  }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM );  return rc;}/*** Create a new page cache and put a pointer to the page cache in *ppPager.** The file to be cached need not exist.  The file is not locked until** the first call to sqlite3pager_get() and is only held open until the** last page is released using sqlite3pager_unref().**** If zFilename is NULL then a randomly-named temporary file is created** and used as the file to be cached.  The file will be deleted** automatically when it is closed.**** If zFilename is ":memory:" then all information is held in cache.** It is never written to disk.  This can be used to implement an** in-memory database.*/int sqlite3pager_open(  Pager **ppPager,         /* Return the Pager structure here */  const char *zFilename,   /* Name of the database file to open */  int nExtra,              /* Extra bytes append to each in-memory page */  int flags                /* flags controlling this file */){  Pager *pPager;  char *zFullPathname = 0;  int nameLen;  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];  *ppPager = 0;  memset(&fd, 0, sizeof(fd));  if( sqlite3_malloc_failed ){    return SQLITE_NOMEM;  }  if( zFilename && zFilename[0] ){#ifndef SQLITE_OMIT_MEMORYDB    if( strcmp(zFilename,":memory:")==0 ){      memDb = 1;      zFullPathname = sqliteStrDup("");      rc = SQLITE_OK;    }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;    }  }  if( !zFullPathname ){    sqlite3OsClose(&fd);    return SQLITE_NOMEM;  }  if( rc!=SQLITE_OK ){    sqlite3OsClose(&fd);    sqliteFree(zFullPathname);    return rc;  }  nameLen = strlen(zFullPathname);  pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );  if( pPager==0 ){    sqlite3OsClose(&fd);    sqliteFree(zFullPathname);    return SQLITE_NOMEM;  }  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;#if OS_UNIX  pPager->fd.pPager = pPager;#endif  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;  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;  return SQLITE_OK;}/*** Set the busy handler function.*/void sqlite3pager_set_busyhandler(Pager *pPager, BusyHandler *pBusyHandler){  pPager->pBusyHandler = pBusyHandler;}/*** Set the destructor for this pager.  If not NULL, the destructor is called** when the reference count on each page reaches zero.  The destructor can** be used to clean up information in the extra segment appended to each page.**** The destructor is not called as a result sqlite3pager_close().  ** Destructors are only called by sqlite3pager_unref().*/void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*,int)){  pPager->xDestructor = xDesc;}/*** Set the reinitializer for this pager.  If not NULL, the reinitializer** is called when the content of a page in cache is restored to its original** value as a result of a rollback.  The callback gives higher-level code** an opportunity to restore the EXTRA section to agree with the restored** page data.*/void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){  pPager->xReiniter = xReinit;}/*** Set the page size.  Return the new size.  If the suggest new page** size is inappropriate, then an alternative page size is selected** and returned.*/int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){  assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );  if( !pPager->memDb ){    pPager->pageSize = pageSize;  }  return pPager->pageSize;}/*** Read the first N bytes from the beginning of the file into memory** that pDest points to.  No error checking is done.*/void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){  memset(pDest, 0, N);  if( MEMDB==0 ){    sqlite3OsSeek(&pPager->fd, 0);    sqlite3OsRead(&pPager->fd, pDest, N);  }}/*** Return the total number of pages in the disk file associated with** pPager.*/int sqlite3pager_pagecount(Pager *pPager){  i64 n;  assert( pPager!=0 );  if( pPager->dbSize>=0 ){    return pPager->dbSize;  }  if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){    pPager->errMask |= PAGER_ERR_DISK;    return 0;  }  n /= pPager->pageSize;  if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){    n++;  }  if( pPager->state!=PAGER_UNLOCK ){    pPager->dbSize = n;  }  return n;}/*** Forward declaration*/static int syncJournal(Pager*);/*** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate** that the page is not part of any hash chain. This is required because the** sqlite3pager_movepage() routine can leave a page in the ** pNextFree/pPrevFree list that is not a part of any hash-chain.*/static void unlinkHashChain(Pager *pPager, PgHdr *pPg){  if( pPg->pgno==0 ){    /* If the page number is zero, then this page is not in any hash chain. */    return;  }  if( pPg->pNextHash ){    pPg->pNextHash->pPrevHash = pPg->pPrevHash;  }  if( pPg->pPrevHash ){    assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );    pPg->pPrevHash->pNextHash = pPg->pNextHash;  }else{    int h = pager_hash(pPg->pgno);    assert( pPager->aHash[h]==pPg );    pPager->aHash[h] = pPg->pNextHash;  }  pPg->pgno = 0;  pPg->pNextHash = pPg->pPrevHash = 0;}/*** Unlink a page from the free list (the list of all pages where nRef==0)** and from its hash collision chain.*/static void unlinkPage(PgHdr *pPg){  Pager *pPager = pPg->pPager;  /* Keep the pFirstSynced pointer pointing at the first synchronized page */  if( pPg==pPager->pFirstSynced ){    PgHdr *p = pPg->pNextFree;    while( p && p->needSync ){ p = p->pNextFree; }    pPager->pFirstSynced = p;  }  /* Unlink from the freelist */  if( pPg->pPrevFree ){    pPg->pPrevFree->pNextFree = pPg->pNextFree;  }else{    assert( pPager->pFirst==pPg );    pPager->pFirst = pPg->pNextFree;  }  if( pPg->pNextFree ){    pPg->pNextFree->pPrevFree = pPg->pPrevFree;  }else{    assert( pPager->pLast==pPg );    pPager->pLast = pPg->pPrevFree;  }  pPg->pNextFree = pPg->pPrevFree = 0;  /* Unlink from the pgno hash table */  unlinkHashChain(pPager, pPg);}#ifndef SQLITE_OMIT_MEMORYDB/*** This routine is used to truncate an in-memory database.  Delete** all pages whose pgno is larger than pPager->dbSize and is unreferenced.** Referenced pages larger than pPager->dbSize are zeroed.*/static void memoryTruncate(Pager *pPager){  PgHdr *pPg;  PgHdr **ppPg;  int dbSize = pPager->dbSize;  ppPg = &pPager->pAll;  while( (pPg = *ppPg)!=0 ){    if( pPg->pgno<=dbSize ){      ppPg = &pPg->pNextAll;    }else if( pPg->nRef>0 ){      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);      ppPg = &pPg->pNextAll;    }else{      *ppPg = pPg->pNextAll;      unlinkPage(pPg);      sqliteFree(pPg);      pPager->nPage--;    }  }}#else#define memoryTruncate(p)#endif/*** Try to obtain a lock on a file.  Invoke the busy callback if the lock** is currently not available.  Repeate until the busy callback returns** false or until the lock succeeds.**** Return SQLITE_OK on success and an error code if we cannot obtain** the lock.*/static int pager_wait_on_lock(Pager *pPager, int locktype){  int rc;  assert( PAGER_SHARED==SHARED_LOCK );  assert( PAGER_RESERVED==RESERVED_LOCK );  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );  if( pPager->state>=locktype ){    rc = SQLITE_OK;  }else{    int busy = 1;    BusyHandler *pH;    do {      rc = sqlite3OsLock(&pPager->fd, locktype);    }while( rc==SQLITE_BUSY &&         (pH = pPager->pBusyHandler)!=0 &&         pH->xFunc && pH->xFunc(pH->pArg, busy++)    );    if( rc==SQLITE_OK ){      pPager->state = locktype;    }  }  return rc;}/*** Truncate the file to the number of pages specified.*/int sqlite3pager_truncate(Pager *pPager, Pgno nPage){  int rc;  sqlite3pager_pagecount(pPager);  if( pPager->errMask!=0 ){    rc = pager_errcode(pPager);    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 ){    

⌨️ 快捷键说明

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