bitvec.c.svn-base
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:10k
源码类别:

数据库系统

开发平台:

C/C++

  1. /*
  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.4 2008/04/14 01:00:58 drh Exp $
  36. */
  37. #include "sqliteInt.h"
  38. #define BITVEC_SZ        512
  39. /* Round the union size down to the nearest pointer boundary, since that's how 
  40. ** it will be aligned within the Bitvec struct. */
  41. #define BITVEC_USIZE     (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*))
  42. #define BITVEC_NCHAR     BITVEC_USIZE
  43. #define BITVEC_NBIT      (BITVEC_NCHAR*8)
  44. #define BITVEC_NINT      (BITVEC_USIZE/4)
  45. #define BITVEC_MXHASH    (BITVEC_NINT/2)
  46. #define BITVEC_NPTR      (BITVEC_USIZE/sizeof(Bitvec *))
  47. #define BITVEC_HASH(X)   (((X)*37)%BITVEC_NINT)
  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. */
  69. struct 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. ** Create a new bitmap object able to handle bits between 0 and iSize,
  81. ** inclusive.  Return a pointer to the new object.  Return NULL if 
  82. ** malloc fails.
  83. */
  84. Bitvec *sqlite3BitvecCreate(u32 iSize){
  85.   Bitvec *p;
  86.   assert( sizeof(*p)==BITVEC_SZ );
  87.   p = sqlite3MallocZero( sizeof(*p) );
  88.   if( p ){
  89.     p->iSize = iSize;
  90.   }
  91.   return p;
  92. }
  93. /*
  94. ** Check to see if the i-th bit is set.  Return true or false.
  95. ** If p is NULL (if the bitmap has not been created) or if
  96. ** i is out of range, then return false.
  97. */
  98. int sqlite3BitvecTest(Bitvec *p, u32 i){
  99.   if( p==0 ) return 0;
  100.   if( i>p->iSize || i==0 ) return 0;
  101.   if( p->iSize<=BITVEC_NBIT ){
  102.     i--;
  103.     return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0;
  104.   }
  105.   if( p->iDivisor>0 ){
  106.     u32 bin = (i-1)/p->iDivisor;
  107.     i = (i-1)%p->iDivisor + 1;
  108.     return sqlite3BitvecTest(p->u.apSub[bin], i);
  109.   }else{
  110.     u32 h = BITVEC_HASH(i);
  111.     while( p->u.aHash[h] ){
  112.       if( p->u.aHash[h]==i ) return 1;
  113.       h++;
  114.       if( h>=BITVEC_NINT ) h = 0;
  115.     }
  116.     return 0;
  117.   }
  118. }
  119. /*
  120. ** Set the i-th bit.  Return 0 on success and an error code if
  121. ** anything goes wrong.
  122. */
  123. int sqlite3BitvecSet(Bitvec *p, u32 i){
  124.   u32 h;
  125.   assert( p!=0 );
  126.   assert( i>0 );
  127.   assert( i<=p->iSize );
  128.   if( p->iSize<=BITVEC_NBIT ){
  129.     i--;
  130.     p->u.aBitmap[i/8] |= 1 << (i&7);
  131.     return SQLITE_OK;
  132.   }
  133.   if( p->iDivisor ){
  134.     u32 bin = (i-1)/p->iDivisor;
  135.     i = (i-1)%p->iDivisor + 1;
  136.     if( p->u.apSub[bin]==0 ){
  137.       sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
  138.       p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
  139.       sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
  140.       if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
  141.     }
  142.     return sqlite3BitvecSet(p->u.apSub[bin], i);
  143.   }
  144.   h = BITVEC_HASH(i);
  145.   while( p->u.aHash[h] ){
  146.     if( p->u.aHash[h]==i ) return SQLITE_OK;
  147.     h++;
  148.     if( h==BITVEC_NINT ) h = 0;
  149.   }
  150.   p->nSet++;
  151.   if( p->nSet>=BITVEC_MXHASH ){
  152.     int j, rc;
  153.     u32 aiValues[BITVEC_NINT];
  154.     memcpy(aiValues, p->u.aHash, sizeof(aiValues));
  155.     memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR);
  156.     p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
  157.     rc = sqlite3BitvecSet(p, i);
  158.     for(j=0; j<BITVEC_NINT; j++){
  159.       if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
  160.     }
  161.     return rc;
  162.   }
  163.   p->u.aHash[h] = i;
  164.   return SQLITE_OK;
  165. }
  166. /*
  167. ** Clear the i-th bit.  Return 0 on success and an error code if
  168. ** anything goes wrong.
  169. */
  170. void sqlite3BitvecClear(Bitvec *p, u32 i){
  171.   assert( p!=0 );
  172.   assert( i>0 );
  173.   if( p->iSize<=BITVEC_NBIT ){
  174.     i--;
  175.     p->u.aBitmap[i/8] &= ~(1 << (i&7));
  176.   }else if( p->iDivisor ){
  177.     u32 bin = (i-1)/p->iDivisor;
  178.     i = (i-1)%p->iDivisor + 1;
  179.     if( p->u.apSub[bin] ){
  180.       sqlite3BitvecClear(p->u.apSub[bin], i);
  181.     }
  182.   }else{
  183.     int j;
  184.     u32 aiValues[BITVEC_NINT];
  185.     memcpy(aiValues, p->u.aHash, sizeof(aiValues));
  186.     memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT);
  187.     p->nSet = 0;
  188.     for(j=0; j<BITVEC_NINT; j++){
  189.       if( aiValues[j] && aiValues[j]!=i ){
  190.         sqlite3BitvecSet(p, aiValues[j]);
  191.       }
  192.     }
  193.   }
  194. }
  195. /*
  196. ** Destroy a bitmap object.  Reclaim all memory used.
  197. */
  198. void sqlite3BitvecDestroy(Bitvec *p){
  199.   if( p==0 ) return;
  200.   if( p->iDivisor ){
  201.     int i;
  202.     for(i=0; i<BITVEC_NPTR; i++){
  203.       sqlite3BitvecDestroy(p->u.apSub[i]);
  204.     }
  205.   }
  206.   sqlite3_free(p);
  207. }
  208. #ifndef SQLITE_OMIT_BUILTIN_TEST
  209. /*
  210. ** Let V[] be an array of unsigned characters sufficient to hold
  211. ** up to N bits.  Let I be an integer between 0 and N.  0<=I<N.
  212. ** Then the following macros can be used to set, clear, or test
  213. ** individual bits within V.
  214. */
  215. #define SETBIT(V,I)      V[I>>3] |= (1<<(I&7))
  216. #define CLEARBIT(V,I)    V[I>>3] &= ~(1<<(I&7))
  217. #define TESTBIT(V,I)     (V[I>>3]&(1<<(I&7)))!=0
  218. /*
  219. ** This routine runs an extensive test of the Bitvec code.
  220. **
  221. ** The input is an array of integers that acts as a program
  222. ** to test the Bitvec.  The integers are opcodes followed
  223. ** by 0, 1, or 3 operands, depending on the opcode.  Another
  224. ** opcode follows immediately after the last operand.
  225. **
  226. ** There are 6 opcodes numbered from 0 through 5.  0 is the
  227. ** "halt" opcode and causes the test to end.
  228. **
  229. **    0          Halt and return the number of errors
  230. **    1 N S X    Set N bits beginning with S and incrementing by X
  231. **    2 N S X    Clear N bits beginning with S and incrementing by X
  232. **    3 N        Set N randomly chosen bits
  233. **    4 N        Clear N randomly chosen bits
  234. **    5 N S X    Set N bits from S increment X in array only, not in bitvec
  235. **
  236. ** The opcodes 1 through 4 perform set and clear operations are performed
  237. ** on both a Bitvec object and on a linear array of bits obtained from malloc.
  238. ** Opcode 5 works on the linear array only, not on the Bitvec.
  239. ** Opcode 5 is used to deliberately induce a fault in order to
  240. ** confirm that error detection works.
  241. **
  242. ** At the conclusion of the test the linear array is compared
  243. ** against the Bitvec object.  If there are any differences,
  244. ** an error is returned.  If they are the same, zero is returned.
  245. **
  246. ** If a memory allocation error occurs, return -1.
  247. */
  248. int sqlite3BitvecBuiltinTest(int sz, int *aOp){
  249.   Bitvec *pBitvec = 0;
  250.   unsigned char *pV = 0;
  251.   int rc = -1;
  252.   int i, nx, pc, op;
  253.   /* Allocate the Bitvec to be tested and a linear array of
  254.   ** bits to act as the reference */
  255.   pBitvec = sqlite3BitvecCreate( sz );
  256.   pV = sqlite3_malloc( (sz+7)/8 + 1 );
  257.   if( pBitvec==0 || pV==0 ) goto bitvec_end;
  258.   memset(pV, 0, (sz+7)/8 + 1);
  259.   /* Run the program */
  260.   pc = 0;
  261.   while( (op = aOp[pc])!=0 ){
  262.     switch( op ){
  263.       case 1:
  264.       case 2:
  265.       case 5: {
  266.         nx = 4;
  267.         i = aOp[pc+2] - 1;
  268.         aOp[pc+2] += aOp[pc+3];
  269.         break;
  270.       }
  271.       case 3:
  272.       case 4: 
  273.       default: {
  274.         nx = 2;
  275.         sqlite3_randomness(sizeof(i), &i);
  276.         break;
  277.       }
  278.     }
  279.     if( (--aOp[pc+1]) > 0 ) nx = 0;
  280.     pc += nx;
  281.     i = (i & 0x7fffffff)%sz;
  282.     if( (op & 1)!=0 ){
  283.       SETBIT(pV, (i+1));
  284.       if( op!=5 ){
  285.         if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
  286.       }
  287.     }else{
  288.       CLEARBIT(pV, (i+1));
  289.       sqlite3BitvecClear(pBitvec, i+1);
  290.     }
  291.   }
  292.   /* Test to make sure the linear array exactly matches the
  293.   ** Bitvec object.  Start with the assumption that they do
  294.   ** match (rc==0).  Change rc to non-zero if a discrepancy
  295.   ** is found.
  296.   */
  297.   rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
  298.           + sqlite3BitvecTest(pBitvec, 0);
  299.   for(i=1; i<=sz; i++){
  300.     if(  (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
  301.       rc = i;
  302.       break;
  303.     }
  304.   }
  305.   /* Free allocated structure */
  306. bitvec_end:
  307.   sqlite3_free(pV);
  308.   sqlite3BitvecDestroy(pBitvec);
  309.   return rc;
  310. }
  311. #endif /* SQLITE_OMIT_BUILTIN_TEST */