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

📄 btree.c

📁 sqlite最新源码
💻 C
📖 第 1 页 / 共 5 页
字号:
** 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;  int rc;  assert( sqlite3_mutex_held(p->db->mutex) );    sqlite3BtreeEnter(p);  assert( pBt && pBt->pPager );  rc = sqlite3PagerNosync(pBt->pPager);  sqlite3BtreeLeave(p);  return rc;}#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){  int rc = SQLITE_OK;  BtShared *pBt = p->pBt;  assert( nReserve>=-1 && nReserve<=255 );  sqlite3BtreeEnter(p);  if( pBt->pageSizeFixed ){    sqlite3BtreeLeave(p);    return SQLITE_READONLY;  }  if( nReserve<0 ){    nReserve = pBt->pageSize - pBt->usableSize;  }  assert( nReserve>=0 && nReserve<=255 );  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&        ((pageSize-1)&pageSize)==0 ){    assert( (pageSize & 7)==0 );    assert( !pBt->pPage1 && !pBt->pCursor );    pBt->pageSize = (u16)pageSize;    freeTempSpace(pBt);    rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);  }  pBt->usableSize = pBt->pageSize - (u16)nReserve;  sqlite3BtreeLeave(p);  return rc;}/*** Return the currently defined page size*/int sqlite3BtreeGetPageSize(Btree *p){  return p->pBt->pageSize;}int sqlite3BtreeGetReserve(Btree *p){  int n;  sqlite3BtreeEnter(p);  n = p->pBt->pageSize - p->pBt->usableSize;  sqlite3BtreeLeave(p);  return n;}/*** Set the maximum page count for a database if mxPage is positive.** No changes are made if mxPage is 0 or negative.** Regardless of the value of mxPage, return the maximum page count.*/int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){  int n;  sqlite3BtreeEnter(p);  n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);  sqlite3BtreeLeave(p);  return n;}#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) *//*** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it** is disabled. The default value for the auto-vacuum property is ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.*/int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){#ifdef SQLITE_OMIT_AUTOVACUUM  return SQLITE_READONLY;#else  BtShared *pBt = p->pBt;  int rc = SQLITE_OK;  u8 av = autoVacuum ?1:0;  sqlite3BtreeEnter(p);  if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){    rc = SQLITE_READONLY;  }else{    pBt->autoVacuum = av;  }  sqlite3BtreeLeave(p);  return rc;#endif}/*** Return the value of the 'auto-vacuum' property. If auto-vacuum is ** enabled 1 is returned. Otherwise 0.*/int sqlite3BtreeGetAutoVacuum(Btree *p){#ifdef SQLITE_OMIT_AUTOVACUUM  return BTREE_AUTOVACUUM_NONE;#else  int rc;  sqlite3BtreeEnter(p);  rc = (    (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE:    (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL:    BTREE_AUTOVACUUM_INCR  );  sqlite3BtreeLeave(p);  return rc;#endif}/*** Get a reference to pPage1 of the database file.  This will** also acquire a readlock on that file.**** SQLITE_OK is returned on success.  If the file is not a** well-formed database file, then SQLITE_CORRUPT is returned.** SQLITE_BUSY is returned if the database is locked.  SQLITE_NOMEM** is returned if we run out of memory. */static int lockBtree(BtShared *pBt){  int rc;  MemPage *pPage1;  int nPage;  assert( sqlite3_mutex_held(pBt->mutex) );  if( pBt->pPage1 ) return SQLITE_OK;  rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);  if( rc!=SQLITE_OK ) return rc;  /* Do some checking to help insure the file we opened really is  ** a valid database file.   */  rc = sqlite3PagerPagecount(pBt->pPager, &nPage);  if( rc!=SQLITE_OK ){    goto page1_init_failed;  }else if( nPage>0 ){    int pageSize;    int usableSize;    u8 *page1 = pPage1->aData;    rc = SQLITE_NOTADB;    if( memcmp(page1, zMagicHeader, 16)!=0 ){      goto page1_init_failed;    }    if( page1[18]>1 ){      pBt->readOnly = 1;    }    if( page1[19]>1 ){      goto page1_init_failed;    }    /* The maximum embedded fraction must be exactly 25%.  And the minimum    ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data.    ** The original design allowed these amounts to vary, but as of    ** version 3.6.0, we require them to be fixed.    */    if( memcmp(&page1[21], "\100\040\040",3)!=0 ){      goto page1_init_failed;    }    pageSize = get2byte(&page1[16]);    if( ((pageSize-1)&pageSize)!=0 || pageSize<512 ||        (SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE)    ){      goto page1_init_failed;    }    assert( (pageSize & 7)==0 );    usableSize = pageSize - page1[20];    if( pageSize!=pBt->pageSize ){      /* After reading the first page of the database assuming a page size      ** of BtShared.pageSize, we have discovered that the page-size is      ** actually pageSize. Unlock the database, leave pBt->pPage1 at      ** zero and return SQLITE_OK. The caller will call this function      ** again with the correct page-size.      */      releasePage(pPage1);      pBt->usableSize = (u16)usableSize;      pBt->pageSize = (u16)pageSize;      freeTempSpace(pBt);      sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);      return SQLITE_OK;    }    if( usableSize<500 ){      goto page1_init_failed;    }    pBt->pageSize = (u16)pageSize;    pBt->usableSize = (u16)usableSize;#ifndef SQLITE_OMIT_AUTOVACUUM    pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);    pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);#endif  }  /* maxLocal is the maximum amount of payload to store locally for  ** a cell.  Make sure it is small enough so that at least minFanout  ** cells can will fit on one page.  We assume a 10-byte page header.  ** Besides the payload, the cell must store:  **     2-byte pointer to the cell  **     4-byte child pointer  **     9-byte nKey value  **     4-byte nData value  **     4-byte overflow page pointer  ** So a cell consists of a 2-byte poiner, a header which is as much as  ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow  ** page pointer.  */  pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23;  pBt->minLocal = (pBt->usableSize-12)*32/255 - 23;  pBt->maxLeaf = pBt->usableSize - 35;  pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );  pBt->pPage1 = pPage1;  return SQLITE_OK;page1_init_failed:  releasePage(pPage1);  pBt->pPage1 = 0;  return rc;}/*** This routine works like lockBtree() except that it also invokes the** busy callback if there is lock contention.*/static int lockBtreeWithRetry(Btree *pRef){  int rc = SQLITE_OK;  assert( sqlite3BtreeHoldsMutex(pRef) );  if( pRef->inTrans==TRANS_NONE ){    u8 inTransaction = pRef->pBt->inTransaction;    btreeIntegrity(pRef);    rc = sqlite3BtreeBeginTrans(pRef, 0);    pRef->pBt->inTransaction = inTransaction;    pRef->inTrans = TRANS_NONE;    if( rc==SQLITE_OK ){      pRef->pBt->nTransaction--;    }    btreeIntegrity(pRef);  }  return rc;}       /*** If there are no outstanding cursors and we are not in the middle** of a transaction but there is a read lock on the database, then** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock.**** If there are any outstanding cursors, this routine is a no-op.**** If there is a transaction in progress, this routine is a no-op.*/static void unlockBtreeIfUnused(BtShared *pBt){  assert( sqlite3_mutex_held(pBt->mutex) );  if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){    if( sqlite3PagerRefcount(pBt->pPager)>=1 ){      assert( pBt->pPage1->aData );#if 0      if( pBt->pPage1->aData==0 ){        MemPage *pPage = pBt->pPage1;        pPage->aData = sqlite3PagerGetData(pPage->pDbPage);        pPage->pBt = pBt;        pPage->pgno = 1;      }#endif      releasePage(pBt->pPage1);    }    pBt->pPage1 = 0;    pBt->inStmt = 0;  }}/*** Create a new database by initializing the first page of the** file.*/static int newDatabase(BtShared *pBt){  MemPage *pP1;  unsigned char *data;  int rc;  int nPage;  assert( sqlite3_mutex_held(pBt->mutex) );  rc = sqlite3PagerPagecount(pBt->pPager, &nPage);  if( rc!=SQLITE_OK || nPage>0 ){    return rc;  }  pP1 = pBt->pPage1;  assert( pP1!=0 );  data = pP1->aData;  rc = sqlite3PagerWrite(pP1->pDbPage);  if( rc ) return rc;  memcpy(data, zMagicHeader, sizeof(zMagicHeader));  assert( sizeof(zMagicHeader)==16 );  put2byte(&data[16], pBt->pageSize);  data[18] = 1;  data[19] = 1;  assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);  data[20] = (u8)(pBt->pageSize - pBt->usableSize);  data[21] = 64;  data[22] = 32;  data[23] = 32;  memset(&data[24], 0, 100-24);  zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );  pBt->pageSizeFixed = 1;#ifndef SQLITE_OMIT_AUTOVACUUM  assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );  assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );  put4byte(&data[36 + 4*4], pBt->autoVacuum);  put4byte(&data[36 + 7*4], pBt->incrVacuum);#endif  return SQLITE_OK;}/*** Attempt to start a new transaction. A write-transaction** is started if the second argument is nonzero, otherwise a read-** transaction.  If the second argument is 2 or more and exclusive** transaction is started, meaning that no other process is allowed** to access the database.  A preexisting transaction may not be** upgraded to exclusive by calling this routine a second time - the** exclusivity flag only works for a new transaction.**** A write-transaction must be started before attempting any ** changes to the database.  None of the following routines ** will work unless a transaction is started first:****      sqlite3BtreeCreateTable()**      sqlite3BtreeCreateIndex()**      sqlite3BtreeClearTable()**      sqlite3BtreeDropTable()**      sqlite3BtreeInsert()**      sqlite3BtreeDelete()**      sqlite3BtreeUpdateMeta()**** If an initial attempt to acquire the lock fails because of lock contention** and the database was previously unlocked, then invoke the busy handler** if there is one.  But if there was previously a read-lock, do not** invoke the busy handler - just return SQLITE_BUSY.  SQLITE_BUSY is ** returned when there is already a read-lock in order to avoid a deadlock.**** Suppose there are two processes A and B.  A has a read lock and B has** a reserved lock.  B tries to promote to exclusive but is blocked because** of A's read lock.  A tries to promote to reserved but is blocked by B.** One or the other of the two processes must give way or there can be** no progress.  By returning SQLITE_BUSY and not invoking the busy callback** when A already has a read lock, we encourage A to give up and let B** proceed.*/int sqlite3BtreeBeginTrans(Btree *p, int wrflag){  BtShared *pBt = p->pBt;  int rc = SQLITE_OK;  sqlite3BtreeEnter(p);  pBt->db = p->db;  btreeIntegrity(p);  /* If the btree is already in a write-transaction, or it  ** is already in a read-transaction and a read-transaction  ** is requested, this is a no-op.  */  if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){    goto trans_begun;  }  /* Write transactions are not possible on a read-only database */  if( pBt->readOnly && wrflag ){    rc = SQLITE_READONLY;    goto trans_begun;  }  /* If another database handle has already opened a write transaction   ** on this shared-btree structure and a second write transaction is  ** requested, return SQLITE_BUSY.  */  if( pBt->inTransaction==TRANS_WRITE && wrflag ){    rc = SQLITE_BUSY;    goto trans_begun;  }#ifndef SQLITE_OMIT_SHARED_CACHE  if( wrflag>1 ){    BtLock *pIter;    for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){      if( pIter->pBtree!=p ){        rc = SQLITE_BUSY;        goto trans_begun;      }    }  }#endif  do {    if( pBt->pPage1==0 ){      do{        rc = lockBtree(pBt);      }while( pBt->pPage1==0 && rc==SQLITE_OK );    }    if( rc==SQLITE_OK && wrflag ){      if( pBt->r

⌨️ 快捷键说明

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