40
40
41
41
#include <limits.h>
42
42
43
- #include "access/htup_details.h"
44
43
#include "common/hashfn.h"
45
44
#include "common/int.h"
46
45
#include "nodes/bitmapset.h"
47
46
#include "nodes/tidbitmap.h"
48
47
#include "storage/lwlock.h"
49
48
#include "utils/dsa.h"
50
49
51
- /*
52
- * The maximum number of tuples per page is not large (typically 256 with
53
- * 8K pages, or 1024 with 32K pages). So there's not much point in making
54
- * the per-page bitmaps variable size. We just legislate that the size
55
- * is this:
56
- */
57
- #define MAX_TUPLES_PER_PAGE MaxHeapTuplesPerPage
58
-
59
50
/*
60
51
* When we have to switch over to lossy storage, we use a data structure
61
52
* with one bit per page, where all pages having the same number DIV
67
58
* table, using identical data structures. (This is because the memory
68
59
* management for hashtables doesn't easily/efficiently allow space to be
69
60
* transferred easily from one hashtable to another.) Therefore it's best
70
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE , or at least not
61
+ * if PAGES_PER_CHUNK is the same as TBM_MAX_TUPLES_PER_PAGE , or at least not
71
62
* too different. But we also want PAGES_PER_CHUNK to be a power of 2 to
72
63
* avoid expensive integer remainder operations. So, define it like this:
73
64
*/
79
70
#define BITNUM (x ) ((x) % BITS_PER_BITMAPWORD)
80
71
81
72
/* number of active words for an exact page: */
82
- #define WORDS_PER_PAGE ((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
73
+ #define WORDS_PER_PAGE ((TBM_MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
83
74
/* number of active words for a lossy chunk: */
84
75
#define WORDS_PER_CHUNK ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
85
76
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
181
172
int spageptr ; /* next spages index */
182
173
int schunkptr ; /* next schunks index */
183
174
int schunkbit ; /* next bit to check in current schunk */
184
- TBMIterateResult output ; /* MUST BE LAST (because variable-size) */
175
+ TBMIterateResult output ;
185
176
};
186
177
187
178
/*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
222
213
PTEntryArray * ptbase ; /* pagetable element array */
223
214
PTIterationArray * ptpages ; /* sorted exact page index list */
224
215
PTIterationArray * ptchunks ; /* sorted lossy page index list */
225
- TBMIterateResult output ; /* MUST BE LAST (because variable-size) */
216
+ TBMIterateResult output ;
226
217
};
227
218
228
219
/* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
390
381
bitnum ;
391
382
392
383
/* safety check to ensure we don't overrun bit array bounds */
393
- if (off < 1 || off > MAX_TUPLES_PER_PAGE )
384
+ if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE )
394
385
elog (ERROR , "tuple offset out of range: %u" , off );
395
386
396
387
/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
696
687
* Create the TBMPrivateIterator struct, with enough trailing space to
697
688
* serve the needs of the TBMIterateResult sub-struct.
698
689
*/
699
- iterator = (TBMPrivateIterator * ) palloc (sizeof (TBMPrivateIterator ) +
700
- MAX_TUPLES_PER_PAGE *
701
- sizeof (OffsetNumber ));
690
+ iterator = (TBMPrivateIterator * ) palloc (sizeof (TBMPrivateIterator ));
702
691
iterator -> tbm = tbm ;
703
692
704
693
/*
@@ -906,11 +895,16 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
906
895
/*
907
896
* tbm_extract_page_tuple - extract the tuple offsets from a page
908
897
*
909
- * The extracted offsets are stored into TBMIterateResult.
898
+ * Returns the number of offsets it filled in if <= max_offsets. Otherwise,
899
+ * fills in as many offsets as fit and returns the total number of offsets in
900
+ * the page.
910
901
*/
911
- static inline int
912
- tbm_extract_page_tuple (PagetableEntry * page , TBMIterateResult * output )
902
+ int
903
+ tbm_extract_page_tuple (TBMIterateResult * iteritem ,
904
+ OffsetNumber * offsets ,
905
+ uint32 max_offsets )
913
906
{
907
+ PagetableEntry * page = iteritem -> internal_page ;
914
908
int wordnum ;
915
909
int ntuples = 0 ;
916
910
@@ -925,7 +919,11 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
925
919
while (w != 0 )
926
920
{
927
921
if (w & 1 )
928
- output -> offsets [ntuples ++ ] = (OffsetNumber ) off ;
922
+ {
923
+ if (ntuples < max_offsets )
924
+ offsets [ntuples ] = (OffsetNumber ) off ;
925
+ ntuples ++ ;
926
+ }
929
927
off ++ ;
930
928
w >>= 1 ;
931
929
}
@@ -1012,9 +1010,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
1012
1010
{
1013
1011
/* Return a lossy page indicator from the chunk */
1014
1012
output -> blockno = chunk_blockno ;
1015
- output -> ntuples = -1 ;
1016
1013
output -> lossy = true;
1017
1014
output -> recheck = true;
1015
+ output -> internal_page = NULL ;
1018
1016
iterator -> schunkbit ++ ;
1019
1017
return output ;
1020
1018
}
@@ -1023,18 +1021,15 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
1023
1021
if (iterator -> spageptr < tbm -> npages )
1024
1022
{
1025
1023
PagetableEntry * page ;
1026
- int ntuples ;
1027
1024
1028
1025
/* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
1029
1026
if (tbm -> status == TBM_ONE_PAGE )
1030
1027
page = & tbm -> entry1 ;
1031
1028
else
1032
1029
page = tbm -> spages [iterator -> spageptr ];
1033
1030
1034
- /* scan bitmap to extract individual offset numbers */
1035
- ntuples = tbm_extract_page_tuple (page , output );
1031
+ output -> internal_page = page ;
1036
1032
output -> blockno = page -> blockno ;
1037
- output -> ntuples = ntuples ;
1038
1033
output -> lossy = false;
1039
1034
output -> recheck = page -> recheck ;
1040
1035
iterator -> spageptr ++ ;
@@ -1107,9 +1102,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
1107
1102
{
1108
1103
/* Return a lossy page indicator from the chunk */
1109
1104
output -> blockno = chunk_blockno ;
1110
- output -> ntuples = -1 ;
1111
1105
output -> lossy = true;
1112
1106
output -> recheck = true;
1107
+ output -> internal_page = NULL ;
1113
1108
istate -> schunkbit ++ ;
1114
1109
1115
1110
LWLockRelease (& istate -> lock );
@@ -1120,12 +1115,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
1120
1115
if (istate -> spageptr < istate -> npages )
1121
1116
{
1122
1117
PagetableEntry * page = & ptbase [idxpages [istate -> spageptr ]];
1123
- int ntuples ;
1124
1118
1125
- /* scan bitmap to extract individual offset numbers */
1126
- ntuples = tbm_extract_page_tuple (page , output );
1119
+ output -> internal_page = page ;
1127
1120
output -> blockno = page -> blockno ;
1128
- output -> ntuples = ntuples ;
1129
1121
output -> lossy = false;
1130
1122
output -> recheck = page -> recheck ;
1131
1123
istate -> spageptr ++ ;
@@ -1473,8 +1465,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
1473
1465
* Create the TBMSharedIterator struct, with enough trailing space to
1474
1466
* serve the needs of the TBMIterateResult sub-struct.
1475
1467
*/
1476
- iterator = (TBMSharedIterator * ) palloc0 (sizeof (TBMSharedIterator ) +
1477
- MAX_TUPLES_PER_PAGE * sizeof (OffsetNumber ));
1468
+ iterator = (TBMSharedIterator * ) palloc0 (sizeof (TBMSharedIterator ));
1478
1469
1479
1470
istate = (TBMSharedIteratorState * ) dsa_get_address (dsa , dp );
1480
1471
0 commit comments