1 /*-------------------------------------------------------------------------
2  *
3  * bloom.h
4  *	  Header for bloom index.
5  *
6  * Copyright (c) 2016, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  *	  contrib/bloom/bloom.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 #ifndef _BLOOM_H_
14 #define _BLOOM_H_
15 
16 #include "access/amapi.h"
17 #include "access/generic_xlog.h"
18 #include "access/itup.h"
19 #include "access/xlog.h"
20 #include "nodes/relation.h"
21 #include "fmgr.h"
22 
23 /* Support procedures numbers */
24 #define BLOOM_HASH_PROC			1
25 #define BLOOM_NPROC				1
26 
27 /* Scan strategies */
28 #define BLOOM_EQUAL_STRATEGY	1
29 #define BLOOM_NSTRATEGIES		1
30 
31 /* Opaque for bloom pages */
32 typedef struct BloomPageOpaqueData
33 {
34 	OffsetNumber maxoff;		/* number of index tuples on page */
35 	uint16		flags;			/* see bit definitions below */
36 	uint16		unused;			/* placeholder to force maxaligning of size of
37 								 * BloomPageOpaqueData and to place
38 								 * bloom_page_id exactly at the end of page */
39 	uint16		bloom_page_id;	/* for identification of BLOOM indexes */
40 } BloomPageOpaqueData;
41 
42 typedef BloomPageOpaqueData *BloomPageOpaque;
43 
44 /* Bloom page flags */
45 #define BLOOM_META		(1<<0)
46 #define BLOOM_DELETED	(2<<0)
47 
48 /*
49  * The page ID is for the convenience of pg_filedump and similar utilities,
50  * which otherwise would have a hard time telling pages of different index
51  * types apart.  It should be the last 2 bytes on the page.  This is more or
52  * less "free" due to alignment considerations.
53  *
54  * See comments above GinPageOpaqueData.
55  */
56 #define BLOOM_PAGE_ID		0xFF83
57 
58 /* Macros for accessing bloom page structures */
59 #define BloomPageGetOpaque(page) ((BloomPageOpaque) PageGetSpecialPointer(page))
60 #define BloomPageGetMaxOffset(page) (BloomPageGetOpaque(page)->maxoff)
61 #define BloomPageIsMeta(page) \
62 	((BloomPageGetOpaque(page)->flags & BLOOM_META) != 0)
63 #define BloomPageIsDeleted(page) \
64 	((BloomPageGetOpaque(page)->flags & BLOOM_DELETED) != 0)
65 #define BloomPageSetDeleted(page) \
66 	(BloomPageGetOpaque(page)->flags |= BLOOM_DELETED)
67 #define BloomPageSetNonDeleted(page) \
68 	(BloomPageGetOpaque(page)->flags &= ~BLOOM_DELETED)
69 #define BloomPageGetData(page)		((BloomTuple *)PageGetContents(page))
70 #define BloomPageGetTuple(state, page, offset) \
71 	((BloomTuple *)(PageGetContents(page) \
72 		+ (state)->sizeOfBloomTuple * ((offset) - 1)))
73 #define BloomPageGetNextTuple(state, tuple) \
74 	((BloomTuple *)((Pointer)(tuple) + (state)->sizeOfBloomTuple))
75 
76 /* Preserved page numbers */
77 #define BLOOM_METAPAGE_BLKNO	(0)
78 #define BLOOM_HEAD_BLKNO		(1)		/* first data page */
79 
80 /*
81  * We store Bloom signatures as arrays of uint16 words.
82  */
83 typedef uint16 BloomSignatureWord;
84 
85 #define SIGNWORDBITS ((int) (BITS_PER_BYTE * sizeof(BloomSignatureWord)))
86 
87 /*
88  * Default and maximum Bloom signature length in bits.
89  */
90 #define DEFAULT_BLOOM_LENGTH	(5 * SIGNWORDBITS)
91 #define MAX_BLOOM_LENGTH		(256 * SIGNWORDBITS)
92 
93 /*
94  * Default and maximum signature bits generated per index key.
95  */
96 #define DEFAULT_BLOOM_BITS		2
97 #define MAX_BLOOM_BITS			(MAX_BLOOM_LENGTH - 1)
98 
99 /* Bloom index options */
100 typedef struct BloomOptions
101 {
102 	int32		vl_len_;		/* varlena header (do not touch directly!) */
103 	int			bloomLength;	/* length of signature in words (not bits!) */
104 	int			bitSize[INDEX_MAX_KEYS];		/* # of bits generated for
105 												 * each index key */
106 } BloomOptions;
107 
108 /*
109  * FreeBlockNumberArray - array of block numbers sized so that metadata fill
110  * all space in metapage.
111  */
112 typedef BlockNumber FreeBlockNumberArray[
113 										 MAXALIGN_DOWN(
114 		BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(BloomPageOpaqueData))
115 	   - MAXALIGN(sizeof(uint16) * 2 + sizeof(uint32) + sizeof(BloomOptions))
116 													   ) / sizeof(BlockNumber)
117 ];
118 
119 /* Metadata of bloom index */
120 typedef struct BloomMetaPageData
121 {
122 	uint32		magickNumber;
123 	uint16		nStart;
124 	uint16		nEnd;
125 	BloomOptions opts;
126 	FreeBlockNumberArray notFullPage;
127 } BloomMetaPageData;
128 
129 /* Magic number to distinguish bloom pages among anothers */
130 #define BLOOM_MAGICK_NUMBER (0xDBAC0DED)
131 
132 /* Number of blocks numbers fit in BloomMetaPageData */
133 #define BloomMetaBlockN		(sizeof(FreeBlockNumberArray) / sizeof(BlockNumber))
134 
135 #define BloomPageGetMeta(page)	((BloomMetaPageData *) PageGetContents(page))
136 
137 typedef struct BloomState
138 {
139 	FmgrInfo	hashFn[INDEX_MAX_KEYS];
140 	BloomOptions opts;			/* copy of options on index's metapage */
141 	int32		nColumns;
142 
143 	/*
144 	 * sizeOfBloomTuple is index-specific, and it depends on reloptions, so
145 	 * precompute it
146 	 */
147 	Size		sizeOfBloomTuple;
148 } BloomState;
149 
150 #define BloomPageGetFreeSpace(state, page) \
151 	(BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \
152 		- BloomPageGetMaxOffset(page) * (state)->sizeOfBloomTuple \
153 		- MAXALIGN(sizeof(BloomPageOpaqueData)))
154 
155 /*
156  * Tuples are very different from all other relations
157  */
158 typedef struct BloomTuple
159 {
160 	ItemPointerData heapPtr;
161 	BloomSignatureWord sign[FLEXIBLE_ARRAY_MEMBER];
162 } BloomTuple;
163 
164 #define BLOOMTUPLEHDRSZ offsetof(BloomTuple, sign)
165 
166 /* Opaque data structure for bloom index scan */
167 typedef struct BloomScanOpaqueData
168 {
169 	BloomSignatureWord *sign;	/* Scan signature */
170 	BloomState	state;
171 } BloomScanOpaqueData;
172 
173 typedef BloomScanOpaqueData *BloomScanOpaque;
174 
175 /* blutils.c */
176 extern void _PG_init(void);
177 extern Datum blhandler(PG_FUNCTION_ARGS);
178 extern void initBloomState(BloomState *state, Relation index);
179 extern void BloomFillMetapage(Relation index, Page metaPage);
180 extern void BloomInitMetapage(Relation index);
181 extern void BloomInitPage(Page page, uint16 flags);
182 extern Buffer BloomNewBuffer(Relation index);
183 extern void signValue(BloomState *state, BloomSignatureWord *sign, Datum value, int attno);
184 extern BloomTuple *BloomFormTuple(BloomState *state, ItemPointer iptr, Datum *values, bool *isnull);
185 extern bool BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple);
186 
187 /* blvalidate.c */
188 extern bool blvalidate(Oid opclassoid);
189 
190 /* index access method interface functions */
191 extern bool blinsert(Relation index, Datum *values, bool *isnull,
192 		 ItemPointer ht_ctid, Relation heapRel,
193 		 IndexUniqueCheck checkUnique);
194 extern IndexScanDesc blbeginscan(Relation r, int nkeys, int norderbys);
195 extern int64 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
196 extern void blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
197 		 ScanKey orderbys, int norderbys);
198 extern void blendscan(IndexScanDesc scan);
199 extern IndexBuildResult *blbuild(Relation heap, Relation index,
200 		struct IndexInfo *indexInfo);
201 extern void blbuildempty(Relation index);
202 extern IndexBulkDeleteResult *blbulkdelete(IndexVacuumInfo *info,
203 			 IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback,
204 			 void *callback_state);
205 extern IndexBulkDeleteResult *blvacuumcleanup(IndexVacuumInfo *info,
206 				IndexBulkDeleteResult *stats);
207 extern bytea *bloptions(Datum reloptions, bool validate);
208 extern void blcostestimate(PlannerInfo *root, IndexPath *path,
209 			   double loop_count, Cost *indexStartupCost,
210 			   Cost *indexTotalCost, Selectivity *indexSelectivity,
211 			   double *indexCorrelation);
212 
213 #endif
214