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

📄 btree.c

📁 SQLite的VS2005封装
💻 C
📖 第 1 页 / 共 5 页
字号:
  p->inTrans = TRANS_NONE;  p->db = db;#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)  /*  ** If this Btree is a candidate for shared cache, try to find an  ** existing BtShared object that we can share with  */  if( isMemdb==0   && (db->flags & SQLITE_Vtab)==0   && zFilename && zFilename[0]  ){    if( sqlite3GlobalConfig.sharedCacheEnabled ){      int nFullPathname = pVfs->mxPathname+1;      char *zFullPathname = sqlite3Malloc(nFullPathname);      sqlite3_mutex *mutexShared;      p->sharable = 1;      db->flags |= SQLITE_SharedCache;      if( !zFullPathname ){        sqlite3_free(p);        return SQLITE_NOMEM;      }      sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);      sqlite3_mutex_enter(mutexShared);      for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){        assert( pBt->nRef>0 );        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){          p->pBt = pBt;          pBt->nRef++;          break;        }      }      sqlite3_mutex_leave(mutexShared);      sqlite3_free(zFullPathname);    }#ifdef SQLITE_DEBUG    else{      /* In debug mode, we mark all persistent databases as sharable      ** even when they are not.  This exercises the locking code and      ** gives more opportunity for asserts(sqlite3_mutex_held())      ** statements to find locking problems.      */      p->sharable = 1;    }#endif  }#endif  if( pBt==0 ){    /*    ** 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 = sqlite3MallocZero( sizeof(*pBt) );    if( pBt==0 ){      rc = SQLITE_NOMEM;      goto btree_open_out;    }    pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler;    pBt->busyHdr.pArg = pBt;    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, pageDestructor,                          EXTRA_SIZE, flags, vfsFlags);    if( rc==SQLITE_OK ){      rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);    }    if( rc!=SQLITE_OK ){      goto btree_open_out;    }    sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);    p->pBt = pBt;      sqlite3PagerSetReiniter(pBt->pPager, pageReinit);    pBt->pCursor = 0;    pBt->pPage1 = 0;    pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);    pBt->pageSize = get2byte(&zDbHeader[16]);    if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE         || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){      pBt->pageSize = 0;      sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);#ifndef SQLITE_OMIT_AUTOVACUUM      /* If the magic name ":memory:" will create an in-memory database, then      ** leave the autoVacuum mode at 0 (do not auto-vacuum), 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. In this case the auto-vacuum applies as per normal.      */      if( zFilename && !isMemdb ){        pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0);        pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0);      }#endif      nReserve = 0;    }else{      nReserve = zDbHeader[20];      pBt->pageSizeFixed = 1;#ifndef SQLITE_OMIT_AUTOVACUUM      pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);      pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);#endif    }    pBt->usableSize = pBt->pageSize - nReserve;    assert( (pBt->pageSize & 7)==0 );  /* 8-byte alignment of pageSize */    sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);   #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)    /* Add the new BtShared object to the linked list sharable BtShareds.    */    if( p->sharable ){      sqlite3_mutex *mutexShared;      pBt->nRef = 1;      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);      if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){        pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);        if( pBt->mutex==0 ){          rc = SQLITE_NOMEM;          db->mallocFailed = 0;          goto btree_open_out;        }      }      sqlite3_mutex_enter(mutexShared);      pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);      GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;      sqlite3_mutex_leave(mutexShared);    }#endif  }#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)  /* If the new Btree uses a sharable pBtShared, then link the new  ** Btree into the list of all sharable Btrees for the same connection.  ** The list is kept in ascending order by pBt address.  */  if( p->sharable ){    int i;    Btree *pSib;    for(i=0; i<db->nDb; i++){      if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){        while( pSib->pPrev ){ pSib = pSib->pPrev; }        if( p->pBt<pSib->pBt ){          p->pNext = pSib;          p->pPrev = 0;          pSib->pPrev = p;        }else{          while( pSib->pNext && pSib->pNext->pBt<p->pBt ){            pSib = pSib->pNext;          }          p->pNext = pSib->pNext;          p->pPrev = pSib;          if( p->pNext ){            p->pNext->pPrev = p;          }          pSib->pNext = p;        }        break;      }    }  }#endif  *ppBtree = p;btree_open_out:  if( rc!=SQLITE_OK ){    if( pBt && pBt->pPager ){      sqlite3PagerClose(pBt->pPager);    }    sqlite3_free(pBt);    sqlite3_free(p);    *ppBtree = 0;  }  return rc;}/*** Decrement the BtShared.nRef counter.  When it reaches zero,** remove the BtShared structure from the sharing list.  Return** true if the BtShared.nRef counter reaches zero and return** false if it is still positive.*/static int removeFromSharingList(BtShared *pBt){#ifndef SQLITE_OMIT_SHARED_CACHE  sqlite3_mutex *pMaster;  BtShared *pList;  int removed = 0;  assert( sqlite3_mutex_notheld(pBt->mutex) );  pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);  sqlite3_mutex_enter(pMaster);  pBt->nRef--;  if( pBt->nRef<=0 ){    if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){      GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;    }else{      pList = GLOBAL(BtShared*,sqlite3SharedCacheList);      while( ALWAYS(pList) && pList->pNext!=pBt ){        pList=pList->pNext;      }      if( ALWAYS(pList) ){        pList->pNext = pBt->pNext;      }    }    if( SQLITE_THREADSAFE ){      sqlite3_mutex_free(pBt->mutex);    }    removed = 1;  }  sqlite3_mutex_leave(pMaster);  return removed;#else  return 1;#endif}/*** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes.*/static void allocateTempSpace(BtShared *pBt){  if( !pBt->pTmpSpace ){    pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );  }}/*** Free the pBt->pTmpSpace allocation*/static void freeTempSpace(BtShared *pBt){  sqlite3PageFree( pBt->pTmpSpace);  pBt->pTmpSpace = 0;}/*** Close an open database and invalidate all cursors.*/int sqlite3BtreeClose(Btree *p){  BtShared *pBt = p->pBt;  BtCursor *pCur;  /* Close all cursors opened via this handle.  */  assert( sqlite3_mutex_held(p->db->mutex) );  sqlite3BtreeEnter(p);  pBt->db = p->db;  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);  sqlite3BtreeLeave(p);  /* 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( p->wantToLock==0 && p->locked==0 );  if( !p->sharable || removeFromSharingList(pBt) ){    /* The pBt is no longer on the sharing list, so we can access    ** it without having to hold the mutex.    **    ** Clean out and delete the BtShared object.    */    assert( !pBt->pCursor );    sqlite3PagerClose(pBt->pPager);    if( pBt->xFreeSchema && pBt->pSchema ){      pBt->xFreeSchema(pBt->pSchema);    }    sqlite3_free(pBt->pSchema);    freeTempSpace(pBt);    sqlite3_free(pBt);  }#ifndef SQLITE_OMIT_SHARED_CACHE  assert( p->wantToLock==0 );  assert( p->locked==0 );  if( p->pPrev ) p->pPrev->pNext = p->pNext;  if( p->pNext ) p->pNext->pPrev = p->pPrev;#endif  sqlite3_free(p);  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;  assert( sqlite3_mutex_held(p->db->mutex) );  sqlite3BtreeEnter(p);  sqlite3PagerSetCachesize(pBt->pPager, mxPage);  sqlite3BtreeLeave(p);  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;  assert( sqlite3_mutex_held(p->db->mutex) );  sqlite3BtreeEnter(p);  sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync);  sqlite3BtreeLeave(p);  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;  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;  sqlite3BtreeEnter(p);  if( pBt->pageSizeFixed ){    sqlite3BtreeLeave(p);    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 = pageSize;    freeTempSpace(pBt);    rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);  }  pBt->usableSize = pBt->pageSize - 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'

⌨️ 快捷键说明

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