gist_private.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*-------------------------------------------------------------------------
  2. *
  3. * gist_private.h
  4. * private declarations for GiST -- declarations related to the
  5. * internal implementation of GiST, not the public API
  6. *
  7. * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  8. * Portions Copyright (c) 1994, Regents of the University of California
  9. *
  10. * src/include/access/gist_private.h
  11. *
  12. *-------------------------------------------------------------------------
  13. */
  14. #ifndef GIST_PRIVATE_H
  15. #define GIST_PRIVATE_H
  16. #include "access/amapi.h"
  17. #include "access/gist.h"
  18. #include "access/itup.h"
  19. #include "access/xlogreader.h"
  20. #include "fmgr.h"
  21. #include "lib/pairingheap.h"
  22. #include "storage/bufmgr.h"
  23. #include "storage/buffile.h"
  24. #include "utils/hsearch.h"
  25. #include "access/genam.h"
  26. /*
  27. * Maximum number of "halves" a page can be split into in one operation.
  28. * Typically a split produces 2 halves, but can be more if keys have very
  29. * different lengths, or when inserting multiple keys in one operation (as
  30. * when inserting downlinks to an internal node). There is no theoretical
  31. * limit on this, but in practice if you get more than a handful page halves
  32. * in one split, there's something wrong with the opclass implementation.
  33. * GIST_MAX_SPLIT_PAGES is an arbitrary limit on that, used to size some
  34. * local arrays used during split. Note that there is also a limit on the
  35. * number of buffers that can be held locked at a time, MAX_SIMUL_LWLOCKS,
  36. * so if you raise this higher than that limit, you'll just get a different
  37. * error.
  38. */
  39. #define GIST_MAX_SPLIT_PAGES 75
  40. /* Buffer lock modes */
  41. #define GIST_SHARE BUFFER_LOCK_SHARE
  42. #define GIST_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
  43. #define GIST_UNLOCK BUFFER_LOCK_UNLOCK
  44. typedef struct
  45. {
  46. BlockNumber prev;
  47. uint32 freespace;
  48. char tupledata[FLEXIBLE_ARRAY_MEMBER];
  49. } GISTNodeBufferPage;
  50. #define BUFFER_PAGE_DATA_OFFSET MAXALIGN(offsetof(GISTNodeBufferPage, tupledata))
  51. /* Returns free space in node buffer page */
  52. #define PAGE_FREE_SPACE(nbp) (nbp->freespace)
  53. /* Checks if node buffer page is empty */
  54. #define PAGE_IS_EMPTY(nbp) (nbp->freespace == BLCKSZ - BUFFER_PAGE_DATA_OFFSET)
  55. /* Checks if node buffers page don't contain sufficient space for index tuple */
  56. #define PAGE_NO_SPACE(nbp, itup) (PAGE_FREE_SPACE(nbp) < \
  57. MAXALIGN(IndexTupleSize(itup)))
  58. /*
  59. * GISTSTATE: information needed for any GiST index operation
  60. *
  61. * This struct retains call info for the index's opclass-specific support
  62. * functions (per index column), plus the index's tuple descriptor.
  63. *
  64. * scanCxt holds the GISTSTATE itself as well as any data that lives for the
  65. * lifetime of the index operation. We pass this to the support functions
  66. * via fn_mcxt, so that they can store scan-lifespan data in it. The
  67. * functions are invoked in tempCxt, which is typically short-lifespan
  68. * (that is, it's reset after each tuple). However, tempCxt can be the same
  69. * as scanCxt if we're not bothering with per-tuple context resets.
  70. */
  71. typedef struct GISTSTATE
  72. {
  73. MemoryContext scanCxt; /* context for scan-lifespan data */
  74. MemoryContext tempCxt; /* short-term context for calling functions */
  75. TupleDesc tupdesc; /* index's tuple descriptor */
  76. TupleDesc fetchTupdesc; /* tuple descriptor for tuples returned in an
  77. * index-only scan */
  78. FmgrInfo consistentFn[INDEX_MAX_KEYS];
  79. FmgrInfo unionFn[INDEX_MAX_KEYS];
  80. FmgrInfo compressFn[INDEX_MAX_KEYS];
  81. FmgrInfo decompressFn[INDEX_MAX_KEYS];
  82. FmgrInfo penaltyFn[INDEX_MAX_KEYS];
  83. FmgrInfo picksplitFn[INDEX_MAX_KEYS];
  84. FmgrInfo equalFn[INDEX_MAX_KEYS];
  85. FmgrInfo distanceFn[INDEX_MAX_KEYS];
  86. FmgrInfo fetchFn[INDEX_MAX_KEYS];
  87. /* Collations to pass to the support functions */
  88. Oid supportCollation[INDEX_MAX_KEYS];
  89. } GISTSTATE;
  90. /*
  91. * During a GiST index search, we must maintain a queue of unvisited items,
  92. * which can be either individual heap tuples or whole index pages. If it
  93. * is an ordered search, the unvisited items should be visited in distance
  94. * order. Unvisited items at the same distance should be visited in
  95. * depth-first order, that is heap items first, then lower index pages, then
  96. * upper index pages; this rule avoids doing extra work during a search that
  97. * ends early due to LIMIT.
  98. *
  99. * To perform an ordered search, we use a pairing heap to manage the
  100. * distance-order queue. In a non-ordered search (no order-by operators),
  101. * we use it to return heap tuples before unvisited index pages, to
  102. * ensure depth-first order, but all entries are otherwise considered
  103. * equal.
  104. */
  105. /* Individual heap tuple to be visited */
  106. typedef struct GISTSearchHeapItem
  107. {
  108. ItemPointerData heapPtr;
  109. bool recheck; /* T if quals must be rechecked */
  110. bool recheckDistances; /* T if distances must be rechecked */
  111. IndexTuple ftup; /* data fetched back from the index, used in
  112. * index-only scans */
  113. OffsetNumber offnum; /* track offset in page to mark tuple as
  114. * LP_DEAD */
  115. } GISTSearchHeapItem;
  116. /* Unvisited item, either index page or heap tuple */
  117. typedef struct GISTSearchItem
  118. {
  119. pairingheap_node phNode;
  120. BlockNumber blkno; /* index page number, or InvalidBlockNumber */
  121. union
  122. {
  123. GistNSN parentlsn; /* parent page's LSN, if index page */
  124. /* we must store parentlsn to detect whether a split occurred */
  125. GISTSearchHeapItem heap; /* heap info, if heap tuple */
  126. } data;
  127. double distances[FLEXIBLE_ARRAY_MEMBER]; /* numberOfOrderBys
  128. * entries */
  129. } GISTSearchItem;
  130. #define GISTSearchItemIsHeap(item) ((item).blkno == InvalidBlockNumber)
  131. #define SizeOfGISTSearchItem(n_distances) (offsetof(GISTSearchItem, distances) + sizeof(double) * (n_distances))
  132. /*
  133. * GISTScanOpaqueData: private state for a scan of a GiST index
  134. */
  135. typedef struct GISTScanOpaqueData
  136. {
  137. GISTSTATE *giststate; /* index information, see above */
  138. Oid *orderByTypes; /* datatypes of ORDER BY expressions */
  139. pairingheap *queue; /* queue of unvisited items */
  140. MemoryContext queueCxt; /* context holding the queue */
  141. bool qual_ok; /* false if qual can never be satisfied */
  142. bool firstCall; /* true until first gistgettuple call */
  143. /* pre-allocated workspace arrays */
  144. double *distances; /* output area for gistindex_keytest */
  145. /* info about killed items if any (killedItems is NULL if never used) */
  146. OffsetNumber *killedItems; /* offset numbers of killed items */
  147. int numKilled; /* number of currently stored items */
  148. BlockNumber curBlkno; /* current number of block */
  149. GistNSN curPageLSN; /* pos in the WAL stream when page was read */
  150. /* In a non-ordered search, returnable heap items are stored here: */
  151. GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
  152. OffsetNumber nPageData; /* number of valid items in array */
  153. OffsetNumber curPageData; /* next item to return */
  154. MemoryContext pageDataCxt; /* context holding the fetched tuples, for
  155. * index-only scans */
  156. } GISTScanOpaqueData;
  157. typedef GISTScanOpaqueData *GISTScanOpaque;
  158. /* XLog stuff */
  159. #define XLOG_GIST_PAGE_UPDATE 0x00
  160. /* #define XLOG_GIST_NEW_ROOT 0x20 */ /* not used anymore */
  161. #define XLOG_GIST_PAGE_SPLIT 0x30
  162. /* #define XLOG_GIST_INSERT_COMPLETE 0x40 */ /* not used anymore */
  163. #define XLOG_GIST_CREATE_INDEX 0x50
  164. /* #define XLOG_GIST_PAGE_DELETE 0x60 */ /* not used anymore */
  165. /*
  166. * Backup Blk 0: updated page.
  167. * Backup Blk 1: If this operation completes a page split, by inserting a
  168. * downlink for the split page, the left half of the split
  169. */
  170. typedef struct gistxlogPageUpdate
  171. {
  172. /* number of deleted offsets */
  173. uint16 ntodelete;
  174. uint16 ntoinsert;
  175. /*
  176. * In payload of blk 0 : 1. todelete OffsetNumbers 2. tuples to insert
  177. */
  178. } gistxlogPageUpdate;
  179. /*
  180. * Backup Blk 0: If this operation completes a page split, by inserting a
  181. * downlink for the split page, the left half of the split
  182. * Backup Blk 1 - npage: split pages (1 is the original page)
  183. */
  184. typedef struct gistxlogPageSplit
  185. {
  186. BlockNumber origrlink; /* rightlink of the page before split */
  187. GistNSN orignsn; /* NSN of the page before split */
  188. bool origleaf; /* was splitted page a leaf page? */
  189. uint16 npage; /* # of pages in the split */
  190. bool markfollowright; /* set F_FOLLOW_RIGHT flags */
  191. /*
  192. * follow: 1. gistxlogPage and array of IndexTupleData per page
  193. */
  194. } gistxlogPageSplit;
  195. typedef struct gistxlogPage
  196. {
  197. BlockNumber blkno;
  198. int num; /* number of index tuples following */
  199. } gistxlogPage;
  200. /* SplitedPageLayout - gistSplit function result */
  201. typedef struct SplitedPageLayout
  202. {
  203. gistxlogPage block;
  204. IndexTupleData *list;
  205. int lenlist;
  206. IndexTuple itup; /* union key for page */
  207. Page page; /* to operate */
  208. Buffer buffer; /* to write after all proceed */
  209. struct SplitedPageLayout *next;
  210. } SplitedPageLayout;
  211. /*
  212. * GISTInsertStack used for locking buffers and transfer arguments during
  213. * insertion
  214. */
  215. typedef struct GISTInsertStack
  216. {
  217. /* current page */
  218. BlockNumber blkno;
  219. Buffer buffer;
  220. Page page;
  221. /*
  222. * log sequence number from page->lsn to recognize page update and compare
  223. * it with page's nsn to recognize page split
  224. */
  225. GistNSN lsn;
  226. /* offset of the downlink in the parent page, that points to this page */
  227. OffsetNumber downlinkoffnum;
  228. /* pointer to parent */
  229. struct GISTInsertStack *parent;
  230. } GISTInsertStack;
  231. /* Working state and results for multi-column split logic in gistsplit.c */
  232. typedef struct GistSplitVector
  233. {
  234. GIST_SPLITVEC splitVector; /* passed to/from user PickSplit method */
  235. Datum spl_lattr[INDEX_MAX_KEYS]; /* Union of subkeys in
  236. * splitVector.spl_left */
  237. bool spl_lisnull[INDEX_MAX_KEYS];
  238. Datum spl_rattr[INDEX_MAX_KEYS]; /* Union of subkeys in
  239. * splitVector.spl_right */
  240. bool spl_risnull[INDEX_MAX_KEYS];
  241. bool *spl_dontcare; /* flags tuples which could go to either side
  242. * of the split for zero penalty */
  243. } GistSplitVector;
  244. typedef struct
  245. {
  246. Relation r;
  247. Size freespace; /* free space to be left */
  248. GISTInsertStack *stack;
  249. } GISTInsertState;
  250. /* root page of a gist index */
  251. #define GIST_ROOT_BLKNO 0
  252. /*
  253. * Before PostgreSQL 9.1, we used to rely on so-called "invalid tuples" on
  254. * inner pages to finish crash recovery of incomplete page splits. If a crash
  255. * happened in the middle of a page split, so that the downlink pointers were
  256. * not yet inserted, crash recovery inserted a special downlink pointer. The
  257. * semantics of an invalid tuple was that it if you encounter one in a scan,
  258. * it must always be followed, because we don't know if the tuples on the
  259. * child page match or not.
  260. *
  261. * We no longer create such invalid tuples, we now mark the left-half of such
  262. * an incomplete split with the F_FOLLOW_RIGHT flag instead, and finish the
  263. * split properly the next time we need to insert on that page. To retain
  264. * on-disk compatibility for the sake of pg_upgrade, we still store 0xffff as
  265. * the offset number of all inner tuples. If we encounter any invalid tuples
  266. * with 0xfffe during insertion, we throw an error, though scans still handle
  267. * them. You should only encounter invalid tuples if you pg_upgrade a pre-9.1
  268. * gist index which already has invalid tuples in it because of a crash. That
  269. * should be rare, and you are recommended to REINDEX anyway if you have any
  270. * invalid tuples in an index, so throwing an error is as far as we go with
  271. * supporting that.
  272. */
  273. #define TUPLE_IS_VALID 0xffff
  274. #define TUPLE_IS_INVALID 0xfffe
  275. #define GistTupleIsInvalid(itup) ( ItemPointerGetOffsetNumber( &((itup)->t_tid) ) == TUPLE_IS_INVALID )
  276. #define GistTupleSetValid(itup) ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_VALID )
  277. /*
  278. * A buffer attached to an internal node, used when building an index in
  279. * buffering mode.
  280. */
  281. typedef struct
  282. {
  283. BlockNumber nodeBlocknum; /* index block # this buffer is for */
  284. int32 blocksCount; /* current # of blocks occupied by buffer */
  285. BlockNumber pageBlocknum; /* temporary file block # */
  286. GISTNodeBufferPage *pageBuffer; /* in-memory buffer page */
  287. /* is this buffer queued for emptying? */
  288. bool queuedForEmptying;
  289. /* is this a temporary copy, not in the hash table? */
  290. bool isTemp;
  291. int level; /* 0 == leaf */
  292. } GISTNodeBuffer;
  293. /*
  294. * Does specified level have buffers? (Beware of multiple evaluation of
  295. * arguments.)
  296. */
  297. #define LEVEL_HAS_BUFFERS(nlevel, gfbb) \
  298. ((nlevel) != 0 && (nlevel) % (gfbb)->levelStep == 0 && \
  299. (nlevel) != (gfbb)->rootlevel)
  300. /* Is specified buffer at least half-filled (should be queued for emptying)? */
  301. #define BUFFER_HALF_FILLED(nodeBuffer, gfbb) \
  302. ((nodeBuffer)->blocksCount > (gfbb)->pagesPerBuffer / 2)
  303. /*
  304. * Is specified buffer full? Our buffers can actually grow indefinitely,
  305. * beyond the "maximum" size, so this just means whether the buffer has grown
  306. * beyond the nominal maximum size.
  307. */
  308. #define BUFFER_OVERFLOWED(nodeBuffer, gfbb) \
  309. ((nodeBuffer)->blocksCount > (gfbb)->pagesPerBuffer)
  310. /*
  311. * Data structure with general information about build buffers.
  312. */
  313. typedef struct GISTBuildBuffers
  314. {
  315. /* Persistent memory context for the buffers and metadata. */
  316. MemoryContext context;
  317. BufFile *pfile; /* Temporary file to store buffers in */
  318. long nFileBlocks; /* Current size of the temporary file */
  319. /*
  320. * resizable array of free blocks.
  321. */
  322. long *freeBlocks;
  323. int nFreeBlocks; /* # of currently free blocks in the array */
  324. int freeBlocksLen; /* current allocated length of the array */
  325. /* Hash for buffers by block number */
  326. HTAB *nodeBuffersTab;
  327. /* List of buffers scheduled for emptying */
  328. List *bufferEmptyingQueue;
  329. /*
  330. * Parameters to the buffering build algorithm. levelStep determines which
  331. * levels in the tree have buffers, and pagesPerBuffer determines how
  332. * large each buffer is.
  333. */
  334. int levelStep;
  335. int pagesPerBuffer;
  336. /* Array of lists of buffers on each level, for final emptying */
  337. List **buffersOnLevels;
  338. int buffersOnLevelsLen;
  339. /*
  340. * Dynamically-sized array of buffers that currently have their last page
  341. * loaded in main memory.
  342. */
  343. GISTNodeBuffer **loadedBuffers;
  344. int loadedBuffersCount; /* # of entries in loadedBuffers */
  345. int loadedBuffersLen; /* allocated size of loadedBuffers */
  346. /* Level of the current root node (= height of the index tree - 1) */
  347. int rootlevel;
  348. } GISTBuildBuffers;
  349. /*
  350. * Storage type for GiST's reloptions
  351. */
  352. typedef struct GiSTOptions
  353. {
  354. int32 vl_len_; /* varlena header (do not touch directly!) */
  355. int fillfactor; /* page fill factor in percent (0..100) */
  356. int bufferingModeOffset; /* use buffering build? */
  357. } GiSTOptions;
  358. /* gist.c */
  359. extern Datum gisthandler(PG_FUNCTION_ARGS);
  360. extern void gistbuildempty(Relation index);
  361. extern bool gistinsert(Relation r, Datum *values, bool *isnull,
  362. ItemPointer ht_ctid, Relation heapRel,
  363. IndexUniqueCheck checkUnique);
  364. extern MemoryContext createTempGistContext(void);
  365. extern GISTSTATE *initGISTstate(Relation index);
  366. extern void freeGISTstate(GISTSTATE *giststate);
  367. extern void gistdoinsert(Relation r,
  368. IndexTuple itup,
  369. Size freespace,
  370. GISTSTATE *GISTstate);
  371. /* A List of these is returned from gistplacetopage() in *splitinfo */
  372. typedef struct
  373. {
  374. Buffer buf; /* the split page "half" */
  375. IndexTuple downlink; /* downlink for this half. */
  376. } GISTPageSplitInfo;
  377. extern bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  378. Buffer buffer,
  379. IndexTuple *itup, int ntup,
  380. OffsetNumber oldoffnum, BlockNumber *newblkno,
  381. Buffer leftchildbuf,
  382. List **splitinfo,
  383. bool markleftchild);
  384. extern SplitedPageLayout *gistSplit(Relation r, Page page, IndexTuple *itup,
  385. int len, GISTSTATE *giststate);
  386. /* gistxlog.c */
  387. extern void gist_redo(XLogReaderState *record);
  388. extern void gist_desc(StringInfo buf, XLogReaderState *record);
  389. extern const char *gist_identify(uint8 info);
  390. extern void gist_xlog_startup(void);
  391. extern void gist_xlog_cleanup(void);
  392. extern XLogRecPtr gistXLogUpdate(Buffer buffer,
  393. OffsetNumber *todelete, int ntodelete,
  394. IndexTuple *itup, int ntup,
  395. Buffer leftchild);
  396. extern XLogRecPtr gistXLogSplit(bool page_is_leaf,
  397. SplitedPageLayout *dist,
  398. BlockNumber origrlink, GistNSN oldnsn,
  399. Buffer leftchild, bool markfollowright);
  400. /* gistget.c */
  401. extern bool gistgettuple(IndexScanDesc scan, ScanDirection dir);
  402. extern int64 gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
  403. extern bool gistcanreturn(Relation index, int attno);
  404. /* gistvalidate.c */
  405. extern bool gistvalidate(Oid opclassoid);
  406. /* gistutil.c */
  407. #define GiSTPageSize \
  408. ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GISTPageOpaqueData)) )
  409. #define GIST_MIN_FILLFACTOR 10
  410. #define GIST_DEFAULT_FILLFACTOR 90
  411. extern bytea *gistoptions(Datum reloptions, bool validate);
  412. extern bool gistproperty(Oid index_oid, int attno,
  413. IndexAMProperty prop, const char *propname,
  414. bool *res, bool *isnull);
  415. extern bool gistfitpage(IndexTuple *itvec, int len);
  416. extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
  417. extern void gistcheckpage(Relation rel, Buffer buf);
  418. extern Buffer gistNewBuffer(Relation r);
  419. extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
  420. OffsetNumber off);
  421. extern IndexTuple *gistextractpage(Page page, int *len /* out */ );
  422. extern IndexTuple *gistjoinvector(
  423. IndexTuple *itvec, int *len,
  424. IndexTuple *additvec, int addlen);
  425. extern IndexTupleData *gistfillitupvec(IndexTuple *vec, int veclen, int *memlen);
  426. extern IndexTuple gistunion(Relation r, IndexTuple *itvec,
  427. int len, GISTSTATE *giststate);
  428. extern IndexTuple gistgetadjusted(Relation r,
  429. IndexTuple oldtup,
  430. IndexTuple addtup,
  431. GISTSTATE *giststate);
  432. extern IndexTuple gistFormTuple(GISTSTATE *giststate,
  433. Relation r, Datum *attdata, bool *isnull, bool isleaf);
  434. extern OffsetNumber gistchoose(Relation r, Page p,
  435. IndexTuple it,
  436. GISTSTATE *giststate);
  437. extern void GISTInitBuffer(Buffer b, uint32 f);
  438. extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
  439. Datum k, Relation r, Page pg, OffsetNumber o,
  440. bool l, bool isNull);
  441. extern float gistpenalty(GISTSTATE *giststate, int attno,
  442. GISTENTRY *key1, bool isNull1,
  443. GISTENTRY *key2, bool isNull2);
  444. extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
  445. Datum *attr, bool *isnull);
  446. extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
  447. extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
  448. OffsetNumber o, GISTENTRY *attdata, bool *isnull);
  449. extern IndexTuple gistFetchTuple(GISTSTATE *giststate, Relation r,
  450. IndexTuple tuple);
  451. extern void gistMakeUnionKey(GISTSTATE *giststate, int attno,
  452. GISTENTRY *entry1, bool isnull1,
  453. GISTENTRY *entry2, bool isnull2,
  454. Datum *dst, bool *dstisnull);
  455. extern XLogRecPtr gistGetFakeLSN(Relation rel);
  456. /* gistvacuum.c */
  457. extern IndexBulkDeleteResult *gistbulkdelete(IndexVacuumInfo *info,
  458. IndexBulkDeleteResult *stats,
  459. IndexBulkDeleteCallback callback,
  460. void *callback_state);
  461. extern IndexBulkDeleteResult *gistvacuumcleanup(IndexVacuumInfo *info,
  462. IndexBulkDeleteResult *stats);
  463. /* gistsplit.c */
  464. extern void gistSplitByKey(Relation r, Page page, IndexTuple *itup,
  465. int len, GISTSTATE *giststate,
  466. GistSplitVector *v,
  467. int attno);
  468. /* gistbuild.c */
  469. extern IndexBuildResult *gistbuild(Relation heap, Relation index,
  470. struct IndexInfo *indexInfo);
  471. extern void gistValidateBufferingOption(char *value);
  472. /* gistbuildbuffers.c */
  473. extern GISTBuildBuffers *gistInitBuildBuffers(int pagesPerBuffer, int levelStep,
  474. int maxLevel);
  475. extern GISTNodeBuffer *gistGetNodeBuffer(GISTBuildBuffers *gfbb,
  476. GISTSTATE *giststate,
  477. BlockNumber blkno, int level);
  478. extern void gistPushItupToNodeBuffer(GISTBuildBuffers *gfbb,
  479. GISTNodeBuffer *nodeBuffer, IndexTuple item);
  480. extern bool gistPopItupFromNodeBuffer(GISTBuildBuffers *gfbb,
  481. GISTNodeBuffer *nodeBuffer, IndexTuple *item);
  482. extern void gistFreeBuildBuffers(GISTBuildBuffers *gfbb);
  483. extern void gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb,
  484. GISTSTATE *giststate, Relation r,
  485. int level, Buffer buffer,
  486. List *splitinfo);
  487. extern void gistUnloadNodeBuffers(GISTBuildBuffers *gfbb);
  488. #endif /* GIST_PRIVATE_H */