Skip to content

Commit a03d2b8

Browse files
yaowangmyjhjstz
authored andcommitted
FIXME enable 64bit bitmapset and update visimap (#14784)
It includes the portion about enabling 64bit bms and other necessary changes related to visimap, plus updates of cmockery unit tests.
1 parent 6584d1b commit a03d2b8

File tree

7 files changed

+381
-51
lines changed

7 files changed

+381
-51
lines changed

src/backend/access/appendonly/appendonly_visimap_entry.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ AppendOnlyVisimap_GetAttrNotNull(HeapTuple t, TupleDesc td, int attr)
129129
void
130130
AppendOnlyVisiMapEnty_ReadData(AppendOnlyVisimapEntry *visiMapEntry, size_t dataSize)
131131
{
132-
int newWordCount;
132+
/* the block count of (ondisk) bitstream */
133+
int onDiskBlockCount;
134+
/* the word count of in-memory bitmapset */
135+
int bmsWordCount;
133136

134137
Assert(visiMapEntry);
135138
Assert(CurrentMemoryContext == visiMapEntry->memoryContext);
@@ -156,21 +159,23 @@ AppendOnlyVisiMapEnty_ReadData(AppendOnlyVisimapEntry *visiMapEntry, size_t data
156159
* but I think it is reasonable to set it to NULLL to avoid similar issues.
157160
*/
158161
visiMapEntry->bitmap = NULL;
159-
newWordCount =
160-
BitmapDecompress_GetBlockCount(&decompressState);
161-
if (newWordCount > 0)
162+
BitmapDecompress_CalculateBlockCounts(&decompressState,
163+
&onDiskBlockCount,
164+
&bmsWordCount);
165+
166+
if (onDiskBlockCount > 0)
162167
{
163168
visiMapEntry->bitmap = palloc0(offsetof(Bitmapset, words) +
164-
(newWordCount * sizeof(bitmapword)));
165-
visiMapEntry->bitmap->nwords = newWordCount;
169+
(bmsWordCount * sizeof(bitmapword)));
170+
visiMapEntry->bitmap->nwords = bmsWordCount;
166171
BitmapDecompress_Decompress(&decompressState,
167-
visiMapEntry->bitmap->words,
168-
newWordCount);
172+
(uint32 *)visiMapEntry->bitmap->words,
173+
onDiskBlockCount);
169174
}
170-
else if (newWordCount != 0)
175+
else if (onDiskBlockCount != 0)
171176
{
172177
elog(ERROR,
173-
"illegal visimap block count: visimap block count %d", newWordCount);
178+
"illegal visimap block count: visimap block count %d", onDiskBlockCount);
174179
}
175180

176181
}
@@ -264,23 +269,32 @@ AppendOnlyVisimapEntry_GetHiddenTupleCount(
264269
void
265270
AppendOnlyVisimapEntry_WriteData(AppendOnlyVisimapEntry *visiMapEntry)
266271
{
267-
int bitmapSize,
268-
compressedBitmapSize;
272+
/* bitmap size, in bytes */
273+
int bitmapSize;
274+
int compressedBitmapSize;
275+
/* word count in 64bit or 32bit words for in-memory bms */
276+
int bmsWordCount;
277+
/* block count always in 32bit (after conversion if necessary) */
278+
int blockCount;
269279

270280
Assert(visiMapEntry);
271281
Assert(CurrentMemoryContext == visiMapEntry->memoryContext);
272282
Assert(AppendOnlyVisimapEntry_IsValid(visiMapEntry));
273283

274-
bitmapSize = (visiMapEntry->bitmap ? (visiMapEntry->bitmap->nwords * sizeof(bitmapword)) : 0);
284+
BitmapCompress_CalculateBlockCounts(visiMapEntry->bitmap,
285+
&blockCount,
286+
&bmsWordCount);
287+
bitmapSize = sizeof(uint32) * blockCount;
275288
bitmapSize += BITMAP_COMPRESSION_HEADER_SIZE;
289+
Assert(bmsWordCount <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT);
276290

277291
Assert(visiMapEntry->data);
278292
Assert(APPENDONLY_VISIMAP_DATA_BUFFER_SIZE >= bitmapSize);
279293
visiMapEntry->data->version = 1;
280294

281295
compressedBitmapSize = Bitmap_Compress(BITMAP_COMPRESSION_TYPE_DEFAULT,
282-
(visiMapEntry->bitmap ? visiMapEntry->bitmap->words : NULL),
283-
(visiMapEntry->bitmap ? visiMapEntry->bitmap->nwords : 0),
296+
(visiMapEntry->bitmap ? (uint32*)visiMapEntry->bitmap->words : NULL),
297+
blockCount,
284298
visiMapEntry->data->data,
285299
bitmapSize);
286300
Assert(compressedBitmapSize >= BITMAP_COMPRESSION_HEADER_SIZE);
@@ -499,6 +513,9 @@ AppendOnlyVisimapEntry_GetMinimalSizeToCover(int64 offset)
499513
minSize |= minSize >> 8;
500514
minSize |= minSize >> 16;
501515
minSize++;
516+
517+
Assert(minSize <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT);
518+
502519
return minSize;
503520
}
504521

src/backend/nodes/bitmapset.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929
#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
3030
#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)
3131

32-
#define BITMAPSET_SIZE(nwords) \
33-
(offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
34-
3532
/*----------
3633
* This is a well-known cute trick for isolating the rightmost one-bit
3734
* in a word. It assumes two's complement arithmetic. Consider any

src/backend/utils/misc/bitmap_compression.c

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "utils/bitmap_compression.h"
1616
#include "utils/bitstream.h"
1717
#include "utils/guc.h"
18+
#include "access/appendonly_visimap.h"
1819

1920
typedef enum BitmapCompressionFlag
2021
{
@@ -80,9 +81,15 @@ BitmapDecompress_HasError(
8081
}
8182

8283
/*
83-
* Performs the bitmap decompression.
84+
* Perform bitmap decompression into in-memory buffer
8485
*
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.
8693
*/
8794
void
8895
BitmapDecompress_Decompress(BitmapDecompressState *state,
@@ -105,7 +112,7 @@ BitmapDecompress_Decompress(BitmapDecompressState *state,
105112

106113
if (state->compressionType == BITMAP_COMPRESSION_TYPE_NO)
107114
{
108-
memcpy(bitmap,
115+
memcpy(bitmap,
109116
Bitstream_GetAlignedData(&state->bitstream, 16),
110117
state->blockCount * sizeof(uint32));
111118
}
@@ -357,3 +364,104 @@ Bitmap_Compress(
357364
return 0;
358365
}
359366
}
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

Comments
 (0)