?? btree.c
字號:
){ int rc; if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } rc = getPage(pBt, pgno, ppPage); if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = initPage(*ppPage, pParent); } return rc;}/*** Release a MemPage. This should be called once for each prior** call to getPage.*/static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); sqlite3pager_unref(pPage->aData); }}/*** This routine is called when the reference count for a page** reaches zero. We need to unref the pParent pointer when that** happens.*/static void pageDestructor(void *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage*)&((char*)pData)[pageSize]; if( pPage->pParent ){ MemPage *pParent = pPage->pParent; pPage->pParent = 0; releasePage(pParent); } pPage->isInit = 0;}/*** During a rollback, when the pager reloads information into the cache** so that the cache is restored to its original state at the start of** the transaction, for each page restored this routine is called.**** This routine needs to reset the extra data section at the end of the** page to agree with the restored data.*/static void pageReinit(void *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage*)&((char*)pData)[pageSize]; if( pPage->isInit ){ pPage->isInit = 0; initPage(pPage, pPage->pParent); }}/*** Open a database file.** ** zFilename is the name of the database file. If zFilename is NULL** a new database with a random name is created. This randomly named** database file will be deleted when sqlite3BtreeClose() is called.*/int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ sqlite3 *pSqlite, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags /* Options */){ BtShared *pBt; /* Shared part of btree structure */ Btree *p; /* Handle to return */ int rc; int nReserve; unsigned char zDbHeader[100];#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) const ThreadData *pTsdro;#endif /* Set the variable isMemdb to true for an in-memory database, or ** false for a file-based database. This symbol is only required if ** either of the shared-data or autovacuum features are compiled ** into the library. */#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) #ifdef SQLITE_OMIT_MEMORYDB const int isMemdb = !zFilename; #else const int isMemdb = !zFilename || (strcmp(zFilename, ":memory:")?0:1); #endif#endif p = sqliteMalloc(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; } p->inTrans = TRANS_NONE; p->pSqlite = pSqlite; /* Try to find an existing Btree structure opened on zFilename. */#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) pTsdro = sqlite3ThreadDataReadOnly(); if( pTsdro->useSharedData && zFilename && !isMemdb ){ char *zFullPathname = sqlite3OsFullPathname(zFilename); if( !zFullPathname ){ sqliteFree(p); return SQLITE_NOMEM; } for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){ p->pBt = pBt; *ppBtree = p; pBt->nRef++; sqliteFree(zFullPathname); return SQLITE_OK; } } sqliteFree(zFullPathname); }#endif /* ** The following asserts make sure that structures used by the btree are ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ assert( sizeof(i64)==8 || sizeof(i64)==4 ); assert( sizeof(u64)==8 || sizeof(u64)==4 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); pBt = sqliteMalloc( sizeof(*pBt) ); if( pBt==0 ){ *ppBtree = 0; sqliteFree(p); return SQLITE_NOMEM; } rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlite3pager_close(pBt->pPager); sqliteFree(pBt); sqliteFree(p); *ppBtree = 0; return rc; } p->pBt = pBt; sqlite3pager_set_destructor(pBt->pPager, pageDestructor); sqlite3pager_set_reiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; pBt->pPage1 = 0; pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager); sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader); pBt->pageSize = get2byte(&zDbHeader[16]); if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE; pBt->maxEmbedFrac = 64; /* 25% */ pBt->minEmbedFrac = 32; /* 12.5% */ pBt->minLeafFrac = 32; /* 12.5% */#ifndef SQLITE_OMIT_AUTOVACUUM /* If the magic name ":memory:" will create an in-memory database, then ** do not set the auto-vacuum flag, even if SQLITE_DEFAULT_AUTOVACUUM ** is true. On the other hand, if SQLITE_OMIT_MEMORYDB has been defined, ** then ":memory:" is just a regular file-name. Respect the auto-vacuum ** default in this case. */ if( zFilename && !isMemdb ){ pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM; }#endif nReserve = 0; }else{ nReserve = zDbHeader[20]; pBt->maxEmbedFrac = zDbHeader[21]; pBt->minEmbedFrac = zDbHeader[22]; pBt->minLeafFrac = zDbHeader[23]; pBt->pageSizeFixed = 1;#ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);#endif } pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize);#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* Add the new btree to the linked list starting at ThreadData.pBtree. ** There is no chance that a malloc() may fail inside of the ** sqlite3ThreadData() call, as the ThreadData structure must have already ** been allocated for pTsdro->useSharedData to be non-zero. */ if( pTsdro->useSharedData && zFilename && !isMemdb ){ pBt->pNext = pTsdro->pBtree; sqlite3ThreadData()->pBtree = pBt; }#endif pBt->nRef = 1; *ppBtree = p; return SQLITE_OK;}/*** Close an open database and invalidate all cursors.*/int sqlite3BtreeClose(Btree *p){ BtShared *pBt = p->pBt; BtCursor *pCur;#ifndef SQLITE_OMIT_SHARED_CACHE ThreadData *pTsd;#endif /* Close all cursors opened via this handle. */ pCur = pBt->pCursor; while( pCur ){ BtCursor *pTmp = pCur; pCur = pCur->pNext; if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); } } /* Rollback any active transaction and free the handle structure. ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ sqlite3BtreeRollback(p); sqliteFree(p);#ifndef SQLITE_OMIT_SHARED_CACHE /* If there are still other outstanding references to the shared-btree ** structure, return now. The remainder of this procedure cleans ** up the shared-btree. */ assert( pBt->nRef>0 ); pBt->nRef--; if( pBt->nRef ){ return SQLITE_OK; } /* Remove the shared-btree from the thread wide list. Call ** ThreadDataReadOnly() and then cast away the const property of the ** pointer to avoid allocating thread data if it is not really required. */ pTsd = (ThreadData *)sqlite3ThreadDataReadOnly(); if( pTsd->pBtree==pBt ){ assert( pTsd==sqlite3ThreadData() ); pTsd->pBtree = pBt->pNext; }else{ BtShared *pPrev; for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext){} if( pPrev ){ assert( pTsd==sqlite3ThreadData() ); pPrev->pNext = pBt->pNext; } }#endif /* Close the pager and free the shared-btree structure */ assert( !pBt->pCursor ); sqlite3pager_close(pBt->pPager); if( pBt->xFreeSchema && pBt->pSchema ){ pBt->xFreeSchema(pBt->pSchema); } sqliteFree(pBt->pSchema); sqliteFree(pBt); return SQLITE_OK;}/*** Change the busy handler callback function.*/int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ BtShared *pBt = p->pBt; pBt->pBusyHandler = pHandler; sqlite3pager_set_busyhandler(pBt->pPager, pHandler); return SQLITE_OK;}/*** Change the limit on the number of pages allowed in the cache.**** The maximum number of cache pages is set to the absolute** value of mxPage. If mxPage is negative, the pager will** operate asynchronously - it will not stop to do fsync()s** to insure data is written to the disk surface before** continuing. Transactions still work if synchronous is off,** and the database cannot be corrupted if this program** crashes. But if the operating system crashes or there is** an abrupt power failure when synchronous is off, the database** could be left in an inconsistent and unrecoverable state.** Synchronous is on by default so database corruption is not** normally a worry.*/int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; sqlite3pager_set_cachesize(pBt->pPager, mxPage); return SQLITE_OK;}/*** Change the way data is synced to disk in order to increase or decrease** how well the database resists damage due to OS crashes and power** failures. Level 1 is the same as asynchronous (no syncs() occur and** there is a high probability of damage) Level 2 is the default. There** is a very low but non-zero probability of damage. Level 3 reduces the** probability of damage to near zero but with a write performance reduction.*/#ifndef SQLITE_OMIT_PAGER_PRAGMASint sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; sqlite3pager_set_safety_level(pBt->pPager, level, fullSync); return SQLITE_OK;}#endif/*** Return TRUE if the given btree is set to safety level 1. In other** words, return TRUE if no sync() occurs on the disk files.*/int sqlite3BtreeSyncDisabled(Btree *p){ BtShared *pBt = p->pBt; assert( pBt && pBt->pPager ); return sqlite3pager_nosync(pBt->pPager);}#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)/*** Change the default pages size and the number of reserved bytes per page.**** The page size must be a power of 2 between 512 and 65536. If the page** size supplied does not meet this constraint then the page size is not** changed.**** Page sizes are constrained to be a power of two so that the region** of the database file used for locking (beginning at PENDING_BYTE,** the first byte past the 1GB boundary, 0x40000000) needs to occur** at the beginning of a page.**** If parameter nReserve is less than zero, then the number of reserved** bytes per page is left unchanged.*/int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ BtShared *pBt = p->pBt; if( pBt->pageSizeFixed ){ return SQLITE_READONLY; } if( nReserve<0 ){ nReserve = pBt->pageSize - pBt->usableSize; } if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; return SQLITE_OK;}/*** Return the currently defined page size*/int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize;}int sqlite3BtreeGetReserve(Btree *p){ return p->pBt->p
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -