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

📄 pager.c

📁 sqlite嵌入式数据库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  }else{    pPager->mxPage = 10;  }}/*** Adjust the robustness of the database to damage due to OS crashes** or power failures by changing the number of syncs()s when writing** the rollback journal.  There are three levels:****    OFF       sqlite3OsSync() is never called.  This is the default**              for temporary and transient files.****    NORMAL    The journal is synced once before writes begin on the**              database.  This is normally adequate protection, but**              it is theoretically possible, though very unlikely,**              that an inopertune power failure could leave the journal**              in a state which would cause damage to the database**              when it is rolled back.****    FULL      The journal is synced twice before writes begin on the**              database (with some additional information - the nRec field**              of the journal header - being written in between the two**              syncs).  If we assume that writing a**              single disk sector is atomic, then this mode provides**              assurance that the journal will not be corrupted to the**              point of causing damage to the database during rollback.**** Numeric values associated with these states are OFF==1, NORMAL=2,** and FULL=3.*/#ifndef SQLITE_OMIT_PAGER_PRAGMASvoid sqlite3pager_set_safety_level(Pager *pPager, int level, int full_fsync){  pPager->noSync =  level==1 || pPager->tempFile;  pPager->fullSync = level==3 && !pPager->tempFile;  pPager->full_fsync = full_fsync;  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.  */#ifdef SQLITE_TESTint sqlite3_opentemp_count = 0;#endif/*** 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 **pFd){  int cnt = 8;  int rc;#ifdef SQLITE_TEST  sqlite3_opentemp_count++;  /* Used for testing and analysis only */#endif  do{    cnt--;    sqlite3OsTempFileName(zFile);    rc = sqlite3OsOpenExclusive(zFile, pFd, 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 = 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;}/*** 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;}/*** The following set of routines are used to disable the simulated** I/O error mechanism.  These routines are used to avoid simulated** errors in places where we do not care about errors.**** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops** and generate no code.*/#ifdef SQLITE_TESTextern int sqlite3_io_error_pending;extern int sqlite3_io_error_hit;static int saved_cnt;void clear_simulated_io_error(){  sqlite3_io_error_hit = 0;}void disable_simulated_io_errors(void){  saved_cnt = sqlite3_io_error_pending;  sqlite3_io_error_pending = -1;}void enable_simulated_io_errors(void){  sqlite3_io_error_pending = saved_cnt;}#else# define clear_simulated_io_error()# define disable_simulated_io_errors()# define enable_simulated_io_errors()#endif/*** Read the first N bytes from the beginning of the file into memory** that pDest points to. **** No error checking is done. The rational for this is that this function ** may be called even if the file does not exist or contain a header. In ** these cases sqlite3OsRead() will return an error, to which the correct ** response is to zero the memory at pDest and continue.  A real IO error ** will presumably recur and be picked up later (Todo: Think about this).*/void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){  memset(pDest, 0, N);  if( MEMDB==0 ){    disable_simulated_io_errors();    sqlite3OsSeek(pPager->fd, 0);    sqlite3OsRead(pPager->fd, pDest, N);    enable_simulated_io_errors();  }}/*** Return the total number of pages in the disk file associated with** pPager. **** If the PENDING_BYTE lies on the page directly after the end of the** file, then consider this page part of the file too. For example, if** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the** file is 4096 bytes, 5 is returned instead of 4.*/int sqlite3pager_pagecount(Pager *pPager){  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;}#ifndef SQLITE_OMIT_MEMORYDB/*** Clear a PgHistory block*/static void clearHistory(PgHistory *pHist){  sqliteFree(pHist->pOrig);  sqliteFree(pHist->pStmt);  pHist->pOrig = 0;  pHist->pStmt = 0;}#else#define clearHistory(x)#endif/*** 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 h

⌨️ 快捷键说明

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