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

📄 btree.c

📁 1.编译色情sqlite源代码为dll;2.运用sqlite3数据库存储二进制数据到数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
    goto page1_init_failed;  }  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;  assert( sqlite3_mutex_held(pBt->mutex) );  if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK;  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;  data[20] = pBt->pageSize - pBt->usableSize;  data[21] = pBt->maxEmbedFrac;  data[22] = pBt->minEmbedFrac;  data[23] = pBt->minLeafFrac;  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 ){      rc = lockBtree(pBt);    }    if( rc==SQLITE_OK && wrflag ){      if( pBt->readOnly ){        rc = SQLITE_READONLY;      }else{        rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1);        if( rc==SQLITE_OK ){          rc = newDatabase(pBt);        }      }    }      if( rc==SQLITE_OK ){      if( wrflag ) pBt->inStmt = 0;    }else{      unlockBtreeIfUnused(pBt);    }  }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&          sqlite3BtreeInvokeBusyHandler(pBt, 0) );  if( rc==SQLITE_OK ){    if( p->inTrans==TRANS_NONE ){      pBt->nTransaction++;    }    p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);    if( p->inTrans>pBt->inTransaction ){      pBt->inTransaction = p->inTrans;    }#ifndef SQLITE_OMIT_SHARED_CACHE    if( wrflag>1 ){      assert( !pBt->pExclusive );      pBt->pExclusive = p;    }#endif  }trans_begun:  btreeIntegrity(p);  sqlite3BtreeLeave(p);  return rc;}#ifndef SQLITE_OMIT_AUTOVACUUM/*** Set the pointer-map entries for all children of page pPage. Also, if** pPage contains cells that point to overflow pages, set the pointer** map entries for the overflow pages as well.*/static int setChildPtrmaps(MemPage *pPage){  int i;                             /* Counter variable */  int nCell;                         /* Number of cells in page pPage */  int rc;                            /* Return code */  BtShared *pBt = pPage->pBt;  int isInitOrig = pPage->isInit;  Pgno pgno = pPage->pgno;  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  rc = sqlite3BtreeInitPage(pPage, pPage->pParent);  if( rc!=SQLITE_OK ){    goto set_child_ptrmaps_out;  }  nCell = pPage->nCell;  for(i=0; i<nCell; i++){    u8 *pCell = findCell(pPage, i);    rc = ptrmapPutOvflPtr(pPage, pCell);    if( rc!=SQLITE_OK ){      goto set_child_ptrmaps_out;    }    if( !pPage->leaf ){      Pgno childPgno = get4byte(pCell);      rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);      if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out;    }  }  if( !pPage->leaf ){    Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);    rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);  }set_child_ptrmaps_out:  pPage->isInit = isInitOrig;  return rc;}/*** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow** page, is a pointer to page iFrom. Modify this pointer so that it points to** iTo. Parameter eType describes the type of pointer to be modified, as ** follows:**** PTRMAP_BTREE:     pPage is a btree-page. The pointer points at a child **                   page of pPage.**** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow**                   page pointed to by one of the cells on pPage.**** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next**                   overflow page in the list.*/static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  if( eType==PTRMAP_OVERFLOW2 ){    /* The pointer is always the first 4 bytes of the page in this case.  */    if( get4byte(pPage->aData)!=iFrom ){      return SQLITE_CORRUPT_BKPT;    }    put4byte(pPage->aData, iTo);  }else{    int isInitOrig = pPage->isInit;    int i;    int nCell;    sqlite3BtreeInitPage(pPage, 0);    nCell = pPage->nCell;    for(i=0; i<nCell; i++){      u8 *pCell = findCell(pPage, i);      if( eType==PTRMAP_OVERFLOW1 ){        CellInfo info;        sqlite3BtreeParseCellPtr(pPage, pCell, &info);        if( info.iOverflow ){          if( iFrom==get4byte(&pCell[info.iOverflow]) ){            put4byte(&pCell[info.iOverflow], iTo);            break;          }        }      }else{        if( get4byte(pCell)==iFrom ){          put4byte(pCell, iTo);          break;        }      }    }      if( i==nCell ){      if( eType!=PTRMAP_BTREE ||           get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){        return SQLITE_CORRUPT_BKPT;      }      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);    }    pPage->isInit = isInitOrig;  }  return SQLITE_OK;}/*** Move the open database page pDbPage to location iFreePage in the ** database. The pDbPage reference remains valid.*/static int relocatePage(  BtShared *pBt,           /* Btree */  MemPage *pDbPage,        /* Open page to move */  u8 eType,                /* Pointer map 'type' entry for pDbPage */  Pgno iPtrPage,           /* Pointer map 'page-no' entry for pDbPage */  Pgno iFreePage           /* The location to move pDbPage to */){  MemPage *pPtrPage;   /* The page that contains a pointer to pDbPage */  Pgno iDbPage = pDbPage->pgno;  Pager *pPager = pBt->pPager;  int rc;  assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||       eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );  assert( sqlite3_mutex_held(pBt->mutex) );  assert( pDbPage->pBt==pBt );  /* Move page iDbPage from its current location to page number iFreePage */  TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",       iDbPage, iFreePage, iPtrPage, eType));  rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage);  if( rc!=SQLITE_OK ){    return rc;  }  pDbPage->pgno = iFreePage;  /* If pDbPage was a btree-page, then it may have child pages and/or cells  ** that point to overflow pages. The pointer map entries for all these  ** pages need to be changed.  **  ** If pDbPage is an overflow page, then the first 4 bytes may store a  ** pointer to a subsequent overflow page. If this is the case, then  ** the pointer map needs to be updated for the subsequent overflow page.  */  if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){    rc = setChildPtrmaps(pDbPage);    if( rc!=SQLITE_OK ){      return rc;    }  }else{    Pgno nextOvfl = get4byte(pDbPage->aData);    if( nextOvfl!=0 ){      rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);      if( rc!=SQLITE_OK ){        return rc;      }    }  }  /* Fix the database pointer on page iPtrPage that pointed at iDbPage so  ** that it points at iFreePage. Also fix the pointer map entry for  ** iPtrPage.  */  if( eType!=PTRMAP_ROOTPAGE ){    rc = sqlite3BtreeGetPage(pBt, iPtrPage, &pPtrPage, 0);    if( rc!=SQLITE_OK ){      return rc;    }    rc = sqlite3PagerWrite(pPtrPage->pDbPage);    if( rc!=SQLITE_OK ){      releasePage(pPtrPage);      return rc;    }    rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);    releasePage(pPtrPage);    if( rc==SQLITE_OK ){      rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);    }  }  return rc;}/* Forward declaration required by incrVacuumStep(). */static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);/*** Perform a single step of an incremental-vacuum. If successful,** return SQLITE_OK. If there is no work to do (and therefore no** poi

⌨️ 快捷键说明

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