mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Changes to btree and pager in preparation for moving to run-time page
size determination. (CVS 1374) FossilOrigin-Name: f63fb6dd4e8e33d4c1983396b1a0305836ee4df7
This commit is contained in:
4
main.mk
4
main.mk
@@ -109,7 +109,7 @@ SRC = \
|
|||||||
|
|
||||||
# Source code to the test files.
|
# Source code to the test files.
|
||||||
#
|
#
|
||||||
TESTSRC = \
|
TESTSRC_SUBSET = \
|
||||||
$(TOP)/src/os.c \
|
$(TOP)/src/os.c \
|
||||||
$(TOP)/src/pager.c \
|
$(TOP)/src/pager.c \
|
||||||
$(TOP)/src/test1.c \
|
$(TOP)/src/test1.c \
|
||||||
@@ -118,7 +118,7 @@ TESTSRC = \
|
|||||||
$(TOP)/src/test5.c \
|
$(TOP)/src/test5.c \
|
||||||
$(TOP)/src/md5.c
|
$(TOP)/src/md5.c
|
||||||
|
|
||||||
TESTSRC_ORIG = \
|
TESTSRC = \
|
||||||
$(TOP)/src/btree.c \
|
$(TOP)/src/btree.c \
|
||||||
$(TOP)/src/func.c \
|
$(TOP)/src/func.c \
|
||||||
$(TOP)/src/os.c \
|
$(TOP)/src/os.c \
|
||||||
|
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Changes\sto\smake\sregression\stests\sin\srowid.test\spass.\s(CVS\s1373)
|
C Changes\sto\sbtree\sand\spager\sin\spreparation\sfor\smoving\sto\srun-time\spage\nsize\sdetermination.\s(CVS\s1374)
|
||||||
D 2004-05-13T13:38:52
|
D 2004-05-14T01:58:12
|
||||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -15,7 +15,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
|||||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||||
F main.mk 08bc0f1706964e029ef0319af0271ad79427cc71
|
F main.mk fbc906044c1b891be4bd9e48a74a9fd5bcd5fc81
|
||||||
F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
|
F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
|
||||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||||
@@ -23,7 +23,7 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
|
|||||||
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||||
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
|
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
|
||||||
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
||||||
F src/btree.c bda57fe687cfa28905e5daebb0b706187649bd6b
|
F src/btree.c 2b85dc8f6b169bbe6bc0dab1730757f77d72811b
|
||||||
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
|
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
|
||||||
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
|
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
|
||||||
F src/build.c f25e4ac9f102efd70188bc09a459c2b461fe2135
|
F src/build.c f25e4ac9f102efd70188bc09a459c2b461fe2135
|
||||||
@@ -40,8 +40,8 @@ F src/main.c 4b82d7e78f4c9799343b02740a5ba9768d5e464d
|
|||||||
F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c
|
F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c
|
||||||
F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e
|
F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e
|
||||||
F src/os.h fbb2f6595fc34fa351830d88fe1c6b85118f0383
|
F src/os.h fbb2f6595fc34fa351830d88fe1c6b85118f0383
|
||||||
F src/pager.c fa60e566b370de0ed400859ba681134948b027bc
|
F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
|
||||||
F src/pager.h 0c95b18f2785b58bfbb2b6f6a221f23caf378687
|
F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
|
||||||
F src/parse.y d0258aa3cc8b0c5742b07b699d10fa98f3caea7d
|
F src/parse.y d0258aa3cc8b0c5742b07b699d10fa98f3caea7d
|
||||||
F src/pragma.c 2ab2a12b62ec5370b9221f44b4743a633a90bfa8
|
F src/pragma.c 2ab2a12b62ec5370b9221f44b4743a633a90bfa8
|
||||||
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
||||||
@@ -191,7 +191,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
|||||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P da9b3dce334bde99360db45b4a3d41be519ec2d1
|
P 790226c94493a6d58a7e52fd3ed35ef495fab11e
|
||||||
R b8ea62c9a072cbdad240805f1fb27046
|
R 1732d9617f45de2d10dd8c0de779aa14
|
||||||
U danielk1977
|
U drh
|
||||||
Z 37e1d6f2ec906eb83a05d292d4e622d2
|
Z 4d4be7c36b4d139bc06baaeae3481d2d
|
||||||
|
@@ -1 +1 @@
|
|||||||
790226c94493a6d58a7e52fd3ed35ef495fab11e
|
f63fb6dd4e8e33d4c1983396b1a0305836ee4df7
|
239
src/btree.c
239
src/btree.c
@@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.133 2004/05/13 13:38:52 danielk1977 Exp $
|
** $Id: btree.c,v 1.134 2004/05/14 01:58:13 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@@ -267,7 +267,8 @@ struct Btree {
|
|||||||
u8 inTrans; /* True if a transaction is in progress */
|
u8 inTrans; /* True if a transaction is in progress */
|
||||||
u8 inStmt; /* True if there is a checkpoint on the transaction */
|
u8 inStmt; /* True if there is a checkpoint on the transaction */
|
||||||
u8 readOnly; /* True if the underlying file is readonly */
|
u8 readOnly; /* True if the underlying file is readonly */
|
||||||
int pageSize; /* Number of usable bytes on each page */
|
int pageSize; /* Total number of bytes on a page */
|
||||||
|
int usableSize; /* Number of usable bytes on each page */
|
||||||
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
||||||
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
||||||
int maxLeaf; /* Maximum local payload in a LEAFDATA table */
|
int maxLeaf; /* Maximum local payload in a LEAFDATA table */
|
||||||
@@ -332,17 +333,6 @@ static void put4byte(unsigned char *p, u32 v){
|
|||||||
p[3] = v;
|
p[3] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* NOT_USED */
|
|
||||||
static u64 get8byte(unsigned char *p){
|
|
||||||
u64 v = get4byte(p);
|
|
||||||
return (v<<32) | get4byte(&p[4]);
|
|
||||||
}
|
|
||||||
static void put8byte(unsigned char *p, u64 v){
|
|
||||||
put4byte(&p[4], v>>32);
|
|
||||||
put4byte(p, v);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Read a variable-length integer. Store the result in *pResult.
|
** Read a variable-length integer. Store the result in *pResult.
|
||||||
** Return the number of bytes in the integer.
|
** Return the number of bytes in the integer.
|
||||||
@@ -420,7 +410,7 @@ static void parseCell(
|
|||||||
pBt = pPage->pBt;
|
pBt = pPage->pBt;
|
||||||
if( pPage->leafData ){
|
if( pPage->leafData ){
|
||||||
minLocal = pBt->minLeaf;
|
minLocal = pBt->minLeaf;
|
||||||
maxLocal = pBt->pageSize - 23;
|
maxLocal = pBt->usableSize - 23;
|
||||||
}else{
|
}else{
|
||||||
minLocal = pBt->minLocal;
|
minLocal = pBt->minLocal;
|
||||||
maxLocal = pBt->maxLocal;
|
maxLocal = pBt->maxLocal;
|
||||||
@@ -430,7 +420,7 @@ static void parseCell(
|
|||||||
pInfo->iOverflow = 0;
|
pInfo->iOverflow = 0;
|
||||||
pInfo->nSize = nPayload + n;
|
pInfo->nSize = nPayload + n;
|
||||||
}else{
|
}else{
|
||||||
int surplus = minLocal + (nPayload - minLocal)%(pBt->pageSize - 4);
|
int surplus = minLocal + (nPayload - minLocal)%(pBt->usableSize - 4);
|
||||||
if( surplus <= maxLocal ){
|
if( surplus <= maxLocal ){
|
||||||
pInfo->nLocal = surplus;
|
pInfo->nLocal = surplus;
|
||||||
}else{
|
}else{
|
||||||
@@ -464,13 +454,13 @@ static int cellSize(MemPage *pPage, unsigned char *pCell){
|
|||||||
*/
|
*/
|
||||||
#if defined(BTREE_DEBUG) && !defined(NDEBUG) && 0
|
#if defined(BTREE_DEBUG) && !defined(NDEBUG) && 0
|
||||||
static void _pageIntegrity(MemPage *pPage){
|
static void _pageIntegrity(MemPage *pPage){
|
||||||
int pageSize;
|
int usableSize;
|
||||||
u8 *data;
|
u8 *data;
|
||||||
int i, idx, c, pc, hdr, nFree;
|
int i, idx, c, pc, hdr, nFree;
|
||||||
u8 used[MX_PAGE_SIZE];
|
u8 used[MX_PAGE_SIZE];
|
||||||
|
|
||||||
pageSize = pPage->pBt->pageSize;
|
usableSize = pPage->pBt->usableSize;
|
||||||
assert( pPage->aData==&((unsigned char*)pPage)[-pageSize] );
|
assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
|
||||||
hdr = pPage->hdrOffset;
|
hdr = pPage->hdrOffset;
|
||||||
assert( hdr==(pPage->pgno==1 ? 100 : 0) );
|
assert( hdr==(pPage->pgno==1 ? 100 : 0) );
|
||||||
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
|
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
|
||||||
@@ -484,15 +474,15 @@ static void _pageIntegrity(MemPage *pPage){
|
|||||||
!(pPage->zeroData || (!pPage->leaf && pPage->leafData)) );
|
!(pPage->zeroData || (!pPage->leaf && pPage->leafData)) );
|
||||||
}
|
}
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
memset(used, 0, pageSize);
|
memset(used, 0, usableSize);
|
||||||
for(i=0; i<hdr+10-pPage->leaf*4; i++) used[i] = 1;
|
for(i=0; i<hdr+10-pPage->leaf*4; i++) used[i] = 1;
|
||||||
nFree = 0;
|
nFree = 0;
|
||||||
pc = get2byte(&data[hdr+1]);
|
pc = get2byte(&data[hdr+1]);
|
||||||
while( pc ){
|
while( pc ){
|
||||||
int size;
|
int size;
|
||||||
assert( pc>0 && pc<pageSize-4 );
|
assert( pc>0 && pc<usableSize-4 );
|
||||||
size = get2byte(&data[pc+2]);
|
size = get2byte(&data[pc+2]);
|
||||||
assert( pc+size<=pageSize );
|
assert( pc+size<=usableSize );
|
||||||
nFree += size;
|
nFree += size;
|
||||||
for(i=pc; i<pc+size; i++){
|
for(i=pc; i<pc+size; i++){
|
||||||
assert( used[i]==0 );
|
assert( used[i]==0 );
|
||||||
@@ -506,10 +496,10 @@ static void _pageIntegrity(MemPage *pPage){
|
|||||||
while( pc ){
|
while( pc ){
|
||||||
int size;
|
int size;
|
||||||
assert( pPage->isInit==0 || idx<pPage->nCell );
|
assert( pPage->isInit==0 || idx<pPage->nCell );
|
||||||
assert( pc>0 && pc<pageSize-4 );
|
assert( pc>0 && pc<usableSize-4 );
|
||||||
assert( pPage->isInit==0 || pPage->aCell[idx]==&data[pc] );
|
assert( pPage->isInit==0 || pPage->aCell[idx]==&data[pc] );
|
||||||
size = cellSize(pPage, &data[pc]);
|
size = cellSize(pPage, &data[pc]);
|
||||||
assert( pc+size<=pageSize );
|
assert( pc+size<=usableSize );
|
||||||
for(i=pc; i<pc+size; i++){
|
for(i=pc; i<pc+size; i++){
|
||||||
assert( used[i]==0 );
|
assert( used[i]==0 );
|
||||||
used[i] = 1;
|
used[i] = 1;
|
||||||
@@ -519,7 +509,7 @@ static void _pageIntegrity(MemPage *pPage){
|
|||||||
}
|
}
|
||||||
assert( idx==pPage->nCell );
|
assert( idx==pPage->nCell );
|
||||||
nFree = 0;
|
nFree = 0;
|
||||||
for(i=0; i<pageSize; i++){
|
for(i=0; i<usableSize; i++){
|
||||||
assert( used[i]<=1 );
|
assert( used[i]<=1 );
|
||||||
if( used[i]==0 ) nFree++;
|
if( used[i]==0 ) nFree++;
|
||||||
}
|
}
|
||||||
@@ -544,7 +534,7 @@ static void defragmentPage(MemPage *pPage){
|
|||||||
|
|
||||||
assert( sqlite3pager_iswriteable(pPage->aData) );
|
assert( sqlite3pager_iswriteable(pPage->aData) );
|
||||||
assert( pPage->pBt!=0 );
|
assert( pPage->pBt!=0 );
|
||||||
assert( pPage->pBt->pageSize <= MX_PAGE_SIZE );
|
assert( pPage->pBt->usableSize <= MX_PAGE_SIZE );
|
||||||
assert( !pPage->needRelink );
|
assert( !pPage->needRelink );
|
||||||
assert( !pPage->isOverfull );
|
assert( !pPage->isOverfull );
|
||||||
oldPage = pPage->aData;
|
oldPage = pPage->aData;
|
||||||
@@ -559,7 +549,7 @@ static void defragmentPage(MemPage *pPage){
|
|||||||
pc = get2byte(&oldPage[addr]);
|
pc = get2byte(&oldPage[addr]);
|
||||||
i = 0;
|
i = 0;
|
||||||
while( pc>0 ){
|
while( pc>0 ){
|
||||||
assert( n<pPage->pBt->pageSize );
|
assert( n<pPage->pBt->usableSize );
|
||||||
size = cellSize(pPage, &oldPage[pc]);
|
size = cellSize(pPage, &oldPage[pc]);
|
||||||
memcpy(&newPage[n], &oldPage[pc], size);
|
memcpy(&newPage[n], &oldPage[pc], size);
|
||||||
put2byte(&newPage[addr],n);
|
put2byte(&newPage[addr],n);
|
||||||
@@ -570,13 +560,13 @@ static void defragmentPage(MemPage *pPage){
|
|||||||
pc = get2byte(&oldPage[pc]);
|
pc = get2byte(&oldPage[pc]);
|
||||||
}
|
}
|
||||||
assert( i==pPage->nCell );
|
assert( i==pPage->nCell );
|
||||||
leftover = pPage->pBt->pageSize - n;
|
leftover = pPage->pBt->usableSize - n;
|
||||||
assert( leftover>=0 );
|
assert( leftover>=0 );
|
||||||
assert( pPage->nFree==leftover );
|
assert( pPage->nFree==leftover );
|
||||||
if( leftover<4 ){
|
if( leftover<4 ){
|
||||||
oldPage[hdr+5] = leftover;
|
oldPage[hdr+5] = leftover;
|
||||||
leftover = 0;
|
leftover = 0;
|
||||||
n = pPage->pBt->pageSize;
|
n = pPage->pBt->usableSize;
|
||||||
}
|
}
|
||||||
memcpy(&oldPage[hdr], &newPage[hdr], n-hdr);
|
memcpy(&oldPage[hdr], &newPage[hdr], n-hdr);
|
||||||
if( leftover==0 ){
|
if( leftover==0 ){
|
||||||
@@ -628,11 +618,11 @@ static int allocateSpace(MemPage *pPage, int nByte){
|
|||||||
addr = hdr+1;
|
addr = hdr+1;
|
||||||
pc = get2byte(&data[addr]);
|
pc = get2byte(&data[addr]);
|
||||||
assert( addr<pc );
|
assert( addr<pc );
|
||||||
assert( pc<=pPage->pBt->pageSize-4 );
|
assert( pc<=pPage->pBt->usableSize-4 );
|
||||||
while( (size = get2byte(&data[pc+2]))<nByte ){
|
while( (size = get2byte(&data[pc+2]))<nByte ){
|
||||||
addr = pc;
|
addr = pc;
|
||||||
pc = get2byte(&data[addr]);
|
pc = get2byte(&data[addr]);
|
||||||
assert( pc<=pPage->pBt->pageSize-4 );
|
assert( pc<=pPage->pBt->usableSize-4 );
|
||||||
assert( pc>=addr+size+4 || pc==0 );
|
assert( pc>=addr+size+4 || pc==0 );
|
||||||
if( pc==0 ){
|
if( pc==0 ){
|
||||||
assert( (cnt++)==0 );
|
assert( (cnt++)==0 );
|
||||||
@@ -643,7 +633,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert( pc>0 && size>=nByte );
|
assert( pc>0 && size>=nByte );
|
||||||
assert( pc+size<=pPage->pBt->pageSize );
|
assert( pc+size<=pPage->pBt->usableSize );
|
||||||
if( size>nByte+4 ){
|
if( size>nByte+4 ){
|
||||||
int newStart = pc+nByte;
|
int newStart = pc+nByte;
|
||||||
put2byte(&data[addr], newStart);
|
put2byte(&data[addr], newStart);
|
||||||
@@ -677,17 +667,17 @@ static void freeSpace(MemPage *pPage, int start, int size){
|
|||||||
assert( pPage->pBt!=0 );
|
assert( pPage->pBt!=0 );
|
||||||
assert( sqlite3pager_iswriteable(data) );
|
assert( sqlite3pager_iswriteable(data) );
|
||||||
assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
|
assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
|
||||||
assert( end<=pPage->pBt->pageSize );
|
assert( end<=pPage->pBt->usableSize );
|
||||||
if( size<4 ) size = 4;
|
if( size<4 ) size = 4;
|
||||||
|
|
||||||
/* Add the space back into the linked list of freeblocks */
|
/* Add the space back into the linked list of freeblocks */
|
||||||
addr = pPage->hdrOffset + 1;
|
addr = pPage->hdrOffset + 1;
|
||||||
while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){
|
while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){
|
||||||
assert( pbegin<=pPage->pBt->pageSize-4 );
|
assert( pbegin<=pPage->pBt->usableSize-4 );
|
||||||
assert( pbegin>addr );
|
assert( pbegin>addr );
|
||||||
addr = pbegin;
|
addr = pbegin;
|
||||||
}
|
}
|
||||||
assert( pbegin<=pPage->pBt->pageSize-4 );
|
assert( pbegin<=pPage->pBt->usableSize-4 );
|
||||||
assert( pbegin>addr || pbegin==0 );
|
assert( pbegin>addr || pbegin==0 );
|
||||||
put2byte(&data[addr], start);
|
put2byte(&data[addr], start);
|
||||||
put2byte(&data[start], pbegin);
|
put2byte(&data[start], pbegin);
|
||||||
@@ -699,7 +689,7 @@ static void freeSpace(MemPage *pPage, int start, int size){
|
|||||||
while( (pbegin = get2byte(&data[addr]))>0 ){
|
while( (pbegin = get2byte(&data[addr]))>0 ){
|
||||||
int pnext, psize;
|
int pnext, psize;
|
||||||
assert( pbegin>addr );
|
assert( pbegin>addr );
|
||||||
assert( pbegin<pPage->pBt->pageSize-4 );
|
assert( pbegin<pPage->pBt->usableSize-4 );
|
||||||
pnext = get2byte(&data[pbegin]);
|
pnext = get2byte(&data[pbegin]);
|
||||||
psize = get2byte(&data[pbegin+2]);
|
psize = get2byte(&data[pbegin+2]);
|
||||||
if( pbegin + psize + 3 >= pnext && pnext>0 ){
|
if( pbegin + psize + 3 >= pnext && pnext>0 ){
|
||||||
@@ -750,7 +740,7 @@ static int initPage(
|
|||||||
){
|
){
|
||||||
int c, pc, i, hdr;
|
int c, pc, i, hdr;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int pageSize;
|
int usableSize;
|
||||||
int sumCell = 0; /* Total size of all cells */
|
int sumCell = 0; /* Total size of all cells */
|
||||||
|
|
||||||
assert( pPage->pBt!=0 );
|
assert( pPage->pBt!=0 );
|
||||||
@@ -776,13 +766,13 @@ static int initPage(
|
|||||||
pPage->isOverfull = 0;
|
pPage->isOverfull = 0;
|
||||||
pPage->needRelink = 0;
|
pPage->needRelink = 0;
|
||||||
pPage->idxShift = 0;
|
pPage->idxShift = 0;
|
||||||
pageSize = pPage->pBt->pageSize;
|
usableSize = pPage->pBt->usableSize;
|
||||||
|
|
||||||
/* Initialize the cell count and cell pointers */
|
/* Initialize the cell count and cell pointers */
|
||||||
pc = get2byte(&data[hdr+3]);
|
pc = get2byte(&data[hdr+3]);
|
||||||
while( pc>0 ){
|
while( pc>0 ){
|
||||||
if( pc>=pageSize ) return SQLITE_CORRUPT;
|
if( pc>=usableSize ) return SQLITE_CORRUPT;
|
||||||
if( pPage->nCell>pageSize ) return SQLITE_CORRUPT;
|
if( pPage->nCell>usableSize ) return SQLITE_CORRUPT;
|
||||||
pPage->nCell++;
|
pPage->nCell++;
|
||||||
pc = get2byte(&data[pc]);
|
pc = get2byte(&data[pc]);
|
||||||
}
|
}
|
||||||
@@ -801,18 +791,18 @@ static int initPage(
|
|||||||
pc = get2byte(&data[hdr+1]);
|
pc = get2byte(&data[hdr+1]);
|
||||||
while( pc>0 ){
|
while( pc>0 ){
|
||||||
int next, size;
|
int next, size;
|
||||||
if( pc>=pageSize ) return SQLITE_CORRUPT;
|
if( pc>=usableSize ) return SQLITE_CORRUPT;
|
||||||
next = get2byte(&data[pc]);
|
next = get2byte(&data[pc]);
|
||||||
size = get2byte(&data[pc+2]);
|
size = get2byte(&data[pc+2]);
|
||||||
if( next>0 && next<=pc+size+3 ) return SQLITE_CORRUPT;
|
if( next>0 && next<=pc+size+3 ) return SQLITE_CORRUPT;
|
||||||
pPage->nFree += size;
|
pPage->nFree += size;
|
||||||
pc = next;
|
pc = next;
|
||||||
}
|
}
|
||||||
if( pPage->nFree>=pageSize ) return SQLITE_CORRUPT;
|
if( pPage->nFree>=usableSize ) return SQLITE_CORRUPT;
|
||||||
|
|
||||||
/* Sanity check: Cells and freespace and header must sum to the size
|
/* Sanity check: Cells and freespace and header must sum to the size
|
||||||
** a page. */
|
** a page. */
|
||||||
if( sumCell+pPage->nFree+hdr+10-pPage->leaf*4 != pageSize ){
|
if( sumCell+pPage->nFree+hdr+10-pPage->leaf*4 != usableSize ){
|
||||||
return SQLITE_CORRUPT;
|
return SQLITE_CORRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -834,16 +824,16 @@ static void zeroPage(MemPage *pPage, int flags){
|
|||||||
assert( sqlite3pager_pagenumber(data)==pPage->pgno );
|
assert( sqlite3pager_pagenumber(data)==pPage->pgno );
|
||||||
assert( &data[pBt->pageSize] == (unsigned char*)pPage );
|
assert( &data[pBt->pageSize] == (unsigned char*)pPage );
|
||||||
assert( sqlite3pager_iswriteable(data) );
|
assert( sqlite3pager_iswriteable(data) );
|
||||||
memset(&data[hdr], 0, pBt->pageSize - hdr);
|
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
||||||
data[hdr] = flags;
|
data[hdr] = flags;
|
||||||
first = hdr + 6 + 4*((flags&PTF_LEAF)==0);
|
first = hdr + 6 + 4*((flags&PTF_LEAF)==0);
|
||||||
put2byte(&data[hdr+1], first);
|
put2byte(&data[hdr+1], first);
|
||||||
put2byte(&data[first+2], pBt->pageSize - first);
|
put2byte(&data[first+2], pBt->usableSize - first);
|
||||||
sqliteFree(pPage->aCell);
|
sqliteFree(pPage->aCell);
|
||||||
pPage->aCell = 0;
|
pPage->aCell = 0;
|
||||||
pPage->nCell = 0;
|
pPage->nCell = 0;
|
||||||
pPage->nCellAlloc = 0;
|
pPage->nCellAlloc = 0;
|
||||||
pPage->nFree = pBt->pageSize - first;
|
pPage->nFree = pBt->usableSize - first;
|
||||||
pPage->intKey = (flags & (PTF_INTKEY|PTF_LEAFDATA))!=0;
|
pPage->intKey = (flags & (PTF_INTKEY|PTF_LEAFDATA))!=0;
|
||||||
pPage->zeroData = (flags & PTF_ZERODATA)!=0;
|
pPage->zeroData = (flags & PTF_ZERODATA)!=0;
|
||||||
pPage->leafData = (flags & PTF_LEAFDATA)!=0;
|
pPage->leafData = (flags & PTF_LEAFDATA)!=0;
|
||||||
@@ -913,8 +903,8 @@ static void releasePage(MemPage *pPage){
|
|||||||
** reaches zero. We need to unref the pParent pointer when that
|
** reaches zero. We need to unref the pParent pointer when that
|
||||||
** happens.
|
** happens.
|
||||||
*/
|
*/
|
||||||
static void pageDestructor(void *pData){
|
static void pageDestructor(void *pData, int pageSize){
|
||||||
MemPage *pPage = (MemPage*)&((char*)pData)[SQLITE_PAGE_SIZE];
|
MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
|
||||||
assert( pPage->isInit==0 || pPage->needRelink==0 );
|
assert( pPage->isInit==0 || pPage->needRelink==0 );
|
||||||
if( pPage->pParent ){
|
if( pPage->pParent ){
|
||||||
MemPage *pParent = pPage->pParent;
|
MemPage *pParent = pPage->pParent;
|
||||||
@@ -978,29 +968,11 @@ int sqlite3BtreeOpen(
|
|||||||
pBt->pPage1 = 0;
|
pBt->pPage1 = 0;
|
||||||
pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
|
pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
|
||||||
pBt->pageSize = SQLITE_PAGE_SIZE; /* FIX ME - read from header */
|
pBt->pageSize = SQLITE_PAGE_SIZE; /* FIX ME - read from header */
|
||||||
|
pBt->usableSize = pBt->pageSize;
|
||||||
pBt->maxEmbedFrac = 64; /* FIX ME - read from header */
|
pBt->maxEmbedFrac = 64; /* FIX ME - read from header */
|
||||||
pBt->minEmbedFrac = 32; /* FIX ME - read from header */
|
pBt->minEmbedFrac = 32; /* FIX ME - read from header */
|
||||||
pBt->minLeafFrac = 32; /* FIX ME - read from header */
|
pBt->minLeafFrac = 32; /* FIX ME - read from header */
|
||||||
|
|
||||||
/* 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 next cell
|
|
||||||
** 4-byte child pointer
|
|
||||||
** 9-byte nKey value
|
|
||||||
** 4-byte nData value
|
|
||||||
** 4-byte overflow page pointer
|
|
||||||
** So a cell consists of a header which is as much as 19 bytes long,
|
|
||||||
** 0 to N bytes of payload, and an optional 4 byte overflow page pointer.
|
|
||||||
*/
|
|
||||||
assert(pBt->maxEmbedFrac>0 && 255/pBt->maxEmbedFrac>=3 );
|
|
||||||
pBt->maxLocal = (pBt->pageSize-10)*pBt->maxEmbedFrac/255 - 23;
|
|
||||||
pBt->minLocal = (pBt->pageSize-10)*pBt->minEmbedFrac/255 - 23;
|
|
||||||
pBt->maxLeaf = pBt->pageSize - 33;
|
|
||||||
pBt->minLeaf = (pBt->pageSize-10)*pBt->minLeafFrac/255 - 23;
|
|
||||||
|
|
||||||
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE );
|
|
||||||
*ppBtree = pBt;
|
*ppBtree = pBt;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -1071,15 +1043,47 @@ static int lockBtree(Btree *pBt){
|
|||||||
/* Do some checking to help insure the file we opened really is
|
/* Do some checking to help insure the file we opened really is
|
||||||
** a valid database file.
|
** a valid database file.
|
||||||
*/
|
*/
|
||||||
|
rc = SQLITE_NOTADB;
|
||||||
if( sqlite3pager_pagecount(pBt->pPager)>0 ){
|
if( sqlite3pager_pagecount(pBt->pPager)>0 ){
|
||||||
if( memcmp(pPage1->aData, zMagicHeader, 16)!=0 ){
|
u8 *page1 = pPage1->aData;
|
||||||
rc = SQLITE_NOTADB;
|
if( memcmp(page1, zMagicHeader, 16)!=0 ){
|
||||||
goto page1_init_failed;
|
goto page1_init_failed;
|
||||||
}
|
}
|
||||||
/*** TBD: Other header checks such as page size ****/
|
if( page1[18]>1 || page1[19]>1 ){
|
||||||
|
goto page1_init_failed;
|
||||||
|
}
|
||||||
|
pBt->pageSize = get2byte(&page1[16]);
|
||||||
|
pBt->usableSize = pBt->pageSize - page1[20];
|
||||||
|
if( pBt->usableSize<500 ){
|
||||||
|
goto page1_init_failed;
|
||||||
|
}
|
||||||
|
pBt->maxEmbedFrac = page1[21];
|
||||||
|
pBt->minEmbedFrac = page1[22];
|
||||||
|
pBt->minLeafFrac = page1[23];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 next cell
|
||||||
|
** 4-byte child pointer
|
||||||
|
** 9-byte nKey value
|
||||||
|
** 4-byte nData value
|
||||||
|
** 4-byte overflow page pointer
|
||||||
|
** So a cell consists of a header which is as much as 19 bytes long,
|
||||||
|
** 0 to N bytes of payload, and an optional 4 byte overflow page pointer.
|
||||||
|
*/
|
||||||
|
pBt->maxLocal = (pBt->usableSize-10)*pBt->maxEmbedFrac/255 - 23;
|
||||||
|
pBt->minLocal = (pBt->usableSize-10)*pBt->minEmbedFrac/255 - 23;
|
||||||
|
pBt->maxLeaf = pBt->usableSize - 33;
|
||||||
|
pBt->minLeaf = (pBt->usableSize-10)*pBt->minLeafFrac/255 - 23;
|
||||||
|
if( pBt->minLocal>pBt->maxLocal || pBt->maxLocal<0 ){
|
||||||
|
goto page1_init_failed;
|
||||||
|
}
|
||||||
|
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE );
|
||||||
pBt->pPage1 = pPage1;
|
pBt->pPage1 = pPage1;
|
||||||
return rc;
|
return SQLITE_OK;
|
||||||
|
|
||||||
page1_init_failed:
|
page1_init_failed:
|
||||||
releasePage(pPage1);
|
releasePage(pPage1);
|
||||||
@@ -1122,10 +1126,14 @@ static int newDatabase(Btree *pBt){
|
|||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
|
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
|
||||||
assert( sizeof(zMagicHeader)==16 );
|
assert( sizeof(zMagicHeader)==16 );
|
||||||
put2byte(&data[16], SQLITE_PAGE_SIZE);
|
put2byte(&data[16], pBt->pageSize);
|
||||||
data[18] = 1;
|
data[18] = 1;
|
||||||
data[19] = 1;
|
data[19] = 1;
|
||||||
put2byte(&data[22], (SQLITE_PAGE_SIZE-10)/4-12);
|
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 );
|
zeroPage(pP1, PTF_INTKEY|PTF_LEAF );
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -1605,7 +1613,7 @@ static int getPayload(
|
|||||||
if( amt>0 ){
|
if( amt>0 ){
|
||||||
nextPage = get4byte(&aPayload[info.nLocal]);
|
nextPage = get4byte(&aPayload[info.nLocal]);
|
||||||
}
|
}
|
||||||
ovflSize = pBt->pageSize - 4;
|
ovflSize = pBt->usableSize - 4;
|
||||||
while( amt>0 && nextPage ){
|
while( amt>0 && nextPage ){
|
||||||
rc = sqlite3pager_get(pBt->pPager, nextPage, (void**)&aPayload);
|
rc = sqlite3pager_get(pBt->pPager, nextPage, (void**)&aPayload);
|
||||||
if( rc!=0 ){
|
if( rc!=0 ){
|
||||||
@@ -2330,7 +2338,7 @@ static int freePage(MemPage *pPage){
|
|||||||
rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
|
rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
k = get4byte(&pTrunk->aData[4]);
|
k = get4byte(&pTrunk->aData[4]);
|
||||||
if( k==pBt->pageSize/4 - 8 ){
|
if( k==pBt->usableSize/4 - 8 ){
|
||||||
/* The trunk is full. Turn the page being freed into a new
|
/* The trunk is full. Turn the page being freed into a new
|
||||||
** trunk page with no leaves. */
|
** trunk page with no leaves. */
|
||||||
rc = sqlite3pager_write(pPage->aData);
|
rc = sqlite3pager_write(pPage->aData);
|
||||||
@@ -2458,7 +2466,7 @@ static int fillInCell(
|
|||||||
pPrior = pOvfl->aData;
|
pPrior = pOvfl->aData;
|
||||||
put4byte(pPrior, 0);
|
put4byte(pPrior, 0);
|
||||||
pPayload = &pOvfl->aData[4];
|
pPayload = &pOvfl->aData[4];
|
||||||
spaceLeft = pBt->pageSize - 4;
|
spaceLeft = pBt->usableSize - 4;
|
||||||
}
|
}
|
||||||
n = nPayload;
|
n = nPayload;
|
||||||
if( n>spaceLeft ) n = spaceLeft;
|
if( n>spaceLeft ) n = spaceLeft;
|
||||||
@@ -2491,7 +2499,7 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
|
|||||||
assert( pBt->pPager!=0 );
|
assert( pBt->pPager!=0 );
|
||||||
aData = sqlite3pager_lookup(pBt->pPager, pgno);
|
aData = sqlite3pager_lookup(pBt->pPager, pgno);
|
||||||
if( aData ){
|
if( aData ){
|
||||||
pThis = (MemPage*)&aData[pBt->pageSize];
|
pThis = (MemPage*)&aData[pBt->usableSize];
|
||||||
if( pThis->isInit ){
|
if( pThis->isInit ){
|
||||||
if( pThis->pParent!=pNewParent ){
|
if( pThis->pParent!=pNewParent ){
|
||||||
if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData);
|
if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData);
|
||||||
@@ -2548,10 +2556,10 @@ static void dropCell(MemPage *pPage, int idx, int sz){
|
|||||||
assert( sz==cellSize(pPage, pPage->aCell[idx]) );
|
assert( sz==cellSize(pPage, pPage->aCell[idx]) );
|
||||||
assert( sqlite3pager_iswriteable(pPage->aData) );
|
assert( sqlite3pager_iswriteable(pPage->aData) );
|
||||||
assert( pPage->aCell[idx]>=pPage->aData );
|
assert( pPage->aCell[idx]>=pPage->aData );
|
||||||
assert( pPage->aCell[idx]<=&pPage->aData[pPage->pBt->pageSize-sz] );
|
assert( pPage->aCell[idx]<=&pPage->aData[pPage->pBt->usableSize-sz] );
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
pc = Addr(pPage->aCell[idx]) - Addr(data);
|
pc = Addr(pPage->aCell[idx]) - Addr(data);
|
||||||
assert( pc>pPage->hdrOffset && pc+sz<=pPage->pBt->pageSize );
|
assert( pc>pPage->hdrOffset && pc+sz<=pPage->pBt->usableSize );
|
||||||
freeSpace(pPage, pc, sz);
|
freeSpace(pPage, pc, sz);
|
||||||
for(j=idx; j<pPage->nCell-1; j++){
|
for(j=idx; j<pPage->nCell-1; j++){
|
||||||
pPage->aCell[j] = pPage->aCell[j+1];
|
pPage->aCell[j] = pPage->aCell[j+1];
|
||||||
@@ -2654,7 +2662,7 @@ static void relinkCellList(MemPage *pPage){
|
|||||||
idxFrom = pPage->hdrOffset+3;
|
idxFrom = pPage->hdrOffset+3;
|
||||||
for(i=0; i<pPage->nCell; i++){
|
for(i=0; i<pPage->nCell; i++){
|
||||||
int idx = Addr(pPage->aCell[i]) - Addr(pPage->aData);
|
int idx = Addr(pPage->aCell[i]) - Addr(pPage->aData);
|
||||||
assert( idx>pPage->hdrOffset && idx<pPage->pBt->pageSize );
|
assert( idx>pPage->hdrOffset && idx<pPage->pBt->usableSize );
|
||||||
put2byte(&pPage->aData[idxFrom], idx);
|
put2byte(&pPage->aData[idxFrom], idx);
|
||||||
idxFrom = idx;
|
idxFrom = idx;
|
||||||
}
|
}
|
||||||
@@ -2681,15 +2689,15 @@ static void relinkCellList(MemPage *pPage){
|
|||||||
static void movePage(MemPage *pTo, MemPage *pFrom){
|
static void movePage(MemPage *pTo, MemPage *pFrom){
|
||||||
uptr from, to;
|
uptr from, to;
|
||||||
int i;
|
int i;
|
||||||
int pageSize;
|
int usableSize;
|
||||||
int ofst;
|
int ofst;
|
||||||
|
|
||||||
assert( pTo->hdrOffset==0 );
|
assert( pTo->hdrOffset==0 );
|
||||||
assert( pFrom->isInit );
|
assert( pFrom->isInit );
|
||||||
ofst = pFrom->hdrOffset;
|
ofst = pFrom->hdrOffset;
|
||||||
pageSize = pFrom->pBt->pageSize;
|
usableSize = pFrom->pBt->usableSize;
|
||||||
sqliteFree(pTo->aCell);
|
sqliteFree(pTo->aCell);
|
||||||
memcpy(pTo->aData, &pFrom->aData[ofst], pageSize - ofst);
|
memcpy(pTo->aData, &pFrom->aData[ofst], usableSize - ofst);
|
||||||
memcpy(pTo, pFrom, offsetof(MemPage, aData));
|
memcpy(pTo, pFrom, offsetof(MemPage, aData));
|
||||||
pFrom->isInit = 0;
|
pFrom->isInit = 0;
|
||||||
pFrom->aCell = 0;
|
pFrom->aCell = 0;
|
||||||
@@ -2700,7 +2708,7 @@ static void movePage(MemPage *pTo, MemPage *pFrom){
|
|||||||
from = Addr(&pFrom->aData[ofst]);
|
from = Addr(&pFrom->aData[ofst]);
|
||||||
for(i=0; i<pTo->nCell; i++){
|
for(i=0; i<pTo->nCell; i++){
|
||||||
uptr x = Addr(pTo->aCell[i]);
|
uptr x = Addr(pTo->aCell[i]);
|
||||||
if( x>from && x<from+pageSize-ofst ){
|
if( x>from && x<from+usableSize-ofst ){
|
||||||
*((uptr*)&pTo->aCell[i]) = x + to - from;
|
*((uptr*)&pTo->aCell[i]) = x + to - from;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2772,6 +2780,7 @@ static int balance(MemPage *pPage){
|
|||||||
int usableSpace; /* Bytes in pPage beyond the header */
|
int usableSpace; /* Bytes in pPage beyond the header */
|
||||||
int pageFlags; /* Value of pPage->aData[0] */
|
int pageFlags; /* Value of pPage->aData[0] */
|
||||||
int subtotal; /* Subtotal of bytes in cells on one page */
|
int subtotal; /* Subtotal of bytes in cells on one page */
|
||||||
|
int iSpace = 0; /* First unused byte of aSpace[] */
|
||||||
MemPage *extraUnref = 0; /* Unref this page if not zero */
|
MemPage *extraUnref = 0; /* Unref this page if not zero */
|
||||||
MemPage *apOld[NB]; /* pPage and up to two siblings */
|
MemPage *apOld[NB]; /* pPage and up to two siblings */
|
||||||
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
|
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
|
||||||
@@ -2780,13 +2789,12 @@ static int balance(MemPage *pPage){
|
|||||||
Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */
|
Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */
|
||||||
int idxDiv[NB]; /* Indices of divider cells in pParent */
|
int idxDiv[NB]; /* Indices of divider cells in pParent */
|
||||||
u8 *apDiv[NB]; /* Divider cells in pParent */
|
u8 *apDiv[NB]; /* Divider cells in pParent */
|
||||||
u8 aTemp[NB][MX_CELL_SIZE]; /* Temporary holding area for apDiv[] */
|
|
||||||
u8 aInsBuf[NB][MX_CELL_SIZE];/* Space to hold dividers cells during insert */
|
|
||||||
int cntNew[NB+1]; /* Index in aCell[] of cell after i-th page */
|
int cntNew[NB+1]; /* Index in aCell[] of cell after i-th page */
|
||||||
int szNew[NB+1]; /* Combined size of cells place on i-th page */
|
int szNew[NB+1]; /* Combined size of cells place on i-th page */
|
||||||
u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
|
u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
|
||||||
int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
|
int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
|
||||||
u8 aCopy[NB][MX_PAGE_SIZE+sizeof(MemPage)]; /* Space for apCopy[] */
|
u8 aCopy[NB][MX_PAGE_SIZE+sizeof(MemPage)]; /* Space for apCopy[] */
|
||||||
|
u8 aSpace[MX_PAGE_SIZE*4]; /* Space to copies of divider cells */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return without doing any work if pPage is neither overfull nor
|
** Return without doing any work if pPage is neither overfull nor
|
||||||
@@ -2795,7 +2803,7 @@ static int balance(MemPage *pPage){
|
|||||||
assert( pPage->isInit );
|
assert( pPage->isInit );
|
||||||
assert( sqlite3pager_iswriteable(pPage->aData) );
|
assert( sqlite3pager_iswriteable(pPage->aData) );
|
||||||
pBt = pPage->pBt;
|
pBt = pPage->pBt;
|
||||||
if( !pPage->isOverfull && pPage->nFree<pBt->pageSize*2/3 && pPage->nCell>=2){
|
if( !pPage->isOverfull && pPage->nFree<pBt->usableSize*2/3 && pPage->nCell>=2){
|
||||||
relinkCellList(pPage);
|
relinkCellList(pPage);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -2851,7 +2859,7 @@ static int balance(MemPage *pPage){
|
|||||||
TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno));
|
TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
memcpy(pPage->aData, pChild->aData, pBt->pageSize);
|
memcpy(pPage->aData, pChild->aData, pBt->usableSize);
|
||||||
pPage->isInit = 0;
|
pPage->isInit = 0;
|
||||||
pPage->pParent = 0;
|
pPage->pParent = 0;
|
||||||
rc = initPage(pPage, 0);
|
rc = initPage(pPage, 0);
|
||||||
@@ -2974,7 +2982,7 @@ static int balance(MemPage *pPage){
|
|||||||
*/
|
*/
|
||||||
for(i=0; i<nOld; i++){
|
for(i=0; i<nOld; i++){
|
||||||
MemPage *p = apCopy[i] = (MemPage*)&aCopy[i+1][-sizeof(MemPage)];
|
MemPage *p = apCopy[i] = (MemPage*)&aCopy[i+1][-sizeof(MemPage)];
|
||||||
p->aData = &((u8*)p)[-pBt->pageSize];
|
p->aData = &((u8*)p)[-pBt->usableSize];
|
||||||
p->aCell = 0;
|
p->aCell = 0;
|
||||||
p->hdrOffset = 0;
|
p->hdrOffset = 0;
|
||||||
movePage(p, apOld[i]);
|
movePage(p, apOld[i]);
|
||||||
@@ -2983,11 +2991,12 @@ static int balance(MemPage *pPage){
|
|||||||
/*
|
/*
|
||||||
** Load pointers to all cells on sibling pages and the divider cells
|
** Load pointers to all cells on sibling pages and the divider cells
|
||||||
** into the local apCell[] array. Make copies of the divider cells
|
** into the local apCell[] array. Make copies of the divider cells
|
||||||
** into aTemp[] and remove the the divider Cells from pParent.
|
** into space obtained form aSpace[] and remove the the divider Cells
|
||||||
|
** from pParent.
|
||||||
**
|
**
|
||||||
** If the siblings are on leaf pages, then the child pointers of the
|
** If the siblings are on leaf pages, then the child pointers of the
|
||||||
** divider cells are stripped from the cells before they are copied
|
** divider cells are stripped from the cells before they are copied
|
||||||
** into aTemp[]. In this wall, all cells in apCell[] are without
|
** into aSpace[]. In this wall, all cells in apCell[] are without
|
||||||
** child pointers. If siblings are not leaves, then all cell in
|
** child pointers. If siblings are not leaves, then all cell in
|
||||||
** apCell[] include child pointers. Either way, all cells in apCell[]
|
** apCell[] include child pointers. Either way, all cells in apCell[]
|
||||||
** are alike.
|
** are alike.
|
||||||
@@ -3003,16 +3012,20 @@ static int balance(MemPage *pPage){
|
|||||||
nCell++;
|
nCell++;
|
||||||
}
|
}
|
||||||
if( i<nOld-1 ){
|
if( i<nOld-1 ){
|
||||||
|
int sz = cellSize(pParent, apDiv[i]);
|
||||||
if( leafData ){
|
if( leafData ){
|
||||||
int sz = cellSize(pParent, apDiv[i]);
|
|
||||||
dropCell(pParent, nxDiv, sz);
|
dropCell(pParent, nxDiv, sz);
|
||||||
}else{
|
}else{
|
||||||
szCell[nCell] = cellSize(pParent, apDiv[i]);
|
u8 *pTemp;
|
||||||
memcpy(aTemp[i], apDiv[i], szCell[nCell]);
|
szCell[nCell] = sz;
|
||||||
apCell[nCell] = &aTemp[i][leafCorrection];
|
pTemp = &aSpace[iSpace];
|
||||||
dropCell(pParent, nxDiv, szCell[nCell]);
|
iSpace += sz;
|
||||||
|
assert( iSpace<=sizeof(aSpace) );
|
||||||
|
memcpy(pTemp, apDiv[i], sz);
|
||||||
|
apCell[nCell] = pTemp+leafCorrection;
|
||||||
|
dropCell(pParent, nxDiv, sz);
|
||||||
szCell[nCell] -= leafCorrection;
|
szCell[nCell] -= leafCorrection;
|
||||||
assert( get4byte(&aTemp[i][2])==pgnoOld[i] );
|
assert( get4byte(pTemp+2)==pgnoOld[i] );
|
||||||
if( !pOld->leaf ){
|
if( !pOld->leaf ){
|
||||||
assert( leafCorrection==0 );
|
assert( leafCorrection==0 );
|
||||||
/* The right pointer of the child page pOld becomes the left
|
/* The right pointer of the child page pOld becomes the left
|
||||||
@@ -3036,7 +3049,7 @@ static int balance(MemPage *pPage){
|
|||||||
** This little patch of code is critical for keeping the tree
|
** This little patch of code is critical for keeping the tree
|
||||||
** balanced.
|
** balanced.
|
||||||
*/
|
*/
|
||||||
usableSpace = pBt->pageSize - 10 + leafCorrection;
|
usableSpace = pBt->usableSize - 10 + leafCorrection;
|
||||||
for(subtotal=k=i=0; i<nCell; i++){
|
for(subtotal=k=i=0; i<nCell; i++){
|
||||||
subtotal += szCell[i];
|
subtotal += szCell[i];
|
||||||
if( subtotal > usableSpace ){
|
if( subtotal > usableSpace ){
|
||||||
@@ -3165,12 +3178,16 @@ static int balance(MemPage *pPage){
|
|||||||
CellInfo info;
|
CellInfo info;
|
||||||
j--;
|
j--;
|
||||||
parseCell(pNew, apCell[j], &info);
|
parseCell(pNew, apCell[j], &info);
|
||||||
pCell = aInsBuf[i];
|
pCell = &aSpace[iSpace];
|
||||||
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
|
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
|
||||||
|
iSpace += sz;
|
||||||
|
assert( iSpace<=sizeof(aSpace) );
|
||||||
pTemp = 0;
|
pTemp = 0;
|
||||||
}else{
|
}else{
|
||||||
pCell -= 4;
|
pCell -= 4;
|
||||||
pTemp = aInsBuf[i];
|
pTemp = &aSpace[iSpace];
|
||||||
|
iSpace += sz;
|
||||||
|
assert( iSpace<=sizeof(aSpace) );
|
||||||
}
|
}
|
||||||
insertCell(pParent, nxDiv, pCell, sz, pTemp);
|
insertCell(pParent, nxDiv, pCell, sz, pTemp);
|
||||||
put4byte(&pParent->aCell[nxDiv][2], pNew->pgno);
|
put4byte(&pParent->aCell[nxDiv][2], pNew->pgno);
|
||||||
@@ -3630,7 +3647,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
|
|||||||
i = 0;
|
i = 0;
|
||||||
assert( hdr == (pgno==1 ? 100 : 0) );
|
assert( hdr == (pgno==1 ? 100 : 0) );
|
||||||
idx = get2byte(&data[hdr+3]);
|
idx = get2byte(&data[hdr+3]);
|
||||||
while( idx>0 && idx<=pBt->pageSize ){
|
while( idx>0 && idx<=pBt->usableSize ){
|
||||||
CellInfo info;
|
CellInfo info;
|
||||||
Pgno child;
|
Pgno child;
|
||||||
unsigned char *pCell = &data[idx];
|
unsigned char *pCell = &data[idx];
|
||||||
@@ -3672,7 +3689,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
|
|||||||
nFree = 0;
|
nFree = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
idx = get2byte(&data[hdr+1]);
|
idx = get2byte(&data[hdr+1]);
|
||||||
while( idx>0 && idx<pPage->pBt->pageSize ){
|
while( idx>0 && idx<pPage->pBt->usableSize ){
|
||||||
int sz = get2byte(&data[idx+2]);
|
int sz = get2byte(&data[idx+2]);
|
||||||
sprintf(range,"%d..%d", idx, idx+sz-1);
|
sprintf(range,"%d..%d", idx, idx+sz-1);
|
||||||
nFree += sz;
|
nFree += sz;
|
||||||
@@ -3686,7 +3703,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
|
|||||||
}
|
}
|
||||||
if( recursive && !pPage->leaf ){
|
if( recursive && !pPage->leaf ){
|
||||||
idx = get2byte(&data[hdr+3]);
|
idx = get2byte(&data[hdr+3]);
|
||||||
while( idx>0 && idx<pBt->pageSize ){
|
while( idx>0 && idx<pBt->usableSize ){
|
||||||
unsigned char *pCell = &data[idx];
|
unsigned char *pCell = &data[idx];
|
||||||
sqlite3BtreePageDump(pBt, get4byte(&pCell[2]), 1);
|
sqlite3BtreePageDump(pBt, get4byte(&pCell[2]), 1);
|
||||||
idx = get2byte(pCell);
|
idx = get2byte(pCell);
|
||||||
@@ -3735,7 +3752,7 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult){
|
|||||||
aResult[4] = pPage->nFree;
|
aResult[4] = pPage->nFree;
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
idx = get2byte(&pPage->aData[pPage->hdrOffset+1]);
|
idx = get2byte(&pPage->aData[pPage->hdrOffset+1]);
|
||||||
while( idx>0 && idx<pPage->pBt->pageSize ){
|
while( idx>0 && idx<pPage->pBt->usableSize ){
|
||||||
cnt++;
|
cnt++;
|
||||||
idx = get2byte(&pPage->aData[idx]);
|
idx = get2byte(&pPage->aData[idx]);
|
||||||
}
|
}
|
||||||
@@ -3880,7 +3897,7 @@ static int checkTreePage(
|
|||||||
u8 *data;
|
u8 *data;
|
||||||
BtCursor cur;
|
BtCursor cur;
|
||||||
Btree *pBt;
|
Btree *pBt;
|
||||||
int maxLocal, pageSize;
|
int maxLocal, usableSize;
|
||||||
char zMsg[100];
|
char zMsg[100];
|
||||||
char zContext[100];
|
char zContext[100];
|
||||||
char hit[MX_PAGE_SIZE];
|
char hit[MX_PAGE_SIZE];
|
||||||
@@ -3888,7 +3905,7 @@ static int checkTreePage(
|
|||||||
/* Check that the page exists
|
/* Check that the page exists
|
||||||
*/
|
*/
|
||||||
cur.pBt = pBt = pCheck->pBt;
|
cur.pBt = pBt = pCheck->pBt;
|
||||||
pageSize = pBt->pageSize;
|
usableSize = pBt->usableSize;
|
||||||
if( iPage==0 ) return 0;
|
if( iPage==0 ) return 0;
|
||||||
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
|
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
|
||||||
if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){
|
if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){
|
||||||
@@ -3921,7 +3938,7 @@ static int checkTreePage(
|
|||||||
sz = info.nData;
|
sz = info.nData;
|
||||||
if( !pPage->intKey ) sz += info.nKey;
|
if( !pPage->intKey ) sz += info.nKey;
|
||||||
if( sz>info.nLocal ){
|
if( sz>info.nLocal ){
|
||||||
int nPage = (sz - info.nLocal + pageSize - 5)/(pageSize - 4);
|
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
|
||||||
checkList(pCheck, 0, get4byte(&pCell[info.iOverflow]),nPage,zContext);
|
checkList(pCheck, 0, get4byte(&pCell[info.iOverflow]),nPage,zContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3944,23 +3961,23 @@ static int checkTreePage(
|
|||||||
|
|
||||||
/* Check for complete coverage of the page
|
/* Check for complete coverage of the page
|
||||||
*/
|
*/
|
||||||
memset(hit, 0, pageSize);
|
memset(hit, 0, usableSize);
|
||||||
memset(hit, 1, pPage->hdrOffset+10-4*(pPage->leaf));
|
memset(hit, 1, pPage->hdrOffset+10-4*(pPage->leaf));
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
hdr = pPage->hdrOffset;
|
hdr = pPage->hdrOffset;
|
||||||
for(cnt=0, i=get2byte(&data[hdr+3]); i>0 && i<pageSize && cnt<10000; cnt++){
|
for(cnt=0, i=get2byte(&data[hdr+3]); i>0 && i<usableSize && cnt<10000; cnt++){
|
||||||
int size = cellSize(pPage, &data[i]);
|
int size = cellSize(pPage, &data[i]);
|
||||||
int j;
|
int j;
|
||||||
for(j=i+size-1; j>=i; j--) hit[j]++;
|
for(j=i+size-1; j>=i; j--) hit[j]++;
|
||||||
i = get2byte(&data[i]);
|
i = get2byte(&data[i]);
|
||||||
}
|
}
|
||||||
for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<pageSize && cnt<10000; cnt++){
|
for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; cnt++){
|
||||||
int size = get2byte(&data[i+2]);
|
int size = get2byte(&data[i+2]);
|
||||||
int j;
|
int j;
|
||||||
for(j=i+size-1; j>=i; j--) hit[j]++;
|
for(j=i+size-1; j>=i; j--) hit[j]++;
|
||||||
i = get2byte(&data[i]);
|
i = get2byte(&data[i]);
|
||||||
}
|
}
|
||||||
for(i=cnt=0; i<pageSize; i++){
|
for(i=cnt=0; i<usableSize; i++){
|
||||||
if( hit[i]==0 ){
|
if( hit[i]==0 ){
|
||||||
cnt++;
|
cnt++;
|
||||||
}else if( hit[i]>1 ){
|
}else if( hit[i]>1 ){
|
||||||
@@ -4070,7 +4087,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
|
|||||||
|
|
||||||
if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
|
if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
|
||||||
if( pBtTo->pCursor ) return SQLITE_BUSY;
|
if( pBtTo->pCursor ) return SQLITE_BUSY;
|
||||||
memcpy(pBtTo->pPage1, pBtFrom->pPage1, pBtFrom->pageSize);
|
memcpy(pBtTo->pPage1, pBtFrom->pPage1, pBtFrom->usableSize);
|
||||||
rc = sqlite3pager_overwrite(pBtTo->pPager, 1, pBtFrom->pPage1);
|
rc = sqlite3pager_overwrite(pBtTo->pPager, 1, pBtFrom->pPage1);
|
||||||
nToPage = sqlite3pager_pagecount(pBtTo->pPager);
|
nToPage = sqlite3pager_pagecount(pBtTo->pPager);
|
||||||
nPage = sqlite3pager_pagecount(pBtFrom->pPager);
|
nPage = sqlite3pager_pagecount(pBtFrom->pPager);
|
||||||
|
18
src/pager.c
18
src/pager.c
@@ -18,7 +18,7 @@
|
|||||||
** file simultaneously, or one process from reading the database while
|
** file simultaneously, or one process from reading the database while
|
||||||
** another is writing.
|
** another is writing.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.c,v 1.107 2004/05/12 13:30:08 drh Exp $
|
** @(#) $Id: pager.c,v 1.108 2004/05/14 01:58:13 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "os.h" /* Must be first to enable large file support */
|
#include "os.h" /* Must be first to enable large file support */
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@@ -181,14 +181,14 @@ struct Pager {
|
|||||||
u32 cksumInit; /* Quasi-random value added to every checksum */
|
u32 cksumInit; /* Quasi-random value added to every checksum */
|
||||||
int stmtNRec; /* Number of records in stmt subjournal */
|
int stmtNRec; /* Number of records in stmt subjournal */
|
||||||
int nExtra; /* Add this many bytes to each in-memory page */
|
int nExtra; /* Add this many bytes to each in-memory page */
|
||||||
void (*xDestructor)(void*); /* Call this routine when freeing pages */
|
void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
|
||||||
|
int pageSize; /* Number of bytes in a page */
|
||||||
int nPage; /* Total number of in-memory pages */
|
int nPage; /* Total number of in-memory pages */
|
||||||
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
|
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
|
||||||
int mxPage; /* Maximum number of pages to hold in cache */
|
int mxPage; /* Maximum number of pages to hold in cache */
|
||||||
int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
|
int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
|
||||||
void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
|
void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
|
||||||
void *pCodecArg; /* First argument to xCodec() */
|
void *pCodecArg; /* First argument to xCodec() */
|
||||||
int pageSize; /* Page size in bytes */
|
|
||||||
u8 journalOpen; /* True if journal file descriptors is valid */
|
u8 journalOpen; /* True if journal file descriptors is valid */
|
||||||
u8 journalStarted; /* True if header of journal is synced */
|
u8 journalStarted; /* True if header of journal is synced */
|
||||||
u8 useJournal; /* Use a rollback journal on this file */
|
u8 useJournal; /* Use a rollback journal on this file */
|
||||||
@@ -587,14 +587,16 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){
|
|||||||
** 1 which is held in use in order to keep the lock on the database
|
** 1 which is held in use in order to keep the lock on the database
|
||||||
** active.
|
** active.
|
||||||
*/
|
*/
|
||||||
|
void *pData;
|
||||||
assert( pPg->nRef==0 || pPg->pgno==1 );
|
assert( pPg->nRef==0 || pPg->pgno==1 );
|
||||||
memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
|
pData = PGHDR_TO_DATA(pPg);
|
||||||
|
memcpy(pData, pgRec.aData, pPager->pageSize);
|
||||||
if( pPager->xDestructor ){
|
if( pPager->xDestructor ){
|
||||||
pPager->xDestructor(PGHDR_TO_DATA(pPg));
|
pPager->xDestructor(pData, pPager->pageSize);
|
||||||
}
|
}
|
||||||
pPg->dirty = 0;
|
pPg->dirty = 0;
|
||||||
pPg->needSync = 0;
|
pPg->needSync = 0;
|
||||||
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
|
CODEC(pPager, pData, pPg->pgno, 3);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -1034,7 +1036,7 @@ int sqlite3pager_open(
|
|||||||
** The destructor is not called as a result sqlite3pager_close().
|
** The destructor is not called as a result sqlite3pager_close().
|
||||||
** Destructors are only called by sqlite3pager_unref().
|
** Destructors are only called by sqlite3pager_unref().
|
||||||
*/
|
*/
|
||||||
void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
|
void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*,int)){
|
||||||
pPager->xDestructor = xDesc;
|
pPager->xDestructor = xDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1708,7 +1710,7 @@ int sqlite3pager_unref(void *pData){
|
|||||||
pPager->pFirstSynced = pPg;
|
pPager->pFirstSynced = pPg;
|
||||||
}
|
}
|
||||||
if( pPager->xDestructor ){
|
if( pPager->xDestructor ){
|
||||||
pPager->xDestructor(pData);
|
pPager->xDestructor(pData, pPager->pageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When all pages reach the freelist, drop the read lock from
|
/* When all pages reach the freelist, drop the read lock from
|
||||||
|
@@ -13,11 +13,11 @@
|
|||||||
** subsystem. The page cache subsystem reads and writes a file a page
|
** subsystem. The page cache subsystem reads and writes a file a page
|
||||||
** at a time and provides a journal for rollback.
|
** at a time and provides a journal for rollback.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.h,v 1.28 2004/05/08 08:23:30 danielk1977 Exp $
|
** @(#) $Id: pager.h,v 1.29 2004/05/14 01:58:13 drh Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The size of one page
|
** The size of a page.
|
||||||
**
|
**
|
||||||
** You can change this value to another (reasonable) value you want.
|
** You can change this value to another (reasonable) value you want.
|
||||||
** It need not be a power of two, though the interface to the disk
|
** It need not be a power of two, though the interface to the disk
|
||||||
@@ -71,7 +71,7 @@ typedef struct Pager Pager;
|
|||||||
*/
|
*/
|
||||||
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
|
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
|
||||||
int nPage, int nExtra, int useJournal);
|
int nPage, int nExtra, int useJournal);
|
||||||
void sqlite3pager_set_destructor(Pager*, void(*)(void*));
|
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
|
||||||
void sqlite3pager_set_cachesize(Pager*, int);
|
void sqlite3pager_set_cachesize(Pager*, int);
|
||||||
int sqlite3pager_close(Pager *pPager);
|
int sqlite3pager_close(Pager *pPager);
|
||||||
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
|
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
|
||||||
@@ -103,6 +103,3 @@ void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
|
|||||||
void sqlite3pager_refdump(Pager*);
|
void sqlite3pager_refdump(Pager*);
|
||||||
int pager3_refinfo_enable;
|
int pager3_refinfo_enable;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user