📄 pager.c
字号:
}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 + -