|
16 | 16 | * visibilitymap_pin_ok - check whether correct map page is already pinned
|
17 | 17 | * visibilitymap_set - set a bit in a previously pinned page
|
18 | 18 | * visibilitymap_test - test if a bit is set
|
| 19 | + * visibilitymap_count - count number of bits set in visibility map |
| 20 | + * visibilitymap_truncate - truncate the visibility map |
19 | 21 | *
|
20 | 22 | * NOTES
|
21 | 23 | *
|
|
110 | 112 | #define HEAPBLK_TO_MAPBYTE(x) (((x) % HEAPBLOCKS_PER_PAGE) / HEAPBLOCKS_PER_BYTE)
|
111 | 113 | #define HEAPBLK_TO_MAPBIT(x) ((x) % HEAPBLOCKS_PER_BYTE)
|
112 | 114 |
|
| 115 | +/* table for fast counting of set bits */ |
| 116 | +static const uint8 number_of_ones[256] = { |
| 117 | + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, |
| 118 | + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 119 | + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 120 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 121 | + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 122 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 123 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 124 | + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 125 | + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 126 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 127 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 128 | + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 129 | + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 130 | + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 131 | + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 132 | + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 |
| 133 | +}; |
| 134 | + |
113 | 135 | /* prototypes for internal routines */
|
114 | 136 | static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend);
|
115 | 137 | static void vm_extend(Relation rel, BlockNumber nvmblocks);
|
@@ -307,6 +329,52 @@ visibilitymap_test(Relation rel, BlockNumber heapBlk, Buffer *buf)
|
307 | 329 | return result;
|
308 | 330 | }
|
309 | 331 |
|
| 332 | +/* |
| 333 | + * visibilitymap_count - count number of bits set in visibility map |
| 334 | + * |
| 335 | + * Note: we ignore the possibility of race conditions when the table is being |
| 336 | + * extended concurrently with the call. New pages added to the table aren't |
| 337 | + * going to be marked all-visible, so they won't affect the result. |
| 338 | + */ |
| 339 | +BlockNumber |
| 340 | +visibilitymap_count(Relation rel) |
| 341 | +{ |
| 342 | + BlockNumber result = 0; |
| 343 | + BlockNumber mapBlock; |
| 344 | + |
| 345 | + for (mapBlock = 0; ; mapBlock++) |
| 346 | + { |
| 347 | + Buffer mapBuffer; |
| 348 | + unsigned char *map; |
| 349 | + int i; |
| 350 | + |
| 351 | + /* |
| 352 | + * Read till we fall off the end of the map. We assume that any |
| 353 | + * extra bytes in the last page are zeroed, so we don't bother |
| 354 | + * excluding them from the count. |
| 355 | + */ |
| 356 | + mapBuffer = vm_readbuf(rel, mapBlock, false); |
| 357 | + if (!BufferIsValid(mapBuffer)) |
| 358 | + break; |
| 359 | + |
| 360 | + /* |
| 361 | + * We choose not to lock the page, since the result is going to be |
| 362 | + * immediately stale anyway if anyone is concurrently setting or |
| 363 | + * clearing bits, and we only really need an approximate value. |
| 364 | + */ |
| 365 | + map = (unsigned char *) PageGetContents(BufferGetPage(mapBuffer)); |
| 366 | + |
| 367 | + for (i = 0; i < MAPSIZE; i++) |
| 368 | + { |
| 369 | + result += number_of_ones[map[i]]; |
| 370 | + } |
| 371 | + |
| 372 | + ReleaseBuffer(mapBuffer); |
| 373 | + } |
| 374 | + |
| 375 | + return result; |
| 376 | +} |
| 377 | + |
310 | 378 | /*
|
311 | 379 | * visibilitymap_truncate - truncate the visibility map
|
312 | 380 | *
|
|
0 commit comments