mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Use a heap rather than a bitmap for cell coverage and overlap testing on
btree pages in PRAGMA integrity_check. FossilOrigin-Name: e94b2ef2242d716379a35dba3d2df1ac512c8d30
This commit is contained in:
13
manifest
13
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\sa\scouple\sof\sunreachable\sbranches.
|
C Use\sa\sheap\srather\sthan\sa\sbitmap\sfor\scell\scoverage\sand\soverlap\stesting\son\nbtree\spages\sin\sPRAGMA\sintegrity_check.
|
||||||
D 2015-04-16T20:27:09.079
|
D 2015-04-16T21:57:37.861
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a
|
F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -173,7 +173,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
|||||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||||
F src/btree.c c6e32d84442f79d5b96965265d65b3baa231dffc
|
F src/btree.c 127aceb71ba93f59bc9c6ba810e992a04299e98a
|
||||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||||
F src/build.c 01b969b20a44a3d9620e597d9af8242348123540
|
F src/build.c 01b969b20a44a3d9620e597d9af8242348123540
|
||||||
@@ -1250,7 +1250,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P 55d10baf0bffdb1a34bf5627ed8f25e4a4efd942
|
P 8f391dffcfe068d48f854784648610d8a86f6bc8 5619c959bf7babb19fd8ba8b228be7f090fe0ce3
|
||||||
R 114fb2d7e0df7ea2622d3974dda61e5a
|
R 72a6fa603587f85ee318933146285087
|
||||||
|
T +closed 5619c959bf7babb19fd8ba8b228be7f090fe0ce3
|
||||||
U drh
|
U drh
|
||||||
Z 08da3cff84a49c68f76471919d394d1c
|
Z e48be2bfe822e32604f22d78d2be1c02
|
||||||
|
@@ -1 +1 @@
|
|||||||
8f391dffcfe068d48f854784648610d8a86f6bc8
|
e94b2ef2242d716379a35dba3d2df1ac512c8d30
|
87
src/btree.c
87
src/btree.c
@@ -8528,6 +8528,57 @@ static void checkList(
|
|||||||
}
|
}
|
||||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** An implementation of a min-heap.
|
||||||
|
**
|
||||||
|
** aHeap[0] is the number of elements on the heap. aHeap[1] is the
|
||||||
|
** root element. The daughter nodes of aHeap[N] are aHeap[N*2]
|
||||||
|
** and aHeap[N*2+1].
|
||||||
|
**
|
||||||
|
** The heap property is this: Every node is less than or equal to both
|
||||||
|
** of its daughter nodes. A consequence of the heap property is that the
|
||||||
|
** root node aHeap[1] is always the minimum value current in the heap.
|
||||||
|
**
|
||||||
|
** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
|
||||||
|
** the heap, preserving the heap property. The btreeHeapPull() routine
|
||||||
|
** removes the root element from the heap (the minimum value in the heap)
|
||||||
|
** and then move other nodes around as necessary to preserve the heap
|
||||||
|
** property.
|
||||||
|
**
|
||||||
|
** This heap is used for cell overlap and coverage testing. Each u32
|
||||||
|
** entry represents the span of a cell or freeblock on a btree page.
|
||||||
|
** The upper 16 bits are the index of the first byte of a range and the
|
||||||
|
** lower 16 bits are the index of the last byte of that range.
|
||||||
|
*/
|
||||||
|
static void btreeHeapInsert(u32 *aHeap, u32 x){
|
||||||
|
u32 j, i = ++aHeap[0];
|
||||||
|
aHeap[i] = x;
|
||||||
|
while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
|
||||||
|
x = aHeap[j];
|
||||||
|
aHeap[j] = aHeap[i];
|
||||||
|
aHeap[i] = x;
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int btreeHeapPull(u32 *aHeap, u32 *pOut){
|
||||||
|
u32 j, i, x;
|
||||||
|
if( (x = aHeap[0])==0 ) return 0;
|
||||||
|
*pOut = aHeap[1];
|
||||||
|
aHeap[1] = aHeap[x];
|
||||||
|
aHeap[x] = 0xffffffff;
|
||||||
|
aHeap[0]--;
|
||||||
|
i = 1;
|
||||||
|
while( (j = i*2)<=aHeap[0] ){
|
||||||
|
if( aHeap[j]>aHeap[j+1] ) j++;
|
||||||
|
if( aHeap[i]<aHeap[j] ) break;
|
||||||
|
x = aHeap[i];
|
||||||
|
aHeap[i] = aHeap[j];
|
||||||
|
aHeap[j] = x;
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||||
/*
|
/*
|
||||||
** Do various sanity checks on a single page of a tree. Return
|
** Do various sanity checks on a single page of a tree. Return
|
||||||
@@ -8560,7 +8611,8 @@ static int checkTreePage(
|
|||||||
u8 *data;
|
u8 *data;
|
||||||
BtShared *pBt;
|
BtShared *pBt;
|
||||||
int usableSize;
|
int usableSize;
|
||||||
char *hit = 0;
|
u32 *heap = 0;
|
||||||
|
u32 x, prev = 0;
|
||||||
i64 nMinKey = 0;
|
i64 nMinKey = 0;
|
||||||
i64 nMaxKey = 0;
|
i64 nMaxKey = 0;
|
||||||
const char *saved_zPfx = pCheck->zPfx;
|
const char *saved_zPfx = pCheck->zPfx;
|
||||||
@@ -8705,15 +8757,15 @@ static int checkTreePage(
|
|||||||
*/
|
*/
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
hdr = pPage->hdrOffset;
|
hdr = pPage->hdrOffset;
|
||||||
hit = sqlite3PageMalloc( pBt->pageSize );
|
heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||||
pCheck->zPfx = 0;
|
pCheck->zPfx = 0;
|
||||||
if( hit==0 ){
|
if( heap==0 ){
|
||||||
pCheck->mallocFailed = 1;
|
pCheck->mallocFailed = 1;
|
||||||
}else{
|
}else{
|
||||||
int contentOffset = get2byteNotZero(&data[hdr+5]);
|
int contentOffset = get2byteNotZero(&data[hdr+5]);
|
||||||
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
||||||
memset(hit+contentOffset, 0, usableSize-contentOffset);
|
heap[0] = 0;
|
||||||
memset(hit, 1, contentOffset);
|
btreeHeapInsert(heap, contentOffset-1);
|
||||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||||
** number of cells on the page. */
|
** number of cells on the page. */
|
||||||
nCell = get2byte(&data[hdr+3]);
|
nCell = get2byte(&data[hdr+3]);
|
||||||
@@ -8725,7 +8777,6 @@ static int checkTreePage(
|
|||||||
for(i=0; i<nCell; i++){
|
for(i=0; i<nCell; i++){
|
||||||
int pc = get2byte(&data[cellStart+i*2]);
|
int pc = get2byte(&data[cellStart+i*2]);
|
||||||
u32 size = 65536;
|
u32 size = 65536;
|
||||||
int j;
|
|
||||||
if( pc<=usableSize-4 ){
|
if( pc<=usableSize-4 ){
|
||||||
size = cellSizePtr(pPage, &data[pc]);
|
size = cellSizePtr(pPage, &data[pc]);
|
||||||
}
|
}
|
||||||
@@ -8734,7 +8785,7 @@ static int checkTreePage(
|
|||||||
checkAppendMsg(pCheck,
|
checkAppendMsg(pCheck,
|
||||||
"Corruption detected in cell %d on page %d",i,iPage);
|
"Corruption detected in cell %d on page %d",i,iPage);
|
||||||
}else{
|
}else{
|
||||||
for(j=pc+size-1; j>=pc; j--) hit[j]++;
|
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
||||||
@@ -8746,7 +8797,7 @@ static int checkTreePage(
|
|||||||
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||||
size = get2byte(&data[i+2]);
|
size = get2byte(&data[i+2]);
|
||||||
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
|
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
|
||||||
for(j=i+size-1; j>=i; j--) hit[j]++;
|
btreeHeapInsert(heap, (i<<16)|(i+size-1));
|
||||||
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
||||||
** big-endian integer which is the offset in the b-tree page of the next
|
** big-endian integer which is the offset in the b-tree page of the next
|
||||||
** freeblock in the chain, or zero if the freeblock is the last on the
|
** freeblock in the chain, or zero if the freeblock is the last on the
|
||||||
@@ -8758,27 +8809,33 @@ static int checkTreePage(
|
|||||||
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||||
i = j;
|
i = j;
|
||||||
}
|
}
|
||||||
for(i=cnt=0; i<usableSize; i++){
|
cnt = 0;
|
||||||
if( hit[i]==0 ){
|
assert( heap[0]>0 );
|
||||||
cnt++;
|
assert( (heap[1]>>16)==0 );
|
||||||
}else if( hit[i]>1 ){
|
btreeHeapPull(heap,&prev);
|
||||||
|
while( btreeHeapPull(heap,&x) ){
|
||||||
|
if( (prev&0xffff)+1>(x>>16) ){
|
||||||
checkAppendMsg(pCheck,
|
checkAppendMsg(pCheck,
|
||||||
"Multiple uses for byte %d of page %d", i, iPage);
|
"Multiple uses for byte %u of page %d", x>>16, iPage);
|
||||||
break;
|
break;
|
||||||
|
}else{
|
||||||
|
cnt += (x>>16) - (prev&0xffff) - 1;
|
||||||
|
prev = x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cnt += usableSize - (prev&0xffff) - 1;
|
||||||
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
|
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
|
||||||
** is stored in the fifth field of the b-tree page header.
|
** is stored in the fifth field of the b-tree page header.
|
||||||
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
|
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
|
||||||
** number of fragmented free bytes within the cell content area.
|
** number of fragmented free bytes within the cell content area.
|
||||||
*/
|
*/
|
||||||
if( cnt!=data[hdr+7] ){
|
if( heap[0]==0 && cnt!=data[hdr+7] ){
|
||||||
checkAppendMsg(pCheck,
|
checkAppendMsg(pCheck,
|
||||||
"Fragmentation of %d bytes reported as %d on page %d",
|
"Fragmentation of %d bytes reported as %d on page %d",
|
||||||
cnt, data[hdr+7], iPage);
|
cnt, data[hdr+7], iPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3PageFree(hit);
|
sqlite3PageFree(heap);
|
||||||
releasePage(pPage);
|
releasePage(pPage);
|
||||||
|
|
||||||
end_of_check:
|
end_of_check:
|
||||||
|
Reference in New Issue
Block a user