From: drh Date: Wed, 19 Nov 2008 18:30:29 +0000 (+0000) Subject: Update the SECURE_DELETE code to track the latest changes in the pager. (CVS 5928) X-Git-Tag: version-3.6.10~249 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1feb7dd391b5def9116f0407972ea0913ddde3a9;p=thirdparty%2Fsqlite.git Update the SECURE_DELETE code to track the latest changes in the pager. (CVS 5928) FossilOrigin-Name: e058f509374e98e48eafeba2f1dadff9633d1190 --- diff --git a/manifest b/manifest index 8e5622f72f..1db5c82e5e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\scompiler\swarnings\sthat\sshow\sup\swhen\sbuilding\sthe\samalgamation\sonly.\s(CVS\s5927) -D 2008-11-19T16:52:44 +C Update\sthe\sSECURE_DELETE\scode\sto\strack\sthe\slatest\schanges\sin\sthe\spager.\s(CVS\s5928) +D 2008-11-19T18:30:29 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 0aa7bbe3be6acc4045706e3bb3fd0b8f38f4a3b5 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -98,7 +98,7 @@ F src/alter.c 0a00c184052b7fd20271e783f65fec4efec6fe30 F src/analyze.c 301a1358f4f4d84d96608927d8ddcf471c53ad9a F src/attach.c 85c6a3d0daf11965b47604190d7cf5597dc88382 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 -F src/bitvec.c 9e922b2577b7e46d8f95349bca6a52f7674d7582 +F src/bitvec.c 4300d311b17fb3c1476623fd895a8feac02a0b08 F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a F src/btree.c 76c1b09263b6f028b4f84bd6d811e9d017448216 F src/btree.h 179c3ea813780df78a289a8f5130db18e6d4616e @@ -139,7 +139,7 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c d12285d66df674c42f6f544a6f7c21bf1a954ee1 F src/os_unix.c 03c76b5269361adcd68cf9d6713181922535ac6e F src/os_win.c 08d0b059ac01f32e8813bb96fc573486592b83f5 -F src/pager.c ae5da38b6415bdd88e56a2a484f29282c4ea09f5 +F src/pager.c db12a8333e54e7bbf62dc621ada5507adb3a6493 F src/pager.h a02ef8e6cc7e78b54874166e5ce786c9d4c489bf F src/parse.y 2c4758b4c5ead6de8cf7112f5a7cce7561d313fe F src/pcache.c f3121a531745b20f5b824201eb63949a7e2959ac @@ -233,7 +233,7 @@ F test/bigfile.test 9a6a8346e4042d9c781ed6cb6553ac871ae30618 F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747 F test/bind.test 1134441f1ea47abd1c740090435a6ecbe9ceb263 F test/bindxfer.test d4f573750e06c34ef2309acb95ad57da1d3c983f -F test/bitvec.test 62a512c3f7041d1df12558eb25990e5a19820571 +F test/bitvec.test ecea9aa315f36991e56e326701279b7775cb2bef F test/blob.test 2a38d867bdf08f9ce081776acec1ac8d4bca66be F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9 @@ -659,7 +659,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 70b2f6839ca97dfc08f72875283f5c75c8fcf0cc -R a6290aee52476a40993da5bd0918f0b1 -U danielk1977 -Z dc69f77ff700b57401f380f9e520f0dd +P d1abe8a1c9a990b02c71d6c249436381c9fde443 +R 28c8816dfcd8d3fc398d31f18c45452f +U drh +Z e8976cc9cb4c6c0e128dc1d970073d42 diff --git a/manifest.uuid b/manifest.uuid index 63a7b9dbe2..ea8123bf6c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d1abe8a1c9a990b02c71d6c249436381c9fde443 \ No newline at end of file +e058f509374e98e48eafeba2f1dadff9633d1190 \ No newline at end of file diff --git a/src/bitvec.c b/src/bitvec.c index bd6c98d1bc..3a28a8004f 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -34,21 +34,42 @@ ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** -** @(#) $Id: bitvec.c,v 1.8 2008/11/11 15:48:48 drh Exp $ +** @(#) $Id: bitvec.c,v 1.9 2008/11/19 18:30:35 shane Exp $ */ #include "sqliteInt.h" +/* Size of the Bitvec structure in bytes. */ #define BITVEC_SZ 512 + /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ -#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*)) -#define BITVEC_NCHAR BITVEC_USIZE -#define BITVEC_NBIT (BITVEC_NCHAR*8) -#define BITVEC_NINT (BITVEC_USIZE/4) +#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) + +/* Type of the array "element" for the bitmap representation. +** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. +** Setting this to the "natural word" size of your CPU may improve +** performance. */ +#define BITVEC_TELEM u8 +/* Size, in bits, of the bitmap element. */ +#define BITVEC_SZELEM 8 +/* Number of elements in a bitmap array. */ +#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM)) +/* Number of bits in the bitmap array. */ +#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM) + +/* Number of u32 values in hash table. */ +#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32)) +/* Maximum number of entries in hash table before +** sub-dividing and re-hashing. */ #define BITVEC_MXHASH (BITVEC_NINT/2) +/* Hashing function for the aHash representation. +** Empirical testing showed that the *37 multiplier +** (an arbitrary prime)in the hash function provided +** no fewer collisions than the no-op *1. */ +#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT) + #define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) -#define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT) /* ** A bitmap is an instance of the following structure. @@ -72,11 +93,15 @@ ** to hold deal with values between 1 and iDivisor. */ struct Bitvec { - u32 iSize; /* Maximum bit index */ - u32 nSet; /* Number of bits that are set */ - u32 iDivisor; /* Number of bits handled by each apSub[] entry */ + u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */ + u32 nSet; /* Number of bits that are set - only valid for aHash element */ + /* Max nSet is BITVEC_NINT. For BITVEC_SZ of 512, this would be 125. */ + u32 iDivisor; /* Number of bits handled by each apSub[] entry. */ + /* Should >=0 for apSub element. */ + /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */ + /* For a BITVEC_SZ of 512, this would be 34,359,739. */ union { - u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */ + BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ u32 aHash[BITVEC_NINT]; /* Hash table representation */ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ } u; @@ -105,16 +130,19 @@ Bitvec *sqlite3BitvecCreate(u32 iSize){ int sqlite3BitvecTest(Bitvec *p, u32 i){ if( p==0 ) return 0; if( i>p->iSize || i==0 ) return 0; - if( p->iSize<=BITVEC_NBIT ){ - i--; - return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0; + i--; + while( p->iDivisor ){ + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; + p = p->u.apSub[bin]; + if (!p) { + return 0; + } } - if( p->iDivisor>0 ){ - u32 bin = (i-1)/p->iDivisor; - i = (i-1)%p->iDivisor + 1; - return sqlite3BitvecTest(p->u.apSub[bin], i); - }else{ - u32 h = BITVEC_HASH(i); + if( p->iSize<=BITVEC_NBIT ){ + return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; + } else{ + u32 h = BITVEC_HASH(i++); while( p->u.aHash[h] ){ if( p->u.aHash[h]==i ) return 1; h++; @@ -141,35 +169,50 @@ int sqlite3BitvecSet(Bitvec *p, u32 i){ assert( p!=0 ); assert( i>0 ); assert( i<=p->iSize ); - if( p->iSize<=BITVEC_NBIT ){ - i--; - p->u.aBitmap[i/8] |= 1 << (i&7); - return SQLITE_OK; - } - if( p->iDivisor ){ - u32 bin = (i-1)/p->iDivisor; - i = (i-1)%p->iDivisor + 1; + i--; + while((p->iSize > BITVEC_NBIT) && p->iDivisor) { + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; if( p->u.apSub[bin]==0 ){ sqlite3BeginBenignMalloc(); p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); sqlite3EndBenignMalloc(); if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; } - return sqlite3BitvecSet(p->u.apSub[bin], i); + p = p->u.apSub[bin]; } - h = BITVEC_HASH(i); - while( p->u.aHash[h] ){ + if( p->iSize<=BITVEC_NBIT ){ + p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1)); + return SQLITE_OK; + } + h = BITVEC_HASH(i++); + /* if there wasn't a hash collision, and this doesn't */ + /* completely fill the hash, then just add it without */ + /* worring about sub-dividing and re-hashing. */ + if( !p->u.aHash[h] ){ + if (p->nSet<(BITVEC_NINT-1)) { + goto bitvec_set_end; + } else { + goto bitvec_set_rehash; + } + } + /* there was a collision, check to see if it's already */ + /* in hash, if not, try to find a spot for it */ + do { if( p->u.aHash[h]==i ) return SQLITE_OK; h++; - if( h==BITVEC_NINT ) h = 0; - } - p->nSet++; + if( h>=BITVEC_NINT ) h = 0; + } while( p->u.aHash[h] ); + /* we didn't find it in the hash. h points to the first */ + /* available free spot. check to see if this is going to */ + /* make our hash too "full". */ +bitvec_set_rehash: if( p->nSet>=BITVEC_MXHASH ){ unsigned int j; int rc; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); + memset(p->u.apSub, 0, sizeof(aiValues)); p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; rc = sqlite3BitvecSet(p, i); for(j=0; jnSet++; p->u.aHash[h] = i; return SQLITE_OK; } /* -** Clear the i-th bit. Return 0 on success and an error code if -** anything goes wrong. +** Clear the i-th bit. */ void sqlite3BitvecClear(Bitvec *p, u32 i){ assert( p!=0 ); assert( i>0 ); - if( p->iSize<=BITVEC_NBIT ){ - i--; - p->u.aBitmap[i/8] &= ~(1 << (i&7)); - }else if( p->iDivisor ){ - u32 bin = (i-1)/p->iDivisor; - i = (i-1)%p->iDivisor + 1; - if( p->u.apSub[bin] ){ - sqlite3BitvecClear(p->u.apSub[bin], i); + i--; + while( p->iDivisor ){ + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; + p = p->u.apSub[bin]; + if (!p) { + return; } + } + if( p->iSize<=BITVEC_NBIT ){ + p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1))); }else{ unsigned int j; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); + memset(p->u.aHash, 0, sizeof(aiValues)); p->nSet = 0; for(j=0; jnSet++; + while( p->u.aHash[h] ){ + h++; + if( h>=BITVEC_NINT ) h = 0; + } + p->u.aHash[h] = aiValues[j]; } } } diff --git a/src/pager.c b/src/pager.c index 71568c60c3..6d5783ec99 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.505 2008/11/19 10:22:33 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.506 2008/11/19 18:30:29 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -3488,7 +3488,8 @@ void sqlite3PagerDontRollback(DbPage *pPg){ } #ifdef SQLITE_SECURE_DELETE - if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || pPg->pgno>pPager->origDbSize ){ + if( sqlite3BitvecTest(pPager->pInJournal, pPg->pgno)!=0 + || pPg->pgno>pPager->origDbSize ){ return; } #endif diff --git a/test/bitvec.test b/test/bitvec.test index aff2bf7fca..24da959f01 100644 --- a/test/bitvec.test +++ b/test/bitvec.test @@ -11,7 +11,7 @@ # # Unit testing of the Bitvec object. # -# $Id: bitvec.test,v 1.2 2008/03/21 16:45:48 drh Exp $ +# $Id: bitvec.test,v 1.3 2008/11/19 18:30:35 shane Exp $ # set testdir [file dirname $argv0] @@ -185,7 +185,3 @@ for {set n 1} {$go} {incr n} { finish_test return - - - -finish_test