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

📄 btree.c

📁 调用sqlite开源数据的小程序
💻 C
📖 第 1 页 / 共 5 页
字号:
  idx = 0;  nCell = get2byte(&data[hdr+3]);  cellLimit = get2byte(&data[hdr+5]);  assert( pPage->isInit==0          || pPage->nFree==nFree+data[hdr+7]+cellLimit-(cellOffset+2*nCell) );  cellOffset = pPage->cellOffset;  for(i=0; i<nCell; i++){    int size;    pc = get2byte(&data[cellOffset+2*i]);    assert( pc>0 && pc<usableSize-4 );    size = cellSize(pPage, &data[pc]);    assert( pc+size<=usableSize );    for(j=pc; j<pc+size; j++){      assert( used[j]==0 );      used[j] = 1;    }  }  for(i=cellOffset+2*nCell; i<cellimit; i++){    assert( used[i]==0 );    used[i] = 1;  }  nFree = 0;  for(i=0; i<usableSize; i++){    assert( used[i]<=1 );    if( used[i]==0 ) nFree++;  }  assert( nFree==data[hdr+7] );  sqliteFree(used);}#define pageIntegrity(X) _pageIntegrity(X)#else# define pageIntegrity(X)#endif/*** Defragment the page given.  All Cells are moved to the** beginning of the page and all free space is collected ** into one big FreeBlk at the end of the page.*/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( sqlite3pager_iswriteable(pPage->aData) );  assert( pPage->pBt!=0 );  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );  assert( pPage->nOverflow==0 );  temp = sqliteMalloc( pPage->pBt->pageSize );  if( temp==0 ) return SQLITE_NOMEM;  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);  sqliteFree(temp);  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( sqlite3pager_iswriteable(data) );  assert( pPage->pBt );  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( sqlite3pager_iswriteable(data) );  assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );  assert( (start + size)<=pPage->pBt->usableSize );  if( size<4 ) size = 4;  /* 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] ){    int top;    pbegin = get2byte(&data[hdr+1]);    memcpy(&data[hdr+1], &data[pbegin], 2);    top = get2byte(&data[hdr+5]);    put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2]));  }}/*** Decode the flags byte (the first byte of the header) for a page** and initialize fields of the MemPage structure accordingly.*/static void decodeFlags(MemPage *pPage, int flagByte){  Btree *pBt;     /* A copy of pPage->pBt */  assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );  pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0;  pPage->zeroData = (flagByte & PTF_ZERODATA)!=0;  pPage->leaf = (flagByte & PTF_LEAF)!=0;  pPage->childPtrSize = 4*(pPage->leaf==0);  pBt = pPage->pBt;  if( flagByte & PTF_LEAFDATA ){    pPage->leafData = 1;    pPage->maxLocal = pBt->maxLeaf;    pPage->minLocal = pBt->minLeaf;  }else{    pPage->leafData = 0;    pPage->maxLocal = pBt->maxLocal;    pPage->minLocal = pBt->minLocal;  }  pPage->hasData = !(pPage->zeroData || (!pPage->leaf && pPage->leafData));}/*** Initialize the auxiliary information for a disk block.**** The pParent parameter must be a pointer to the MemPage which** is the parent of the page being initialized.  The root of a** BTree has no parent and so for that page, pParent==NULL.**** Return SQLITE_OK on success.  If we see that the page does** not contain a well-formed database page, then return ** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not** guarantee that the page is well-formed.  It only shows that** we failed to detect any corruption.*/static int initPage(  MemPage *pPage,        /* The page to be initialized */  MemPage *pParent       /* The parent.  Might be NULL */){  int pc;            /* Address of a freeblock within pPage->aData[] */  int hdr;           /* Offset to beginning of page header */  u8 *data;          /* Equal to pPage->aData */  Btree *pBt;        /* The main btree structure */  int usableSize;    /* Amount of usable space on each page */  int cellOffset;    /* Offset from start of page to first cell pointer */  int nFree;         /* Number of unused bytes on the page */  int top;           /* First byte of the cell content area */  pBt = pPage->pBt;  assert( pBt!=0 );  assert( pParent==0 || pParent->pBt==pBt );  assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );  assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );  if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){    /* The parent page should never change unless the file is corrupt */    return SQLITE_CORRUPT_BKPT;  }  if( pPage->isInit ) return SQLITE_OK;  if( pPage->pParent==0 && pParent!=0 ){    pPage->pParent = pParent;    sqlite3pager_ref(pParent->aData);  }  hdr = pPage->hdrOffset;  data = pPage->aData;  decodeFlags(pPage, data[hdr]);  pPage->nOverflow = 0;  pPage->idxShift = 0;  usableSize = pBt->usableSize;  pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;  top = get2byte(&data[hdr+5]);  pPage->nCell = get2byte(&data[hdr+3]);  if( pPage->nCell>MX_CELL(pBt) ){    /* To many cells for a single page.  The page must be corrupt */    return SQLITE_CORRUPT_BKPT;  }  if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){    /* All pages must have at least one cell, except for root pages */    return SQLITE_CORRUPT_BKPT;  }  /* Compute the total free space on the page */  pc = get2byte(&data[hdr+1]);  nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);  while( pc>0 ){    int next, size;    if( pc>usableSize-4 ){      /* Free block is off the page */      return SQLITE_CORRUPT_BKPT;     }    next = get2byte(&data[pc]);    size = get2byte(&data[pc+2]);    if( next>0 && next<=pc+size+3 ){      /* Free blocks must be in accending order */      return SQLITE_CORRUPT_BKPT;     }    nFree += size;    pc = next;  }  pPage->nFree = nFree;  if( nFree>=usableSize ){    /* Free space cannot exceed total page size */    return SQLITE_CORRUPT_BKPT;   }  pPage->isInit = 1;  pageIntegrity(pPage);  return SQLITE_OK;}/*** Set up a raw page so that it looks like a database page holding** no entries.*/static void zeroPage(MemPage *pPage, int flags){  unsigned char *data = pPage->aData;  Btree *pBt = pPage->pBt;  int hdr = pPage->hdrOffset;  int first;  assert( sqlite3pager_pagenumber(data)==pPage->pgno );  assert( &data[pBt->pageSize] == (unsigned char*)pPage );  assert( sqlite3pager_iswriteable(data) );  memset(&data[hdr], 0, pBt->usableSize - hdr);  data[hdr] = flags;  first = hdr + 8 + 4*((flags&PTF_LEAF)==0);  memset(&data[hdr+1], 0, 4);  data[hdr+7] = 0;  put2byte(&data[hdr+5], pBt->usableSize);  pPage->nFree = pBt->usableSize - first;  decodeFlags(pPage, flags);  pPage->hdrOffset = hdr;  pPage->cellOffset = first;  pPage->nOverflow = 0;  pPage->idxShift = 0;  pPage->nCell = 0;  pPage->isInit = 1;  pageIntegrity(pPage);}/*** Get a page from the pager.  Initialize the MemPage.pBt and** MemPage.aData elements if needed.*/static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){  int rc;  unsigned char *aData;  MemPage *pPage;  rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData);  if( rc ) return rc;  pPage = (MemPage*)&aData[pBt->pageSize];  pPage->aData = aData;  pPage->pBt = pBt;  pPage->pgno = pgno;  pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;  *ppPage = pPage;  return SQLITE_OK;}/*** Get a page from the pager and initialize it.  This routine

⌨️ 快捷键说明

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