PostgreSQL Source Code  git master
combocid.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "miscadmin.h"
#include "storage/shmem.h"
#include "utils/combocid.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
Include dependency graph for combocid.c:

Go to the source code of this file.

Data Structures

struct  ComboCidKeyData
 
struct  ComboCidEntryData
 

Macros

#define CCID_HASH_SIZE   100
 
#define CCID_ARRAY_SIZE   100
 

Typedefs

typedef ComboCidKeyDataComboCidKey
 
typedef ComboCidEntryDataComboCidEntry
 

Functions

static CommandId GetComboCommandId (CommandId cmin, CommandId cmax)
 
static CommandId GetRealCmin (CommandId combocid)
 
static CommandId GetRealCmax (CommandId combocid)
 
CommandId HeapTupleHeaderGetCmin (HeapTupleHeader tup)
 
CommandId HeapTupleHeaderGetCmax (HeapTupleHeader tup)
 
void HeapTupleHeaderAdjustCmax (HeapTupleHeader tup, CommandId *cmax, bool *iscombo)
 
void AtEOXact_ComboCid (void)
 
Size EstimateComboCIDStateSpace (void)
 
void SerializeComboCIDState (Size maxsize, char *start_address)
 
void RestoreComboCIDState (char *comboCIDstate)
 

Variables

static HTABcomboHash = NULL
 
static ComboCidKey comboCids = NULL
 
static int usedComboCids = 0
 
static int sizeComboCids = 0
 

Macro Definition Documentation

◆ CCID_ARRAY_SIZE

#define CCID_ARRAY_SIZE   100

Definition at line 85 of file combocid.c.

Referenced by GetComboCommandId().

◆ CCID_HASH_SIZE

#define CCID_HASH_SIZE   100

Definition at line 73 of file combocid.c.

Referenced by GetComboCommandId().

Typedef Documentation

◆ ComboCidEntry

Definition at line 70 of file combocid.c.

◆ ComboCidKey

Definition at line 62 of file combocid.c.

Function Documentation

◆ AtEOXact_ComboCid()

void AtEOXact_ComboCid ( void  )

Definition at line 182 of file combocid.c.

References sizeComboCids, and usedComboCids.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

183 {
184  /*
185  * Don't bother to pfree. These are allocated in TopTransactionContext, so
186  * they're going to go away at the end of transaction anyway.
187  */
188  comboHash = NULL;
189 
190  comboCids = NULL;
191  usedComboCids = 0;
192  sizeComboCids = 0;
193 }
static int usedComboCids
Definition: combocid.c:81
static ComboCidKey comboCids
Definition: combocid.c:80
static HTAB * comboHash
Definition: combocid.c:53
static int sizeComboCids
Definition: combocid.c:82

◆ EstimateComboCIDStateSpace()

Size EstimateComboCIDStateSpace ( void  )

Definition at line 298 of file combocid.c.

References add_size(), mul_size(), and usedComboCids.

Referenced by InitializeParallelDSM().

299 {
300  Size size;
301 
302  /* Add space required for saving usedComboCids */
303  size = sizeof(int);
304 
305  /* Add space required for saving the combocids key */
306  size = add_size(size, mul_size(sizeof(ComboCidKeyData), usedComboCids));
307 
308  return size;
309 }
static int usedComboCids
Definition: combocid.c:81
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:467

◆ GetComboCommandId()

static CommandId GetComboCommandId ( CommandId  cmin,
CommandId  cmax 
)
static

Definition at line 204 of file combocid.c.

References CCID_ARRAY_SIZE, CCID_HASH_SIZE, ComboCidKeyData::cmax, ComboCidKeyData::cmin, ComboCidEntryData::combocid, HASHCTL::entrysize, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::hcxt, sort-test::key, HASHCTL::keysize, MemoryContextAlloc(), repalloc(), sizeComboCids, TopTransactionContext, and usedComboCids.

Referenced by HeapTupleHeaderAdjustCmax(), and RestoreComboCIDState().

205 {
206  CommandId combocid;
208  ComboCidEntry entry;
209  bool found;
210 
211  /*
212  * Create the hash table and array the first time we need to use combo
213  * cids in the transaction.
214  */
215  if (comboHash == NULL)
216  {
217  HASHCTL hash_ctl;
218 
219  /* Make array first; existence of hash table asserts array exists */
222  sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE);
224  usedComboCids = 0;
225 
226  memset(&hash_ctl, 0, sizeof(hash_ctl));
227  hash_ctl.keysize = sizeof(ComboCidKeyData);
228  hash_ctl.entrysize = sizeof(ComboCidEntryData);
229  hash_ctl.hcxt = TopTransactionContext;
230 
231  comboHash = hash_create("Combo CIDs",
233  &hash_ctl,
235  }
236 
237  /*
238  * Grow the array if there's not at least one free slot. We must do this
239  * before possibly entering a new hashtable entry, else failure to
240  * repalloc would leave a corrupt hashtable entry behind.
241  */
243  {
244  int newsize = sizeComboCids * 2;
245 
247  repalloc(comboCids, sizeof(ComboCidKeyData) * newsize);
248  sizeComboCids = newsize;
249  }
250 
251  /* Lookup or create a hash entry with the desired cmin/cmax */
252 
253  /* We assume there is no struct padding in ComboCidKeyData! */
254  key.cmin = cmin;
255  key.cmax = cmax;
257  (void *) &key,
258  HASH_ENTER,
259  &found);
260 
261  if (found)
262  {
263  /* Reuse an existing combo cid */
264  return entry->combocid;
265  }
266 
267  /* We have to create a new combo cid; we already made room in the array */
268  combocid = usedComboCids;
269 
270  comboCids[combocid].cmin = cmin;
271  comboCids[combocid].cmax = cmax;
272  usedComboCids++;
273 
274  entry->combocid = combocid;
275 
276  return combocid;
277 }
uint32 CommandId
Definition: c.h:528
MemoryContext TopTransactionContext
Definition: mcxt.c:49
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
#define CCID_ARRAY_SIZE
Definition: combocid.c:85
Size entrysize
Definition: hsearch.h:73
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static int usedComboCids
Definition: combocid.c:81
static ComboCidKey comboCids
Definition: combocid.c:80
static HTAB * comboHash
Definition: combocid.c:53
#define HASH_BLOBS
Definition: hsearch.h:88
CommandId cmin
Definition: combocid.c:58
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
static int sizeComboCids
Definition: combocid.c:82
CommandId cmax
Definition: combocid.c:59
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
#define CCID_HASH_SIZE
Definition: combocid.c:73
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
CommandId combocid
Definition: combocid.c:67
ComboCidEntryData * ComboCidEntry
Definition: combocid.c:70

◆ GetRealCmax()

static CommandId GetRealCmax ( CommandId  combocid)
static

Definition at line 287 of file combocid.c.

References Assert, ComboCidKeyData::cmax, and usedComboCids.

Referenced by HeapTupleHeaderGetCmax().

288 {
289  Assert(combocid < usedComboCids);
290  return comboCids[combocid].cmax;
291 }
static int usedComboCids
Definition: combocid.c:81
static ComboCidKey comboCids
Definition: combocid.c:80
CommandId cmax
Definition: combocid.c:59
#define Assert(condition)
Definition: c.h:739

◆ GetRealCmin()

static CommandId GetRealCmin ( CommandId  combocid)
static

Definition at line 280 of file combocid.c.

References Assert, ComboCidKeyData::cmin, and usedComboCids.

Referenced by HeapTupleHeaderGetCmin().

281 {
282  Assert(combocid < usedComboCids);
283  return comboCids[combocid].cmin;
284 }
static int usedComboCids
Definition: combocid.c:81
static ComboCidKey comboCids
Definition: combocid.c:80
CommandId cmin
Definition: combocid.c:58
#define Assert(condition)
Definition: c.h:739

◆ HeapTupleHeaderAdjustCmax()

void HeapTupleHeaderAdjustCmax ( HeapTupleHeader  tup,
CommandId cmax,
bool iscombo 
)

Definition at line 153 of file combocid.c.

References GetComboCommandId(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmin, HeapTupleHeaderXminCommitted, and TransactionIdIsCurrentTransactionId().

Referenced by heap_delete(), and heap_update().

156 {
157  /*
158  * If we're marking a tuple deleted that was inserted by (any
159  * subtransaction of) our transaction, we need to use a combo command id.
160  * Test for HeapTupleHeaderXminCommitted() first, because it's cheaper
161  * than a TransactionIdIsCurrentTransactionId call.
162  */
163  if (!HeapTupleHeaderXminCommitted(tup) &&
165  {
166  CommandId cmin = HeapTupleHeaderGetCmin(tup);
167 
168  *cmax = GetComboCommandId(cmin, *cmax);
169  *iscombo = true;
170  }
171  else
172  {
173  *iscombo = false;
174  }
175 }
uint32 CommandId
Definition: c.h:528
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:104
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
static CommandId GetComboCommandId(CommandId cmin, CommandId cmax)
Definition: combocid.c:204
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308

◆ HeapTupleHeaderGetCmax()

CommandId HeapTupleHeaderGetCmax ( HeapTupleHeader  tup)

Definition at line 118 of file combocid.c.

References Assert, CritSectionCount, GetRealCmax(), HEAP_COMBOCID, HEAP_MOVED, HeapTupleHeaderGetRawCommandId, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderData::t_infomask, and TransactionIdIsCurrentTransactionId().

Referenced by heap_delete(), heap_lock_tuple(), heap_update(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesUpdate(), and log_heap_new_cid().

119 {
121 
122  Assert(!(tup->t_infomask & HEAP_MOVED));
123 
124  /*
125  * Because GetUpdateXid() performs memory allocations if xmax is a
126  * multixact we can't Assert() if we're inside a critical section. This
127  * weakens the check, but not using GetCmax() inside one would complicate
128  * things too much.
129  */
130  Assert(CritSectionCount > 0 ||
132 
133  if (tup->t_infomask & HEAP_COMBOCID)
134  return GetRealCmax(cid);
135  else
136  return cid;
137 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:365
uint32 CommandId
Definition: c.h:528
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
volatile uint32 CritSectionCount
Definition: globals.c:38
static CommandId GetRealCmax(CommandId combocid)
Definition: combocid.c:287
#define HEAP_MOVED
Definition: htup_details.h:216
#define HEAP_COMBOCID
Definition: htup_details.h:194
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:391

◆ HeapTupleHeaderGetCmin()

CommandId HeapTupleHeaderGetCmin ( HeapTupleHeader  tup)

Definition at line 104 of file combocid.c.

References Assert, GetRealCmin(), HEAP_COMBOCID, HEAP_MOVED, HeapTupleHeaderGetRawCommandId, HeapTupleHeaderGetXmin, HeapTupleHeaderData::t_infomask, and TransactionIdIsCurrentTransactionId().

Referenced by heapam_tuple_lock(), HeapTupleHeaderAdjustCmax(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesUpdate(), and log_heap_new_cid().

105 {
107 
108  Assert(!(tup->t_infomask & HEAP_MOVED));
110 
111  if (tup->t_infomask & HEAP_COMBOCID)
112  return GetRealCmin(cid);
113  else
114  return cid;
115 }
uint32 CommandId
Definition: c.h:528
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
static CommandId GetRealCmin(CommandId combocid)
Definition: combocid.c:280
#define HEAP_MOVED
Definition: htup_details.h:216
#define HEAP_COMBOCID
Definition: htup_details.h:194
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:391

◆ RestoreComboCIDState()

void RestoreComboCIDState ( char *  comboCIDstate)

Definition at line 343 of file combocid.c.

References Assert, elog, ERROR, GetComboCommandId(), and i.

Referenced by ParallelWorkerMain().

344 {
345  int num_elements;
346  ComboCidKeyData *keydata;
347  int i;
348  CommandId cid;
349 
350  Assert(!comboCids && !comboHash);
351 
352  /* First, we retrieve the number of ComboCIDs that were serialized. */
353  num_elements = *(int *) comboCIDstate;
354  keydata = (ComboCidKeyData *) (comboCIDstate + sizeof(int));
355 
356  /* Use GetComboCommandId to restore each ComboCID. */
357  for (i = 0; i < num_elements; i++)
358  {
359  cid = GetComboCommandId(keydata[i].cmin, keydata[i].cmax);
360 
361  /* Verify that we got the expected answer. */
362  if (cid != i)
363  elog(ERROR, "unexpected command ID while restoring combo CIDs");
364  }
365 }
uint32 CommandId
Definition: c.h:528
static ComboCidKey comboCids
Definition: combocid.c:80
#define ERROR
Definition: elog.h:43
static CommandId GetComboCommandId(CommandId cmin, CommandId cmax)
Definition: combocid.c:204
static HTAB * comboHash
Definition: combocid.c:53
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228
int i

◆ SerializeComboCIDState()

void SerializeComboCIDState ( Size  maxsize,
char *  start_address 
)

Definition at line 317 of file combocid.c.

References elog, ERROR, and usedComboCids.

Referenced by InitializeParallelDSM().

318 {
319  char *endptr;
320 
321  /* First, we store the number of currently-existing ComboCIDs. */
322  *(int *) start_address = usedComboCids;
323 
324  /* If maxsize is too small, throw an error. */
325  endptr = start_address + sizeof(int) +
326  (sizeof(ComboCidKeyData) * usedComboCids);
327  if (endptr < start_address || endptr > start_address + maxsize)
328  elog(ERROR, "not enough space to serialize ComboCID state");
329 
330  /* Now, copy the actual cmin/cmax pairs. */
331  if (usedComboCids > 0)
332  memcpy(start_address + sizeof(int), comboCids,
333  (sizeof(ComboCidKeyData) * usedComboCids));
334 }
static int usedComboCids
Definition: combocid.c:81
static ComboCidKey comboCids
Definition: combocid.c:80
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:228

Variable Documentation

◆ comboCids

ComboCidKey comboCids = NULL
static

Definition at line 80 of file combocid.c.

◆ comboHash

HTAB* comboHash = NULL
static

Definition at line 53 of file combocid.c.

◆ sizeComboCids

int sizeComboCids = 0
static

Definition at line 82 of file combocid.c.

Referenced by AtEOXact_ComboCid(), and GetComboCommandId().

◆ usedComboCids

int usedComboCids = 0
static