PostgreSQL Source Code  git master
test_tidstore.c File Reference
#include "postgres.h"
#include "access/tidstore.h"
#include "fmgr.h"
#include "funcapi.h"
#include "storage/block.h"
#include "storage/itemptr.h"
#include "storage/lwlock.h"
#include "utils/array.h"
#include "utils/memutils.h"
Include dependency graph for test_tidstore.c:

Go to the source code of this file.

Data Structures

struct  ItemArray
 

Typedefs

typedef struct ItemArray ItemArray
 

Functions

 PG_FUNCTION_INFO_V1 (test_create)
 
 PG_FUNCTION_INFO_V1 (do_set_block_offsets)
 
 PG_FUNCTION_INFO_V1 (check_set_block_offsets)
 
 PG_FUNCTION_INFO_V1 (test_is_full)
 
 PG_FUNCTION_INFO_V1 (test_destroy)
 
static int itemptr_cmp (const void *left, const void *right)
 
Datum test_create (PG_FUNCTION_ARGS)
 
static void sanity_check_array (ArrayType *ta)
 
static void purge_from_verification_array (BlockNumber blkno)
 
Datum do_set_block_offsets (PG_FUNCTION_ARGS)
 
Datum check_set_block_offsets (PG_FUNCTION_ARGS)
 
Datum test_is_full (PG_FUNCTION_ARGS)
 
Datum test_destroy (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 
static TidStoretidstore = NULL
 
static size_t tidstore_empty_size
 
static ItemArray items
 

Typedef Documentation

◆ ItemArray

typedef struct ItemArray ItemArray

Function Documentation

◆ check_set_block_offsets()

Datum check_set_block_offsets ( PG_FUNCTION_ARGS  )

Definition at line 212 of file test_tidstore.c.

213 {
214  TidStoreIter *iter;
215  TidStoreIterResult *iter_result;
216  int num_iter_tids = 0;
217  int num_lookup_tids = 0;
218  BlockNumber prevblkno = 0;
219 
220  /* lookup each member in the verification array */
221  for (int i = 0; i < items.num_tids; i++)
223  elog(ERROR, "missing TID with block %u, offset %u",
226 
227  /*
228  * Lookup all possible TIDs for each distinct block in the verification
229  * array and save successful lookups in the lookup array.
230  */
231 
232  for (int i = 0; i < items.num_tids; i++)
233  {
235 
236  if (i > 0 && blkno == prevblkno)
237  continue;
238 
239  for (OffsetNumber offset = FirstOffsetNumber; offset < MaxOffsetNumber; offset++)
240  {
241  ItemPointerData tid;
242 
243  ItemPointerSet(&tid, blkno, offset);
244 
246  if (TidStoreIsMember(tidstore, &tid))
247  ItemPointerSet(&items.lookup_tids[num_lookup_tids++], blkno, offset);
249  }
250 
251  prevblkno = blkno;
252  }
253 
254  /* Collect TIDs stored in the tidstore, in order */
255 
258  while ((iter_result = TidStoreIterateNext(iter)) != NULL)
259  {
260  for (int i = 0; i < iter_result->num_offsets; i++)
261  ItemPointerSet(&(items.iter_tids[num_iter_tids++]), iter_result->blkno,
262  iter_result->offsets[i]);
263  }
264  TidStoreEndIterate(iter);
266 
267  /*
268  * Sort verification and lookup arrays and test that all arrays are the
269  * same.
270  */
271 
272  if (num_lookup_tids != items.num_tids)
273  elog(ERROR, "should have %d TIDs, have %d", items.num_tids, num_lookup_tids);
274  if (num_iter_tids != items.num_tids)
275  elog(ERROR, "should have %d TIDs, have %d", items.num_tids, num_iter_tids);
276 
279  for (int i = 0; i < items.num_tids; i++)
280  {
281  if (itemptr_cmp((const void *) &items.insert_tids[i], (const void *) &items.iter_tids[i]) != 0)
282  elog(ERROR, "TID iter array doesn't match verification array, got (%u,%u) expected (%u,%u)",
287  if (itemptr_cmp((const void *) &items.insert_tids[i], (const void *) &items.lookup_tids[i]) != 0)
288  elog(ERROR, "TID lookup array doesn't match verification array, got (%u,%u) expected (%u,%u)",
293  }
294 
295  PG_RETURN_VOID();
296 }
uint32 BlockNumber
Definition: block.h:31
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define PG_RETURN_VOID()
Definition: fmgr.h:349
int i
Definition: isn.c:73
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition: itemptr.h:135
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define MaxOffsetNumber
Definition: off.h:28
#define qsort(a, b, c, d)
Definition: port.h:449
ItemPointerData * insert_tids
Definition: test_tidstore.c:42
ItemPointerData * lookup_tids
Definition: test_tidstore.c:43
ItemPointerData * iter_tids
Definition: test_tidstore.c:44
BlockNumber blkno
Definition: tidstore.h:26
OffsetNumber * offsets
Definition: tidstore.h:29
static int itemptr_cmp(const void *left, const void *right)
Definition: test_tidstore.c:53
static TidStore * tidstore
Definition: test_tidstore.c:36
static ItemArray items
Definition: test_tidstore.c:49
void TidStoreEndIterate(TidStoreIter *iter)
Definition: tidstore.c:536
TidStoreIterResult * TidStoreIterateNext(TidStoreIter *iter)
Definition: tidstore.c:511
void TidStoreLockShare(TidStore *ts)
Definition: tidstore.c:305
void TidStoreUnlock(TidStore *ts)
Definition: tidstore.c:312
bool TidStoreIsMember(TidStore *ts, ItemPointer tid)
Definition: tidstore.c:432
TidStoreIter * TidStoreBeginIterate(TidStore *ts)
Definition: tidstore.c:482

References TidStoreIterResult::blkno, elog, ERROR, FirstOffsetNumber, i, ItemArray::insert_tids, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), ItemPointerSet(), itemptr_cmp(), items, ItemArray::iter_tids, ItemArray::lookup_tids, MaxOffsetNumber, TidStoreIterResult::num_offsets, ItemArray::num_tids, TidStoreIterResult::offsets, PG_RETURN_VOID, qsort, tidstore, TidStoreBeginIterate(), TidStoreEndIterate(), TidStoreIsMember(), TidStoreIterateNext(), TidStoreLockShare(), and TidStoreUnlock().

◆ do_set_block_offsets()

Datum do_set_block_offsets ( PG_FUNCTION_ARGS  )

Definition at line 163 of file test_tidstore.c.

164 {
165  BlockNumber blkno = PG_GETARG_INT64(0);
167  OffsetNumber *offs;
168  int noffs;
169 
170  sanity_check_array(ta);
171 
172  noffs = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
173  offs = ((OffsetNumber *) ARR_DATA_PTR(ta));
174 
175  /* Set TIDs in the store */
177  TidStoreSetBlockOffsets(tidstore, blkno, offs, noffs);
179 
180  /* Remove the existing items of blkno from the verification array */
182 
183  /* Set TIDs in verification array */
184  for (int i = 0; i < noffs; i++)
185  {
186  ItemPointer tid;
187  int idx = items.num_tids + i;
188 
189  /* Enlarge the TID arrays if necessary */
190  if (idx >= items.max_tids)
191  {
192  items.max_tids *= 2;
196  }
197 
198  tid = &(items.insert_tids[idx]);
199  ItemPointerSet(tid, blkno, offs[i]);
200  }
201 
202  /* Update statistics */
203  items.num_tids += noffs;
204 
205  PG_RETURN_INT64(blkno);
206 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:264
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define ARR_DIMS(a)
Definition: array.h:294
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
static void sanity_check_array(ArrayType *ta)
static void purge_from_verification_array(BlockNumber blkno)
void TidStoreLockExclusive(TidStore *ts)
Definition: tidstore.c:298
void TidStoreSetBlockOffsets(TidStore *ts, BlockNumber blkno, OffsetNumber *offsets, int num_offsets)
Definition: tidstore.c:356

References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), i, idx(), ItemArray::insert_tids, ItemPointerSet(), items, ItemArray::iter_tids, ItemArray::lookup_tids, ItemArray::max_tids, ItemArray::num_tids, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT64, PG_RETURN_INT64, purge_from_verification_array(), repalloc(), sanity_check_array(), tidstore, TidStoreLockExclusive(), TidStoreSetBlockOffsets(), and TidStoreUnlock().

◆ itemptr_cmp()

static int itemptr_cmp ( const void *  left,
const void *  right 
)
static

Definition at line 53 of file test_tidstore.c.

54 {
55  BlockNumber lblk,
56  rblk;
57  OffsetNumber loff,
58  roff;
59 
61  rblk = ItemPointerGetBlockNumber((ItemPointer) right);
62 
63  if (lblk < rblk)
64  return -1;
65  if (lblk > rblk)
66  return 1;
67 
70 
71  if (loff < roff)
72  return -1;
73  if (loff > roff)
74  return 1;
75 
76  return 0;
77 }

References ItemPointerGetBlockNumber(), and ItemPointerGetOffsetNumber().

Referenced by check_set_block_offsets().

◆ PG_FUNCTION_INFO_V1() [1/5]

PG_FUNCTION_INFO_V1 ( check_set_block_offsets  )

◆ PG_FUNCTION_INFO_V1() [2/5]

PG_FUNCTION_INFO_V1 ( do_set_block_offsets  )

◆ PG_FUNCTION_INFO_V1() [3/5]

PG_FUNCTION_INFO_V1 ( test_create  )

◆ PG_FUNCTION_INFO_V1() [4/5]

PG_FUNCTION_INFO_V1 ( test_destroy  )

◆ PG_FUNCTION_INFO_V1() [5/5]

PG_FUNCTION_INFO_V1 ( test_is_full  )

◆ purge_from_verification_array()

static void purge_from_verification_array ( BlockNumber  blkno)
static

Definition at line 150 of file test_tidstore.c.

151 {
152  int dst = 0;
153 
154  for (int src = 0; src < items.num_tids; src++)
155  if (ItemPointerGetBlockNumber(&items.insert_tids[src]) != blkno)
156  items.insert_tids[dst++] = items.insert_tids[src];
157  items.num_tids = dst;
158 }

References ItemArray::insert_tids, ItemPointerGetBlockNumber(), items, and ItemArray::num_tids.

Referenced by do_set_block_offsets().

◆ sanity_check_array()

static void sanity_check_array ( ArrayType ta)
static

Definition at line 136 of file test_tidstore.c.

137 {
138  if (ARR_HASNULL(ta) && array_contains_nulls(ta))
139  ereport(ERROR,
140  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
141  errmsg("array must not contain nulls")));
142 
143  if (ARR_NDIM(ta) > 1)
144  ereport(ERROR,
145  (errcode(ERRCODE_DATA_EXCEPTION),
146  errmsg("argument must be empty or one-dimensional array")));
147 }
#define ARR_HASNULL(a)
Definition: array.h:291
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3748
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereport(elevel,...)
Definition: elog.h:149

References ARR_HASNULL, ARR_NDIM, array_contains_nulls(), ereport, errcode(), errmsg(), and ERROR.

Referenced by do_set_block_offsets().

◆ test_create()

Datum test_create ( PG_FUNCTION_ARGS  )

Definition at line 86 of file test_tidstore.c.

87 {
88  bool shared = PG_GETARG_BOOL(0);
90 
91  /* doesn't really matter, since it's just a hint */
92  size_t tidstore_max_size = 2 * 1024 * 1024;
93  size_t array_init_size = 1024;
94 
95  Assert(tidstore == NULL);
96 
97  /*
98  * Create the TidStore on TopMemoryContext so that the same process use it
99  * for subsequent tests.
100  */
102 
103  if (shared)
104  {
105  int tranche_id;
106 
107  tranche_id = LWLockNewTrancheId();
108  LWLockRegisterTranche(tranche_id, "test_tidstore");
109 
110  tidstore = TidStoreCreateShared(tidstore_max_size, tranche_id);
111 
112  /*
113  * Remain attached until end of backend or explicitly detached so that
114  * the same process use the tidstore for subsequent tests.
115  */
117  }
118  else
119  /* VACUUM uses insert only, so we test the other option. */
120  tidstore = TidStoreCreateLocal(tidstore_max_size, false);
121 
123 
124  items.num_tids = 0;
125  items.max_tids = array_init_size / sizeof(ItemPointerData);
126  items.insert_tids = (ItemPointerData *) palloc0(array_init_size);
127  items.lookup_tids = (ItemPointerData *) palloc0(array_init_size);
128  items.iter_tids = (ItemPointerData *) palloc0(array_init_size);
129 
131 
132  PG_RETURN_VOID();
133 }
#define Assert(condition)
Definition: c.h:858
void dsa_pin_mapping(dsa_area *area)
Definition: dsa.c:635
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
struct ItemPointerData ItemPointerData
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
Definition: lwlock.c:630
int LWLockNewTrancheId(void)
Definition: lwlock.c:606
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * palloc0(Size size)
Definition: mcxt.c:1346
RT_SCOPE RT_RADIX_TREE *MemoryContext old_ctx
Definition: radixtree.h:1822
MemoryContextSwitchTo(old_ctx)
static size_t tidstore_empty_size
Definition: test_tidstore.c:37
TidStore * TidStoreCreateShared(size_t max_bytes, int tranche_id)
Definition: tidstore.c:213
dsa_area * TidStoreGetDSA(TidStore *ts)
Definition: tidstore.c:563
TidStore * TidStoreCreateLocal(size_t max_bytes, bool insert_only)
Definition: tidstore.c:165
size_t TidStoreMemoryUsage(TidStore *ts)
Definition: tidstore.c:551

References Assert, dsa_pin_mapping(), ItemArray::insert_tids, items, ItemArray::iter_tids, ItemArray::lookup_tids, LWLockNewTrancheId(), LWLockRegisterTranche(), ItemArray::max_tids, MemoryContextSwitchTo(), ItemArray::num_tids, old_ctx, palloc0(), PG_GETARG_BOOL, PG_RETURN_VOID, tidstore, tidstore_empty_size, TidStoreCreateLocal(), TidStoreCreateShared(), TidStoreGetDSA(), TidStoreMemoryUsage(), and TopMemoryContext.

◆ test_destroy()

Datum test_destroy ( PG_FUNCTION_ARGS  )

Definition at line 315 of file test_tidstore.c.

316 {
318  tidstore = NULL;
319  items.num_tids = 0;
323 
324  PG_RETURN_VOID();
325 }
void pfree(void *pointer)
Definition: mcxt.c:1520
void TidStoreDestroy(TidStore *ts)
Definition: tidstore.c:328

References ItemArray::insert_tids, items, ItemArray::iter_tids, ItemArray::lookup_tids, ItemArray::num_tids, pfree(), PG_RETURN_VOID, tidstore, and TidStoreDestroy().

◆ test_is_full()

Datum test_is_full ( PG_FUNCTION_ARGS  )

Definition at line 304 of file test_tidstore.c.

305 {
306  bool is_full;
307 
309 
310  PG_RETURN_BOOL(is_full);
311 }
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

References PG_RETURN_BOOL, tidstore, tidstore_empty_size, and TidStoreMemoryUsage().

Variable Documentation

◆ items

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 28 of file test_tidstore.c.

◆ tidstore

TidStore* tidstore = NULL
static

◆ tidstore_empty_size

size_t tidstore_empty_size
static

Definition at line 37 of file test_tidstore.c.

Referenced by test_create(), and test_is_full().