15
15
#include "utils/bitmap_compression.h"
16
16
#include "utils/bitstream.h"
17
17
#include "utils/guc.h"
18
+ #include "access/appendonly_visimap.h"
18
19
19
20
typedef enum BitmapCompressionFlag
20
21
{
@@ -80,9 +81,15 @@ BitmapDecompress_HasError(
80
81
}
81
82
82
83
/*
83
- * Performs the bitmap decompression.
84
+ * Perform bitmap decompression into in-memory buffer
84
85
*
85
- * bitmapDataSize in uint32-words.
86
+ * bitmap: caller-allocated buffer that can hold state->blockCount
87
+ * number of 32-bit on-disk bitmap words.
88
+ *
89
+ * For both 32-bit and 64-bit in-memory bitmap word sizes, we write
90
+ * 32-bit words into the in-memory buffer contiguously. This is safe
91
+ * to do as we interpret two contiguous 32-bit words as one 64-bit
92
+ * word.
86
93
*/
87
94
void
88
95
BitmapDecompress_Decompress (BitmapDecompressState * state ,
@@ -105,7 +112,7 @@ BitmapDecompress_Decompress(BitmapDecompressState *state,
105
112
106
113
if (state -> compressionType == BITMAP_COMPRESSION_TYPE_NO )
107
114
{
108
- memcpy (bitmap ,
115
+ memcpy (bitmap ,
109
116
Bitstream_GetAlignedData (& state -> bitstream , 16 ),
110
117
state -> blockCount * sizeof (uint32 ));
111
118
}
@@ -357,3 +364,104 @@ Bitmap_Compress(
357
364
return 0 ;
358
365
}
359
366
}
367
+
368
+ /*
369
+ * Calculate two counts for decompress:
370
+ * 1. 'onDiskBlockCount': the block count of (ondisk) bitstream
371
+ * 2. 'bmsWordCount': the word count of in-memory bitmapset
372
+ */
373
+ void BitmapDecompress_CalculateBlockCounts (BitmapDecompressState * decompressState ,
374
+ int * onDiskBlockCount ,
375
+ int * bmsWordCount )
376
+ {
377
+ * onDiskBlockCount =
378
+ BitmapDecompress_GetBlockCount (decompressState );
379
+
380
+ /* The on-disk bitmap representation always uses 32-bit block size
381
+ * (for backward compatibility). Depending on the environment, we
382
+ * may be using either 64-bit words or 32-bit words for the
383
+ * in-memory representation.
384
+ * So, if (in-memory) bitmapset uses 64 bit words, we can use half
385
+ * of the on-disk bitmap block count.
386
+ */
387
+ if (BITS_PER_BITMAPWORD == 64 )
388
+ {
389
+ /*
390
+ * Number of on-disk blocks is always 0, 1 or even.
391
+ * See resizing logic in AppendOnlyVisimapEntry_HideTuple()
392
+ */
393
+ if (* onDiskBlockCount == 1 )
394
+ * bmsWordCount = 1 ;
395
+ else
396
+ {
397
+ Assert (* onDiskBlockCount % 2 == 0 );
398
+ * bmsWordCount = * onDiskBlockCount / 2 ;
399
+ }
400
+ }
401
+ else
402
+ {
403
+ Assert (BITS_PER_BITMAPWORD == 32 );
404
+ * bmsWordCount = * onDiskBlockCount ;
405
+ }
406
+ Assert (* bmsWordCount <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT );
407
+ Assert (* bmsWordCount >= 0 );
408
+ }
409
+
410
+ /*
411
+ * Calculate two counts for compress:
412
+ * 1. 'onDiskBlockCount': the block count of (ondisk) bitstream
413
+ * 2. 'bmsWordCount': the word count of in-memory bitmapset
414
+ */
415
+ void BitmapCompress_CalculateBlockCounts (Bitmapset * bitmap ,
416
+ int * onDiskBlockCount ,
417
+ int * bmsWordCount )
418
+ {
419
+ * onDiskBlockCount = 0 ;
420
+ * bmsWordCount = 0 ;
421
+
422
+ if (bitmap )
423
+ {
424
+ * bmsWordCount = bitmap -> nwords ;
425
+
426
+ /*
427
+ * On 64bit env, there is a conflict: in-memory bms is in 64bit word,
428
+ * but on-disk block is in 32bit word to keep consistency. We need to
429
+ * provide 32bit block count to Bitmap_Compress() after kind of
430
+ * conversion.
431
+ */
432
+ if (BITS_PER_BITMAPWORD == 64 )
433
+ {
434
+ /*
435
+ * On 64bit env, if there is only one 64 bit word in memory, and the
436
+ * 32 higher order bits of that word are all zero, it implies that
437
+ * there is only one 32 bit word. We can always assume that the 32
438
+ * higher order bits for a 64 bit bitmap word is zeroed out - this
439
+ * is ensured by routines such as bms_add_member() and
440
+ * AppendOnlyVisiMapEnty_ReadData().
441
+ */
442
+ if (* bmsWordCount == 1
443
+ && (bitmap -> words [0 ] >> 32 ) == 0 )
444
+ {
445
+ * onDiskBlockCount = 1 ;
446
+ }
447
+ else
448
+ {
449
+ /*
450
+ * onDiskBlockCount required by Bitmap_Compress() is always in
451
+ * uint32-words. So, if bitmapset uses 64 bit words, double
452
+ * the value of bmsWordCount.
453
+ */
454
+ * onDiskBlockCount = bitmap -> nwords * 2 ;
455
+ }
456
+ }
457
+ else
458
+ {
459
+ Assert (BITS_PER_BITMAPWORD == 32 );
460
+
461
+ /*
462
+ * On 32bit env, onDiskBlockCount is always equal to bmsWordCount.
463
+ */
464
+ * onDiskBlockCount = bitmap -> nwords ;
465
+ }
466
+ }
467
+ }
0 commit comments