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

📄 btree.c

📁 1.编译色情sqlite源代码为dll;2.运用sqlite3数据库存储二进制数据到数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
  int rc;  assert( sqlite3_mutex_held(pBt->mutex) );  /* The master-journal page number must never be used as a pointer map page */  assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );  assert( pBt->autoVacuum );  if( key==0 ){    return SQLITE_CORRUPT_BKPT;  }  iPtrmap = PTRMAP_PAGENO(pBt, key);  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);  if( rc!=SQLITE_OK ){    return rc;  }  offset = PTRMAP_PTROFFSET(pBt, key);  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);  if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){    TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));    rc = sqlite3PagerWrite(pDbPage);    if( rc==SQLITE_OK ){      pPtrmap[offset] = eType;      put4byte(&pPtrmap[offset+1], parent);    }  }  sqlite3PagerUnref(pDbPage);  return rc;}/*** Read an entry from the pointer map.**** This routine retrieves the pointer map entry for page 'key', writing** the type and parent page number to *pEType and *pPgno respectively.** An error code is returned if something goes wrong, otherwise SQLITE_OK.*/static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){  DbPage *pDbPage;   /* The pointer map page */  int iPtrmap;       /* Pointer map page index */  u8 *pPtrmap;       /* Pointer map page data */  int offset;        /* Offset of entry in pointer map */  int rc;  assert( sqlite3_mutex_held(pBt->mutex) );  iPtrmap = PTRMAP_PAGENO(pBt, key);  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);  if( rc!=0 ){    return rc;  }  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);  offset = PTRMAP_PTROFFSET(pBt, key);  assert( pEType!=0 );  *pEType = pPtrmap[offset];  if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);  sqlite3PagerUnref(pDbPage);  if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;  return SQLITE_OK;}#endif /* SQLITE_OMIT_AUTOVACUUM *//*** Given a btree page and a cell index (0 means the first cell on** the page, 1 means the second cell, and so forth) return a pointer** to the cell content.**** This routine works only for pages that do not contain overflow cells.*/#define findCell(pPage, iCell) \  ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)]))#ifdef SQLITE_TESTu8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){  assert( iCell>=0 );  assert( iCell<get2byte(&pPage->aData[pPage->hdrOffset+3]) );  return findCell(pPage, iCell);}#endif/*** This a more complex version of sqlite3BtreeFindCell() that works for** pages that do contain overflow cells.  See insert*/static u8 *findOverflowCell(MemPage *pPage, int iCell){  int i;  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  for(i=pPage->nOverflow-1; i>=0; i--){    int k;    struct _OvflCell *pOvfl;    pOvfl = &pPage->aOvfl[i];    k = pOvfl->idx;    if( k<=iCell ){      if( k==iCell ){        return pOvfl->pCell;      }      iCell--;    }  }  return findCell(pPage, iCell);}/*** Parse a cell content block and fill in the CellInfo structure.  There** are two versions of this function.  sqlite3BtreeParseCell() takes a ** cell index as the second argument and sqlite3BtreeParseCellPtr() ** takes a pointer to the body of the cell as its second argument.**** Within this file, the parseCell() macro can be called instead of** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster.*/void sqlite3BtreeParseCellPtr(  MemPage *pPage,         /* Page containing the cell */  u8 *pCell,              /* Pointer to the cell text. */  CellInfo *pInfo         /* Fill in this structure */){  int n;                  /* Number bytes in cell content header */  u32 nPayload;           /* Number of bytes of cell payload */  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  pInfo->pCell = pCell;  assert( pPage->leaf==0 || pPage->leaf==1 );  n = pPage->childPtrSize;  assert( n==4-4*pPage->leaf );  if( pPage->hasData ){    n += getVarint32(&pCell[n], &nPayload);  }else{    nPayload = 0;  }  pInfo->nData = nPayload;  if( pPage->intKey ){    n += getVarint(&pCell[n], (u64 *)&pInfo->nKey);  }else{    u32 x;    n += getVarint32(&pCell[n], &x);    pInfo->nKey = x;    nPayload += x;  }  pInfo->nPayload = nPayload;  pInfo->nHeader = n;  if( nPayload<=pPage->maxLocal ){    /* This is the (easy) common case where the entire payload fits    ** on the local page.  No overflow is required.    */    int nSize;          /* Total size of cell content in bytes */    pInfo->nLocal = nPayload;    pInfo->iOverflow = 0;    nSize = nPayload + n;    if( nSize<4 ){      nSize = 4;        /* Minimum cell size is 4 */    }    pInfo->nSize = nSize;  }else{    /* If the payload will not fit completely on the local page, we have    ** to decide how much to store locally and how much to spill onto    ** overflow pages.  The strategy is to minimize the amount of unused    ** space on overflow pages while keeping the amount of local storage    ** in between minLocal and maxLocal.    **    ** Warning:  changing the way overflow payload is distributed in any    ** way will result in an incompatible file format.    */    int minLocal;  /* Minimum amount of payload held locally */    int maxLocal;  /* Maximum amount of payload held locally */    int surplus;   /* Overflow payload available for local storage */    minLocal = pPage->minLocal;    maxLocal = pPage->maxLocal;    surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4);    if( surplus <= maxLocal ){      pInfo->nLocal = surplus;    }else{      pInfo->nLocal = minLocal;    }    pInfo->iOverflow = pInfo->nLocal + n;    pInfo->nSize = pInfo->iOverflow + 4;  }}#define parseCell(pPage, iCell, pInfo) \  sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo))void sqlite3BtreeParseCell(  MemPage *pPage,         /* Page containing the cell */  int iCell,              /* The cell index.  First cell is 0 */  CellInfo *pInfo         /* Fill in this structure */){  parseCell(pPage, iCell, pInfo);}/*** Compute the total number of bytes that a Cell needs in the cell** data area of the btree-page.  The return number includes the cell** data header and the local payload, but not any overflow page or** the space used by the cell pointer.*/#ifndef NDEBUGstatic int cellSize(MemPage *pPage, int iCell){  CellInfo info;  sqlite3BtreeParseCell(pPage, iCell, &info);  return info.nSize;}#endifstatic int cellSizePtr(MemPage *pPage, u8 *pCell){  CellInfo info;  sqlite3BtreeParseCellPtr(pPage, pCell, &info);  return info.nSize;}#ifndef SQLITE_OMIT_AUTOVACUUM/*** If the cell pCell, part of page pPage contains a pointer** to an overflow page, insert an entry into the pointer-map** for the overflow page.*/static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){  if( pCell ){    CellInfo info;    sqlite3BtreeParseCellPtr(pPage, pCell, &info);    assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );    if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){      Pgno ovfl = get4byte(&pCell[info.iOverflow]);      return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno);    }  }  return SQLITE_OK;}/*** If the cell with index iCell on page pPage contains a pointer** to an overflow page, insert an entry into the pointer-map** for the overflow page.*/static int ptrmapPutOvfl(MemPage *pPage, int iCell){  u8 *pCell;  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  pCell = findOverflowCell(pPage, iCell);  return ptrmapPutOvflPtr(pPage, pCell);}#endif/*** Defragment the page given.  All Cells are moved to the** end of the page and all free space is collected into one** big FreeBlk that occurs in between the header and cell** pointer array and the cell content area.*/static int defragmentPage(MemPage *pPage){  int i;                     /* Loop counter */  int pc;                    /* Address of a i-th cell */  int addr;                  /* Offset of first byte after cell pointer array */  int hdr;                   /* Offset to the page header */  int size;                  /* Size of a cell */  int usableSize;            /* Number of usable bytes on a page */  int cellOffset;            /* Offset to the cell pointer array */  int brk;                   /* Offset to the cell content area */  int nCell;                 /* Number of cells on the page */  unsigned char *data;       /* The page data */  unsigned char *temp;       /* Temp area for cell content */  assert( sqlite3PagerIswriteable(pPage->pDbPage) );  assert( pPage->pBt!=0 );  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );  assert( pPage->nOverflow==0 );  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  temp = sqlite3PagerTempSpace(pPage->pBt->pPager);  data = pPage->aData;  hdr = pPage->hdrOffset;  cellOffset = pPage->cellOffset;  nCell = pPage->nCell;  assert( nCell==get2byte(&data[hdr+3]) );  usableSize = pPage->pBt->usableSize;  brk = get2byte(&data[hdr+5]);  memcpy(&temp[brk], &data[brk], usableSize - brk);  brk = usableSize;  for(i=0; i<nCell; i++){    u8 *pAddr;     /* The i-th cell pointer */    pAddr = &data[cellOffset + i*2];    pc = get2byte(pAddr);    assert( pc<pPage->pBt->usableSize );    size = cellSizePtr(pPage, &temp[pc]);    brk -= size;    memcpy(&data[brk], &temp[pc], size);    put2byte(pAddr, brk);  }  assert( brk>=cellOffset+2*nCell );  put2byte(&data[hdr+5], brk);  data[hdr+1] = 0;  data[hdr+2] = 0;  data[hdr+7] = 0;  addr = cellOffset+2*nCell;  memset(&data[addr], 0, brk-addr);  return SQLITE_OK;}/*** Allocate nByte bytes of space on a page.**** Return the index into pPage->aData[] of the first byte of** the new allocation. Or return 0 if there is not enough free** space on the page to satisfy the allocation request.**** If the page contains nBytes of free space but does not contain** nBytes of contiguous free space, then this routine automatically** calls defragementPage() to consolidate all free space before ** allocating the new chunk.*/static int allocateSpace(MemPage *pPage, int nByte){  int addr, pc, hdr;  int size;  int nFrag;  int top;  int nCell;  int cellOffset;  unsigned char *data;    data = pPage->aData;  assert( sqlite3PagerIswriteable(pPage->pDbPage) );  assert( pPage->pBt );  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  if( nByte<4 ) nByte = 4;  if( pPage->nFree<nByte || pPage->nOverflow>0 ) return 0;  pPage->nFree -= nByte;  hdr = pPage->hdrOffset;  nFrag = data[hdr+7];  if( nFrag<60 ){    /* Search the freelist looking for a slot big enough to satisfy the    ** space request. */    addr = hdr+1;    while( (pc = get2byte(&data[addr]))>0 ){      size = get2byte(&data[pc+2]);      if( size>=nByte ){        if( size<nByte+4 ){          memcpy(&data[addr], &data[pc], 2);          data[hdr+7] = nFrag + size - nByte;          return pc;        }else{          put2byte(&data[pc+2], size-nByte);          return pc + size - nByte;        }      }      addr = pc;    }  }  /* Allocate memory from the gap in between the cell pointer array  ** and the cell content area.  */  top = get2byte(&data[hdr+5]);  nCell = get2byte(&data[hdr+3]);  cellOffset = pPage->cellOffset;  if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){    if( defragmentPage(pPage) ) return 0;    top = get2byte(&data[hdr+5]);  }  top -= nByte;  assert( cellOffset + 2*nCell <= top );  put2byte(&data[hdr+5], top);  return top;}/*** Return a section of the pPage->aData to the freelist.** The first byte of the new free block is pPage->aDisk[start]** and the size of the block is "size" bytes.**** Most of the effort here is involved in coalesing adjacent** free blocks into a single big free block.*/static void freeSpace(MemPage *pPage, int start, int size){  int addr, pbegin, hdr;  unsigned char *data = pPage->aData;  assert( pPage->pBt!=0 );  assert( sqlite3PagerIswriteable(pPage->pDbPage) );  assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );  assert( (start + size)<=pPage->pBt->usableSize );  assert( sqlite3_mutex_held(pPage->pBt->mutex) );  if( size<4 ) size = 4;#ifdef SQLITE_SECURE_DELETE  /* Overwrite deleted information with zeros when the SECURE_DELETE   ** option is enabled at compile-time */  memset(&data[start], 0, size);#endif  /* Add the space back into the linked list of freeblocks */  hdr = pPage->hdrOffset;  addr = hdr + 1;  while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){    assert( pbegin<=pPage->pBt->usableSize-4 );    assert( pbegin>addr );    addr = pbegin;  }  assert( pbegin<=pPage->pBt->usableSize-4 );  assert( pbegin>addr || pbegin==0 );  put2byte(&data[addr], start);  put2byte(&data[start], pbegin);  put2byte(&data[start+2], size);  pPage->nFree += size;  /* Coalesce adjacent free blocks */  addr = pPage->hdrOffset + 1;  while( (pbegin = get2byte(&data[addr]))>0 ){    int pnext, psize;    assert( pbegin>addr );    assert( pbegin<=pPage->pBt->usableSize-4 );    pnext = get2byte(&data[pbegin]);    psize = get2byte(&data[pbegin+2]);    if( pbegin + psize + 3 >= pnext && pnext>0 ){      int frag = pnext - (pbegin+psize);      assert( frag<=data[pPage->hdrOffset+7] );      data[pPage->hdrOffset+7] -= frag;      put2byte(&data[pbegin], get2byte(&data[pnext]));      put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin);    }else{      addr = pbegin;    }  }  /* If the cell content area begins with a freeblock, remove it. */  if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){

⌨️ 快捷键说明

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