PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ginbulk.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/gin_private.h"
#include "utils/datum.h"
#include "utils/memutils.h"
Include dependency graph for ginbulk.c:

Go to the source code of this file.

Macros

#define DEF_NENTRY   2048 /* GinEntryAccumulator allocation quantum */
 
#define DEF_NPTR   5 /* ItemPointer initial allocation quantum */
 

Functions

static void ginCombineData (RBNode *existing, const RBNode *newdata, void *arg)
 
static int cmpEntryAccumulator (const RBNode *a, const RBNode *b, void *arg)
 
static RBNodeginAllocEntryAccumulator (void *arg)
 
void ginInitBA (BuildAccumulator *accum)
 
static Datum getDatumCopy (BuildAccumulator *accum, OffsetNumber attnum, Datum value)
 
static void ginInsertBAEntry (BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum key, GinNullCategory category)
 
void ginInsertBAEntries (BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
 
static int qsortCompareItemPointers (const void *a, const void *b)
 
void ginBeginBAScan (BuildAccumulator *accum)
 
ItemPointerDataginGetBAEntry (BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
 

Macro Definition Documentation

#define DEF_NENTRY   2048 /* GinEntryAccumulator allocation quantum */

Definition at line 24 of file ginbulk.c.

Referenced by ginAllocEntryAccumulator().

#define DEF_NPTR   5 /* ItemPointer initial allocation quantum */

Definition at line 25 of file ginbulk.c.

Referenced by ginInsertBAEntry().

Function Documentation

static int cmpEntryAccumulator ( const RBNode a,
const RBNode b,
void *  arg 
)
static

Definition at line 72 of file ginbulk.c.

References GinEntryAccumulator::attnum, GinEntryAccumulator::category, ginCompareAttEntries(), BuildAccumulator::ginstate, and GinEntryAccumulator::key.

Referenced by ginInitBA().

73 {
74  const GinEntryAccumulator *ea = (const GinEntryAccumulator *) a;
75  const GinEntryAccumulator *eb = (const GinEntryAccumulator *) b;
77 
78  return ginCompareAttEntries(accum->ginstate,
79  ea->attnum, ea->key, ea->category,
80  eb->attnum, eb->key, eb->category);
81 }
OffsetNumber attnum
Definition: gin_private.h:398
int ginCompareAttEntries(GinState *ginstate, OffsetNumber attnuma, Datum a, GinNullCategory categorya, OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:405
GinNullCategory category
Definition: gin_private.h:397
GinState * ginstate
Definition: gin_private.h:407
void * arg
static Datum getDatumCopy ( BuildAccumulator accum,
OffsetNumber  attnum,
Datum  value 
)
static

Definition at line 128 of file ginbulk.c.

References BuildAccumulator::allocatedMemory, datumCopy(), DatumGetPointer, GetMemoryChunkSpace(), BuildAccumulator::ginstate, GinState::origTupdesc, TupleDescAttr, and value.

Referenced by ginInsertBAEntry().

129 {
130  Form_pg_attribute att;
131  Datum res;
132 
133  att = TupleDescAttr(accum->ginstate->origTupdesc, attnum - 1);
134  if (att->attbyval)
135  res = value;
136  else
137  {
138  res = datumCopy(value, false, att->attlen);
140  }
141  return res;
142 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
static struct @121 value
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
GinState * ginstate
Definition: gin_private.h:407
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define DatumGetPointer(X)
Definition: postgres.h:555
TupleDesc origTupdesc
Definition: gin_private.h:67
static RBNode* ginAllocEntryAccumulator ( void *  arg)
static

Definition at line 85 of file ginbulk.c.

References BuildAccumulator::allocatedMemory, DEF_NENTRY, BuildAccumulator::eas_used, BuildAccumulator::entryallocator, GetMemoryChunkSpace(), and palloc().

Referenced by ginInitBA().

86 {
89 
90  /*
91  * Allocate memory by rather big chunks to decrease overhead. We have no
92  * need to reclaim RBNodes individually, so this costs nothing.
93  */
94  if (accum->entryallocator == NULL || accum->eas_used >= DEF_NENTRY)
95  {
98  accum->eas_used = 0;
99  }
100 
101  /* Allocate new RBNode from current chunk */
102  ea = accum->entryallocator + accum->eas_used;
103  accum->eas_used++;
104 
105  return (RBNode *) ea;
106 }
GinEntryAccumulator * entryallocator
Definition: gin_private.h:409
#define DEF_NENTRY
Definition: ginbulk.c:24
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
Definition: rbtree.h:23
void * palloc(Size size)
Definition: mcxt.c:848
void * arg
void ginBeginBAScan ( BuildAccumulator accum)

Definition at line 257 of file ginbulk.c.

References LeftRightWalk, rb_begin_iterate(), BuildAccumulator::tree, and BuildAccumulator::tree_walk.

Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().

258 {
259  rb_begin_iterate(accum->tree, LeftRightWalk, &accum->tree_walk);
260 }
void rb_begin_iterate(RBTree *rb, RBOrderControl ctrl, RBTreeIterator *iter)
Definition: rbtree.c:737
RBTreeIterator tree_walk
Definition: gin_private.h:412
static void ginCombineData ( RBNode existing,
const RBNode newdata,
void *  arg 
)
static

Definition at line 30 of file ginbulk.c.

References BuildAccumulator::allocatedMemory, Assert, GinEntryAccumulator::count, ereport, errcode(), errhint(), errmsg(), ERROR, FALSE, GetMemoryChunkSpace(), ginCompareItemPointers(), GinEntryAccumulator::list, GinEntryAccumulator::maxcount, repalloc_huge(), GinEntryAccumulator::shouldSort, and TRUE.

Referenced by ginInitBA().

31 {
32  GinEntryAccumulator *eo = (GinEntryAccumulator *) existing;
33  const GinEntryAccumulator *en = (const GinEntryAccumulator *) newdata;
35 
36  /*
37  * Note this code assumes that newdata contains only one itempointer.
38  */
39  if (eo->count >= eo->maxcount)
40  {
41  if (eo->maxcount > INT_MAX)
42  ereport(ERROR,
43  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
44  errmsg("posting list is too long"),
45  errhint("Reduce maintenance_work_mem.")));
46 
48  eo->maxcount *= 2;
49  eo->list = (ItemPointerData *)
50  repalloc_huge(eo->list, sizeof(ItemPointerData) * eo->maxcount);
52  }
53 
54  /* If item pointers are not ordered, they will need to be sorted later */
55  if (eo->shouldSort == FALSE)
56  {
57  int res;
58 
59  res = ginCompareItemPointers(eo->list + eo->count - 1, en->list);
60  Assert(res != 0);
61 
62  if (res > 0)
63  eo->shouldSort = TRUE;
64  }
65 
66  eo->list[eo->count] = en->list[0];
67  eo->count++;
68 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
#define ERROR
Definition: elog.h:43
#define FALSE
Definition: c.h:219
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:681
static int ginCompareItemPointers(ItemPointer a, ItemPointer b)
Definition: gin_private.h:461
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1030
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
#define TRUE
Definition: c.h:215
ItemPointerData * list
Definition: gin_private.h:400
ItemPointerData* ginGetBAEntry ( BuildAccumulator accum,
OffsetNumber attnum,
Datum key,
GinNullCategory category,
uint32 n 
)

Definition at line 268 of file ginbulk.c.

References Assert, GinEntryAccumulator::attnum, GinEntryAccumulator::category, GinEntryAccumulator::count, GinEntryAccumulator::key, sort-test::list, GinEntryAccumulator::list, qsort, qsortCompareItemPointers(), rb_iterate(), GinEntryAccumulator::shouldSort, and BuildAccumulator::tree_walk.

Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().

271 {
272  GinEntryAccumulator *entry;
274 
275  entry = (GinEntryAccumulator *) rb_iterate(&accum->tree_walk);
276 
277  if (entry == NULL)
278  return NULL; /* no more entries */
279 
280  *attnum = entry->attnum;
281  *key = entry->key;
282  *category = entry->category;
283  list = entry->list;
284  *n = entry->count;
285 
286  Assert(list != NULL && entry->count > 0);
287 
288  if (entry->shouldSort && entry->count > 1)
289  qsort(list, entry->count, sizeof(ItemPointerData),
291 
292  return list;
293 }
OffsetNumber attnum
Definition: gin_private.h:398
RBNode * rb_iterate(RBTreeIterator *iter)
Definition: rbtree.c:761
GinNullCategory category
Definition: gin_private.h:397
#define Assert(condition)
Definition: c.h:681
static int qsortCompareItemPointers(const void *a, const void *b)
Definition: ginbulk.c:246
tuple list
Definition: sort-test.py:11
RBTreeIterator tree_walk
Definition: gin_private.h:412
#define qsort(a, b, c, d)
Definition: port.h:447
ItemPointerData * list
Definition: gin_private.h:400
void ginInitBA ( BuildAccumulator accum)

Definition at line 109 of file ginbulk.c.

References BuildAccumulator::allocatedMemory, cmpEntryAccumulator(), BuildAccumulator::eas_used, BuildAccumulator::entryallocator, ginAllocEntryAccumulator(), ginCombineData(), rb_create(), and BuildAccumulator::tree.

Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().

110 {
111  /* accum->ginstate is intentionally not set here */
112  accum->allocatedMemory = 0;
113  accum->entryallocator = NULL;
114  accum->eas_used = 0;
115  accum->tree = rb_create(sizeof(GinEntryAccumulator),
119  NULL, /* no freefunc needed */
120  (void *) accum);
121 }
GinEntryAccumulator * entryallocator
Definition: gin_private.h:409
static void ginCombineData(RBNode *existing, const RBNode *newdata, void *arg)
Definition: ginbulk.c:30
RBTree * rb_create(Size node_size, rb_comparator comparator, rb_combiner combiner, rb_allocfunc allocfunc, rb_freefunc freefunc, void *arg)
Definition: rbtree.c:99
static int cmpEntryAccumulator(const RBNode *a, const RBNode *b, void *arg)
Definition: ginbulk.c:72
static RBNode * ginAllocEntryAccumulator(void *arg)
Definition: ginbulk.c:85
void ginInsertBAEntries ( BuildAccumulator accum,
ItemPointer  heapptr,
OffsetNumber  attnum,
Datum entries,
GinNullCategory categories,
int32  nentries 
)

Definition at line 210 of file ginbulk.c.

References Assert, FirstOffsetNumber, ginInsertBAEntry(), i, and ItemPointerIsValid.

Referenced by ginHeapTupleBulkInsert(), and processPendingPage().

214 {
215  uint32 step = nentries;
216 
217  if (nentries <= 0)
218  return;
219 
220  Assert(ItemPointerIsValid(heapptr) && attnum >= FirstOffsetNumber);
221 
222  /*
223  * step will contain largest power of 2 and <= nentries
224  */
225  step |= (step >> 1);
226  step |= (step >> 2);
227  step |= (step >> 4);
228  step |= (step >> 8);
229  step |= (step >> 16);
230  step >>= 1;
231  step++;
232 
233  while (step > 0)
234  {
235  int i;
236 
237  for (i = step - 1; i < nentries && i >= 0; i += step << 1 /* *2 */ )
238  ginInsertBAEntry(accum, heapptr, attnum,
239  entries[i], categories[i]);
240 
241  step >>= 1; /* /2 */
242  }
243 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
static void ginInsertBAEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum key, GinNullCategory category)
Definition: ginbulk.c:148
#define FirstOffsetNumber
Definition: off.h:27
unsigned int uint32
Definition: c.h:258
#define Assert(condition)
Definition: c.h:681
int i
static void ginInsertBAEntry ( BuildAccumulator accum,
ItemPointer  heapptr,
OffsetNumber  attnum,
Datum  key,
GinNullCategory  category 
)
static

Definition at line 148 of file ginbulk.c.

References BuildAccumulator::allocatedMemory, GinEntryAccumulator::attnum, GinEntryAccumulator::category, GinEntryAccumulator::count, DEF_NPTR, FALSE, getDatumCopy(), GetMemoryChunkSpace(), GIN_CAT_NORM_KEY, GinEntryAccumulator::key, GinEntryAccumulator::list, GinEntryAccumulator::maxcount, palloc(), rb_insert(), GinEntryAccumulator::shouldSort, and BuildAccumulator::tree.

Referenced by ginInsertBAEntries().

151 {
152  GinEntryAccumulator eatmp;
154  bool isNew;
155 
156  /*
157  * For the moment, fill only the fields of eatmp that will be looked at by
158  * cmpEntryAccumulator or ginCombineData.
159  */
160  eatmp.attnum = attnum;
161  eatmp.key = key;
162  eatmp.category = category;
163  /* temporarily set up single-entry itempointer list */
164  eatmp.list = heapptr;
165 
166  ea = (GinEntryAccumulator *) rb_insert(accum->tree, (RBNode *) &eatmp,
167  &isNew);
168 
169  if (isNew)
170  {
171  /*
172  * Finish initializing new tree entry, including making permanent
173  * copies of the datum (if it's not null) and itempointer.
174  */
175  if (category == GIN_CAT_NORM_KEY)
176  ea->key = getDatumCopy(accum, attnum, key);
177  ea->maxcount = DEF_NPTR;
178  ea->count = 1;
179  ea->shouldSort = FALSE;
180  ea->list =
182  ea->list[0] = *heapptr;
184  }
185  else
186  {
187  /*
188  * ginCombineData did everything needed.
189  */
190  }
191 }
RBNode * rb_insert(RBTree *rb, const RBNode *data, bool *isNew)
Definition: rbtree.c:388
OffsetNumber attnum
Definition: gin_private.h:398
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
GinNullCategory category
Definition: gin_private.h:397
#define FALSE
Definition: c.h:219
Definition: rbtree.h:23
#define GIN_CAT_NORM_KEY
Definition: ginblock.h:199
static Datum getDatumCopy(BuildAccumulator *accum, OffsetNumber attnum, Datum value)
Definition: ginbulk.c:128
#define DEF_NPTR
Definition: ginbulk.c:25
void * palloc(Size size)
Definition: mcxt.c:848
ItemPointerData * list
Definition: gin_private.h:400
static int qsortCompareItemPointers ( const void *  a,
const void *  b 
)
static

Definition at line 246 of file ginbulk.c.

References Assert, and ginCompareItemPointers().

Referenced by ginGetBAEntry().

247 {
248  int res = ginCompareItemPointers((ItemPointer) a, (ItemPointer) b);
249 
250  /* Assert that there are no equal item pointers being sorted */
251  Assert(res != 0);
252  return res;
253 }
#define Assert(condition)
Definition: c.h:681
static int ginCompareItemPointers(ItemPointer a, ItemPointer b)
Definition: gin_private.h:461