blob: 23a002c64d43f98965d8e2882b6b584429c41296 [file] [log] [blame]
drhf5e7bb52008-02-18 14:47:33 +00001/*
2** 2008 February 16
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12** This file implements an object that represents a fixed-length
13** bitmap. Bits are numbered starting with 1.
14**
15** A bitmap is used to record what pages a database file have been
16** journalled during a transaction. Usually only a few pages are
17** journalled. So the bitmap is usually sparse and has low cardinality.
18** But sometimes (for example when during a DROP of a large table) most
19** or all of the pages get journalled. In those cases, the bitmap becomes
20** dense. The algorithm needs to handle both cases well.
21**
22** The size of the bitmap is fixed when the object is created.
23**
24** All bits are clear when the bitmap is created. Individual bits
25** may be set or cleared one at a time.
26**
27** Test operations are about 100 times more common that set operations.
28** Clear operations are exceedingly rare. There are usually between
29** 5 and 500 set operations per Bitvec object, though the number of sets can
30** sometimes grow into tens of thousands or larger. The size of the
31** Bitvec object is the number of pages in the database file at the
32** start of a transaction, and is thus usually less than a few thousand,
33** but can be as large as 2 billion for a really big database.
34**
35** @(#) $Id: bitvec.c,v 1.1 2008/02/18 14:47:34 drh Exp $
36*/
37#include "sqliteInt.h"
38
39#define BITVEC_SZ 512
40#define BITVEC_NCHAR (BITVEC_SZ-12)
41#define BITVEC_NBIT (BITVEC_NCHAR*8)
42#define BITVEC_NINT ((BITVEC_SZ-12)/4)
43#define BITVEC_MXHASH (BITVEC_NINT/2)
44#define BITVEC_NPTR ((BITVEC_SZ-12)/8)
45
46#define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT)
47
48/*
49** A bitmap is an instance of the following structure.
50**
51** This bitmap records the existance of zero or more bits
52** with values between 1 and iSize, inclusive.
53**
54** There are three possible representations of the bitmap.
55** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
56** bitmap. The least significant bit is bit 1.
57**
58** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
59** a hash table that will hold up to BITVEC_MXHASH distinct values.
60**
61** Otherwise, the value i is redirected into one of BITVEC_NPTR
62** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
63** handles up to iDivisor separate values of i. apSub[0] holds
64** values between 1 and iDivisor. apSub[1] holds values between
65** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
66** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
67** to hold deal with values between 1 and iDivisor.
68*/
69struct Bitvec {
70 u32 iSize; /* Maximum bit index */
71 u32 nSet; /* Number of bits that are set */
72 u32 iDivisor; /* Number of bits handled by each apSub[] entry */
73 union {
74 u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */
75 u32 aHash[BITVEC_NINT]; /* Hash table representation */
76 Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
77 } u;
78};
79
80/*
81** Create a new bitmap object able to handle bits between 0 and iSize,
82** inclusive. Return a pointer to the new object. Return NULL if
83** malloc fails.
84*/
85Bitvec *sqlite3BitvecCreate(u32 iSize){
86 Bitvec *p;
87 assert( sizeof(*p)==BITVEC_SZ );
88 p = sqlite3MallocZero( sizeof(*p) );
89 if( p ){
90 p->iSize = iSize;
91 }
92 return p;
93}
94
95/*
96** Check to see if the i-th bit is set. Return true or false.
97** If p is NULL (if the bitmap has not been created) or if
98** i is out of range, then return false.
99*/
100int sqlite3BitvecTest(Bitvec *p, u32 i){
101 assert( i>0 );
102 if( p==0 ) return 0;
103 if( i>p->iSize ) return 0;
104 if( p->iSize<=BITVEC_NBIT ){
105 i--;
106 return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0;
107 }
108 if( p->iDivisor>0 ){
109 u32 bin = (i-1)/p->iDivisor;
110 i = (i-1)%p->iDivisor + 1;
111 return sqlite3BitvecTest(p->u.apSub[bin], i);
112 }else{
113 u32 h = BITVEC_HASH(i);
114 while( p->u.aHash[h] ){
115 if( p->u.aHash[h]==i ) return 1;
116 h++;
117 if( h>=BITVEC_NINT ) h = 0;
118 }
119 return 0;
120 }
121}
122
123/*
124** Set the i-th bit. Return 0 on success and an error code if
125** anything goes wrong.
126*/
127int sqlite3BitvecSet(Bitvec *p, u32 i){
128 u32 h;
129 assert( p!=0 );
130 if( p->iSize<=BITVEC_NBIT ){
131 i--;
132 p->u.aBitmap[i/8] |= 1 << (i&7);
133 return SQLITE_OK;
134 }
135 if( p->iDivisor ){
136 u32 bin = (i-1)/p->iDivisor;
137 i = (i-1)%p->iDivisor + 1;
138 if( p->u.apSub[bin]==0 ){
139 sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
140 p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
141 sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
142 if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
143 }
144 return sqlite3BitvecSet(p->u.apSub[bin], i);
145 }
146 h = BITVEC_HASH(i);
147 while( p->u.aHash[h] ){
148 if( p->u.aHash[h]==i ) return SQLITE_OK;
149 h++;
150 if( h==BITVEC_NINT ) h = 0;
151 }
152 p->nSet++;
153 if( p->nSet>=BITVEC_MXHASH ){
154 int j, rc;
155 u32 aiValues[BITVEC_NINT];
156 memcpy(aiValues, p->u.aHash, sizeof(aiValues));
157 memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR);
158 p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
159 sqlite3BitvecSet(p, i);
160 for(rc=j=0; j<BITVEC_NINT; j++){
161 if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
162 }
163 return rc;
164 }
165 p->u.aHash[h] = i;
166 return SQLITE_OK;
167}
168
169/*
170** Clear the i-th bit. Return 0 on success and an error code if
171** anything goes wrong.
172*/
173void sqlite3BitvecClear(Bitvec *p, u32 i){
174 assert( p!=0 );
175 if( p->iSize<=BITVEC_NBIT ){
176 i--;
177 p->u.aBitmap[i/8] &= ~(1 << (i&7));
178 }else if( p->iDivisor ){
179 u32 bin = (i-1)/p->iDivisor;
180 i = (i-1)%p->iDivisor + 1;
181 if( p->u.apSub[bin] ){
182 sqlite3BitvecClear(p->u.apSub[bin], i);
183 }
184 }else{
185 int j;
186 u32 aiValues[BITVEC_NINT];
187 memcpy(aiValues, p->u.aHash, sizeof(aiValues));
188 memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT);
189 p->nSet = 0;
190 for(j=0; j<BITVEC_NINT; j++){
191 if( aiValues[j] && aiValues[j]!=i ) sqlite3BitvecSet(p, aiValues[j]);
192 }
193 }
194}
195
196/*
197** Destroy a bitmap object. Reclaim all memory used.
198*/
199void sqlite3BitvecDestroy(Bitvec *p){
200 if( p==0 ) return;
201 if( p->iDivisor ){
202 int i;
203 for(i=0; i<BITVEC_NPTR; i++){
204 sqlite3BitvecDestroy(p->u.apSub[i]);
205 }
206 }
207 sqlite3_free(p);
208}