blob: 7fa8a8aec7891e7a8f43630aeee0496f7f8320d5 [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**
mlcreechdda5b682008-03-14 13:02:08 +000035** @(#) $Id: bitvec.c,v 1.2 2008/03/14 13:02:08 mlcreech Exp $
drhf5e7bb52008-02-18 14:47:33 +000036*/
37#include "sqliteInt.h"
38
39#define BITVEC_SZ 512
mlcreechdda5b682008-03-14 13:02:08 +000040/* Round the union size down to the nearest pointer boundary, since that's how
41** it will be aligned within the Bitvec struct. */
42#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec *))*sizeof(Bitvec *))
43#define BITVEC_NCHAR BITVEC_USIZE
drhf5e7bb52008-02-18 14:47:33 +000044#define BITVEC_NBIT (BITVEC_NCHAR*8)
mlcreechdda5b682008-03-14 13:02:08 +000045#define BITVEC_NINT (BITVEC_USIZE/4)
drhf5e7bb52008-02-18 14:47:33 +000046#define BITVEC_MXHASH (BITVEC_NINT/2)
mlcreechdda5b682008-03-14 13:02:08 +000047#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
drhf5e7bb52008-02-18 14:47:33 +000048
49#define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT)
50
51/*
52** A bitmap is an instance of the following structure.
53**
54** This bitmap records the existance of zero or more bits
55** with values between 1 and iSize, inclusive.
56**
57** There are three possible representations of the bitmap.
58** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
59** bitmap. The least significant bit is bit 1.
60**
61** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
62** a hash table that will hold up to BITVEC_MXHASH distinct values.
63**
64** Otherwise, the value i is redirected into one of BITVEC_NPTR
65** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
66** handles up to iDivisor separate values of i. apSub[0] holds
67** values between 1 and iDivisor. apSub[1] holds values between
68** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
69** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
70** to hold deal with values between 1 and iDivisor.
71*/
72struct Bitvec {
73 u32 iSize; /* Maximum bit index */
74 u32 nSet; /* Number of bits that are set */
75 u32 iDivisor; /* Number of bits handled by each apSub[] entry */
76 union {
77 u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */
78 u32 aHash[BITVEC_NINT]; /* Hash table representation */
79 Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
80 } u;
81};
82
83/*
84** Create a new bitmap object able to handle bits between 0 and iSize,
85** inclusive. Return a pointer to the new object. Return NULL if
86** malloc fails.
87*/
88Bitvec *sqlite3BitvecCreate(u32 iSize){
89 Bitvec *p;
90 assert( sizeof(*p)==BITVEC_SZ );
91 p = sqlite3MallocZero( sizeof(*p) );
92 if( p ){
93 p->iSize = iSize;
94 }
95 return p;
96}
97
98/*
99** Check to see if the i-th bit is set. Return true or false.
100** If p is NULL (if the bitmap has not been created) or if
101** i is out of range, then return false.
102*/
103int sqlite3BitvecTest(Bitvec *p, u32 i){
104 assert( i>0 );
105 if( p==0 ) return 0;
106 if( i>p->iSize ) return 0;
107 if( p->iSize<=BITVEC_NBIT ){
108 i--;
109 return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0;
110 }
111 if( p->iDivisor>0 ){
112 u32 bin = (i-1)/p->iDivisor;
113 i = (i-1)%p->iDivisor + 1;
114 return sqlite3BitvecTest(p->u.apSub[bin], i);
115 }else{
116 u32 h = BITVEC_HASH(i);
117 while( p->u.aHash[h] ){
118 if( p->u.aHash[h]==i ) return 1;
119 h++;
120 if( h>=BITVEC_NINT ) h = 0;
121 }
122 return 0;
123 }
124}
125
126/*
127** Set the i-th bit. Return 0 on success and an error code if
128** anything goes wrong.
129*/
130int sqlite3BitvecSet(Bitvec *p, u32 i){
131 u32 h;
132 assert( p!=0 );
133 if( p->iSize<=BITVEC_NBIT ){
134 i--;
135 p->u.aBitmap[i/8] |= 1 << (i&7);
136 return SQLITE_OK;
137 }
138 if( p->iDivisor ){
139 u32 bin = (i-1)/p->iDivisor;
140 i = (i-1)%p->iDivisor + 1;
141 if( p->u.apSub[bin]==0 ){
142 sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
143 p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
144 sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
145 if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
146 }
147 return sqlite3BitvecSet(p->u.apSub[bin], i);
148 }
149 h = BITVEC_HASH(i);
150 while( p->u.aHash[h] ){
151 if( p->u.aHash[h]==i ) return SQLITE_OK;
152 h++;
153 if( h==BITVEC_NINT ) h = 0;
154 }
155 p->nSet++;
156 if( p->nSet>=BITVEC_MXHASH ){
157 int j, rc;
158 u32 aiValues[BITVEC_NINT];
159 memcpy(aiValues, p->u.aHash, sizeof(aiValues));
160 memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR);
161 p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
162 sqlite3BitvecSet(p, i);
163 for(rc=j=0; j<BITVEC_NINT; j++){
164 if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
165 }
166 return rc;
167 }
168 p->u.aHash[h] = i;
169 return SQLITE_OK;
170}
171
172/*
173** Clear the i-th bit. Return 0 on success and an error code if
174** anything goes wrong.
175*/
176void sqlite3BitvecClear(Bitvec *p, u32 i){
177 assert( p!=0 );
178 if( p->iSize<=BITVEC_NBIT ){
179 i--;
180 p->u.aBitmap[i/8] &= ~(1 << (i&7));
181 }else if( p->iDivisor ){
182 u32 bin = (i-1)/p->iDivisor;
183 i = (i-1)%p->iDivisor + 1;
184 if( p->u.apSub[bin] ){
185 sqlite3BitvecClear(p->u.apSub[bin], i);
186 }
187 }else{
188 int j;
189 u32 aiValues[BITVEC_NINT];
190 memcpy(aiValues, p->u.aHash, sizeof(aiValues));
191 memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT);
192 p->nSet = 0;
193 for(j=0; j<BITVEC_NINT; j++){
194 if( aiValues[j] && aiValues[j]!=i ) sqlite3BitvecSet(p, aiValues[j]);
195 }
196 }
197}
198
199/*
200** Destroy a bitmap object. Reclaim all memory used.
201*/
202void sqlite3BitvecDestroy(Bitvec *p){
203 if( p==0 ) return;
204 if( p->iDivisor ){
205 int i;
206 for(i=0; i<BITVEC_NPTR; i++){
207 sqlite3BitvecDestroy(p->u.apSub[i]);
208 }
209 }
210 sqlite3_free(p);
211}