PostgreSQL Source Code  git master
reorderbuffer.h File Reference
#include "access/htup_details.h"
#include "lib/ilist.h"
#include "storage/sinval.h"
#include "utils/hsearch.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
#include "utils/timestamp.h"
Include dependency graph for reorderbuffer.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ReorderBufferTupleBuf
 
struct  ReorderBufferChange
 
struct  ReorderBufferTXN
 
struct  ReorderBuffer
 

Macros

#define ReorderBufferTupleBufData(p)   ((HeapTupleHeader) MAXALIGN(((char *) p) + sizeof(ReorderBufferTupleBuf)))
 

Typedefs

typedef struct ReorderBufferTupleBuf ReorderBufferTupleBuf
 
typedef struct ReorderBufferChange ReorderBufferChange
 
typedef struct ReorderBufferTXN ReorderBufferTXN
 
typedef struct ReorderBuffer ReorderBuffer
 
typedef void(* ReorderBufferApplyChangeCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)
 
typedef void(* ReorderBufferApplyTruncateCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)
 
typedef void(* ReorderBufferBeginCB) (ReorderBuffer *rb, ReorderBufferTXN *txn)
 
typedef void(* ReorderBufferCommitCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
 
typedef void(* ReorderBufferMessageCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)
 

Enumerations

enum  ReorderBufferChangeType {
  REORDER_BUFFER_CHANGE_INSERT, REORDER_BUFFER_CHANGE_UPDATE, REORDER_BUFFER_CHANGE_DELETE, REORDER_BUFFER_CHANGE_MESSAGE,
  REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT, REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID, REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID, REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT,
  REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM, REORDER_BUFFER_CHANGE_TRUNCATE
}
 

Functions

ReorderBufferReorderBufferAllocate (void)
 
void ReorderBufferFree (ReorderBuffer *)
 
ReorderBufferTupleBufReorderBufferGetTupleBuf (ReorderBuffer *, Size tuple_len)
 
void ReorderBufferReturnTupleBuf (ReorderBuffer *, ReorderBufferTupleBuf *tuple)
 
ReorderBufferChangeReorderBufferGetChange (ReorderBuffer *)
 
void ReorderBufferReturnChange (ReorderBuffer *, ReorderBufferChange *)
 
OidReorderBufferGetRelids (ReorderBuffer *, int nrelids)
 
void ReorderBufferReturnRelids (ReorderBuffer *, Oid *relids)
 
void ReorderBufferQueueChange (ReorderBuffer *, TransactionId, XLogRecPtr lsn, ReorderBufferChange *)
 
void ReorderBufferQueueMessage (ReorderBuffer *, TransactionId, Snapshot snapshot, XLogRecPtr lsn, bool transactional, const char *prefix, Size message_size, const char *message)
 
void ReorderBufferCommit (ReorderBuffer *, TransactionId, XLogRecPtr commit_lsn, XLogRecPtr end_lsn, TimestampTz commit_time, RepOriginId origin_id, XLogRecPtr origin_lsn)
 
void ReorderBufferAssignChild (ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn)
 
void ReorderBufferCommitChild (ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn, XLogRecPtr end_lsn)
 
void ReorderBufferAbort (ReorderBuffer *, TransactionId, XLogRecPtr lsn)
 
void ReorderBufferAbortOld (ReorderBuffer *, TransactionId xid)
 
void ReorderBufferForget (ReorderBuffer *, TransactionId, XLogRecPtr lsn)
 
void ReorderBufferSetBaseSnapshot (ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap)
 
void ReorderBufferAddSnapshot (ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap)
 
void ReorderBufferAddNewCommandId (ReorderBuffer *, TransactionId, XLogRecPtr lsn, CommandId cid)
 
void ReorderBufferAddNewTupleCids (ReorderBuffer *, TransactionId, XLogRecPtr lsn, RelFileNode node, ItemPointerData pt, CommandId cmin, CommandId cmax, CommandId combocid)
 
void ReorderBufferAddInvalidations (ReorderBuffer *, TransactionId, XLogRecPtr lsn, Size nmsgs, SharedInvalidationMessage *msgs)
 
void ReorderBufferImmediateInvalidation (ReorderBuffer *, uint32 ninvalidations, SharedInvalidationMessage *invalidations)
 
void ReorderBufferProcessXid (ReorderBuffer *, TransactionId xid, XLogRecPtr lsn)
 
void ReorderBufferXidSetCatalogChanges (ReorderBuffer *, TransactionId xid, XLogRecPtr lsn)
 
bool ReorderBufferXidHasCatalogChanges (ReorderBuffer *, TransactionId xid)
 
bool ReorderBufferXidHasBaseSnapshot (ReorderBuffer *, TransactionId xid)
 
ReorderBufferTXNReorderBufferGetOldestTXN (ReorderBuffer *)
 
TransactionId ReorderBufferGetOldestXmin (ReorderBuffer *rb)
 
void ReorderBufferSetRestartPoint (ReorderBuffer *, XLogRecPtr ptr)
 
void StartupReorderBuffer (void)
 

Macro Definition Documentation

◆ ReorderBufferTupleBufData

#define ReorderBufferTupleBufData (   p)    ((HeapTupleHeader) MAXALIGN(((char *) p) + sizeof(ReorderBufferTupleBuf)))

Typedef Documentation

◆ ReorderBuffer

typedef struct ReorderBuffer ReorderBuffer

Definition at line 292 of file reorderbuffer.h.

◆ ReorderBufferApplyChangeCB

typedef void(* ReorderBufferApplyChangeCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)

Definition at line 295 of file reorderbuffer.h.

◆ ReorderBufferApplyTruncateCB

typedef void(* ReorderBufferApplyTruncateCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)

Definition at line 301 of file reorderbuffer.h.

◆ ReorderBufferBeginCB

typedef void(* ReorderBufferBeginCB) (ReorderBuffer *rb, ReorderBufferTXN *txn)

Definition at line 308 of file reorderbuffer.h.

◆ ReorderBufferChange

◆ ReorderBufferCommitCB

typedef void(* ReorderBufferCommitCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)

Definition at line 312 of file reorderbuffer.h.

◆ ReorderBufferMessageCB

typedef void(* ReorderBufferMessageCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)

Definition at line 317 of file reorderbuffer.h.

◆ ReorderBufferTupleBuf

◆ ReorderBufferTXN

Enumeration Type Documentation

◆ ReorderBufferChangeType

Enumerator
REORDER_BUFFER_CHANGE_INSERT 
REORDER_BUFFER_CHANGE_UPDATE 
REORDER_BUFFER_CHANGE_DELETE 
REORDER_BUFFER_CHANGE_MESSAGE 
REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT 
REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID 
REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID 
REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT 
REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM 
REORDER_BUFFER_CHANGE_TRUNCATE 

Definition at line 52 of file reorderbuffer.h.

Function Documentation

◆ ReorderBufferAbort()

void ReorderBufferAbort ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn 
)

Definition at line 1856 of file reorderbuffer.c.

References ReorderBufferTXN::final_lsn, InvalidXLogRecPtr, ReorderBufferCleanupTXN(), ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeAbort().

1857 {
1858  ReorderBufferTXN *txn;
1859 
1860  txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
1861  false);
1862 
1863  /* unknown, nothing to remove */
1864  if (txn == NULL)
1865  return;
1866 
1867  /* cosmetic... */
1868  txn->final_lsn = lsn;
1869 
1870  /* remove potential on-disk data, and deallocate */
1871  ReorderBufferCleanupTXN(rb, txn);
1872 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr final_lsn
static void ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ ReorderBufferAbortOld()

void ReorderBufferAbortOld ( ReorderBuffer ,
TransactionId  xid 
)

Definition at line 1882 of file reorderbuffer.c.

References ReorderBufferTXN::changes, dlist_mutable_iter::cur, DEBUG2, dlist_container, dlist_foreach_modify, dlist_tail_element, elog, ReorderBufferTXN::final_lsn, ReorderBufferChange::lsn, ReorderBufferCleanupTXN(), ReorderBufferTXN::serialized, ReorderBuffer::toplevel_by_lsn, TransactionIdPrecedes(), ReorderBufferTXNByIdEnt::txn, and ReorderBufferTXN::xid.

Referenced by DecodeStandbyOp().

1883 {
1884  dlist_mutable_iter it;
1885 
1886  /*
1887  * Iterate through all (potential) toplevel TXNs and abort all that are
1888  * older than what possibly can be running. Once we've found the first
1889  * that is alive we stop, there might be some that acquired an xid earlier
1890  * but started writing later, but it's unlikely and they will be cleaned
1891  * up in a later call to this function.
1892  */
1893  dlist_foreach_modify(it, &rb->toplevel_by_lsn)
1894  {
1895  ReorderBufferTXN *txn;
1896 
1897  txn = dlist_container(ReorderBufferTXN, node, it.cur);
1898 
1899  if (TransactionIdPrecedes(txn->xid, oldestRunningXid))
1900  {
1901  /*
1902  * We set final_lsn on a transaction when we decode its commit or
1903  * abort record, but we never see those records for crashed
1904  * transactions. To ensure cleanup of these transactions, set
1905  * final_lsn to that of their last change; this causes
1906  * ReorderBufferRestoreCleanup to do the right thing.
1907  */
1908  if (txn->serialized && txn->final_lsn == 0)
1909  {
1910  ReorderBufferChange *last =
1912 
1913  txn->final_lsn = last->lsn;
1914  }
1915 
1916  elog(DEBUG2, "aborting old transaction %u", txn->xid);
1917 
1918  /* remove potential on-disk data, and deallocate this tx */
1919  ReorderBufferCleanupTXN(rb, txn);
1920  }
1921  else
1922  return;
1923  }
1924 }
dlist_node * cur
Definition: ilist.h:180
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define dlist_tail_element(type, membername, lhead)
Definition: ilist.h:496
dlist_head changes
#define DEBUG2
Definition: elog.h:24
XLogRecPtr final_lsn
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
TransactionId xid
#define elog(elevel,...)
Definition: elog.h:226

◆ ReorderBufferAddInvalidations()

void ReorderBufferAddInvalidations ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
Size  nmsgs,
SharedInvalidationMessage msgs 
)

Definition at line 2118 of file reorderbuffer.c.

References Assert, ReorderBuffer::context, elog, ERROR, ReorderBufferTXN::invalidations, MemoryContextAlloc(), ReorderBufferTXN::ninvalidations, ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeCommit().

2121 {
2122  ReorderBufferTXN *txn;
2123 
2124  txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
2125 
2126  if (txn->ninvalidations != 0)
2127  elog(ERROR, "only ever add one set of invalidations");
2128 
2129  Assert(nmsgs > 0);
2130 
2131  txn->ninvalidations = nmsgs;
2133  MemoryContextAlloc(rb->context,
2134  sizeof(SharedInvalidationMessage) * nmsgs);
2135  memcpy(txn->invalidations, msgs,
2136  sizeof(SharedInvalidationMessage) * nmsgs);
2137 }
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:732
SharedInvalidationMessage * invalidations
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:226

◆ ReorderBufferAddNewCommandId()

void ReorderBufferAddNewCommandId ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
CommandId  cid 
)

Definition at line 2074 of file reorderbuffer.c.

References ReorderBufferChange::action, ReorderBufferChange::command_id, ReorderBufferChange::data, REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID, ReorderBufferGetChange(), and ReorderBufferQueueChange().

Referenced by SnapBuildProcessNewCid().

2076 {
2078 
2079  change->data.command_id = cid;
2081 
2082  ReorderBufferQueueChange(rb, xid, lsn, change);
2083 }
ReorderBufferChange * ReorderBufferGetChange(ReorderBuffer *rb)
enum ReorderBufferChangeType action
Definition: reorderbuffer.h:78
union ReorderBufferChange::@101 data
void ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, ReorderBufferChange *change)

◆ ReorderBufferAddNewTupleCids()

void ReorderBufferAddNewTupleCids ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
RelFileNode  node,
ItemPointerData  pt,
CommandId  cmin,
CommandId  cmax,
CommandId  combocid 
)

Definition at line 2090 of file reorderbuffer.c.

References ReorderBufferChange::action, ReorderBufferChange::data, dlist_push_tail(), ReorderBufferChange::lsn, ReorderBufferChange::node, ReorderBufferTXN::ntuplecids, REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID, ReorderBufferGetChange(), ReorderBufferTXNByXid(), ReorderBufferChange::tuplecid, ReorderBufferTXN::tuplecids, and ReorderBufferTXNByIdEnt::txn.

Referenced by SnapBuildProcessNewCid().

2094 {
2096  ReorderBufferTXN *txn;
2097 
2098  txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
2099 
2100  change->data.tuplecid.node = node;
2101  change->data.tuplecid.tid = tid;
2102  change->data.tuplecid.cmin = cmin;
2103  change->data.tuplecid.cmax = cmax;
2104  change->data.tuplecid.combocid = combocid;
2105  change->lsn = lsn;
2107 
2108  dlist_push_tail(&txn->tuplecids, &change->node);
2109  txn->ntuplecids++;
2110 }
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
struct ReorderBufferChange::@101::@105 tuplecid
ReorderBufferChange * ReorderBufferGetChange(ReorderBuffer *rb)
enum ReorderBufferChangeType action
Definition: reorderbuffer.h:78
union ReorderBufferChange::@101 data
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
dlist_head tuplecids

◆ ReorderBufferAddSnapshot()

void ReorderBufferAddSnapshot ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
struct SnapshotData snap 
)

◆ ReorderBufferAllocate()

ReorderBuffer* ReorderBufferAllocate ( void  )

Definition at line 226 of file reorderbuffer.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, ReorderBuffer::by_txn, ReorderBuffer::by_txn_last_txn, ReorderBuffer::by_txn_last_xid, ReorderBuffer::change_context, ReorderBuffer::context, ReorderBuffer::current_restart_decoding_lsn, CurrentMemoryContext, ReplicationSlot::data, dlist_init(), HASHCTL::entrysize, GenerationContextCreate(), HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASHCTL::hcxt, InvalidTransactionId, InvalidXLogRecPtr, HASHCTL::keysize, MemoryContextAlloc(), MyReplicationSlot, ReplicationSlotPersistentData::name, NameStr, ReorderBuffer::outbuf, ReorderBuffer::outbufsize, ReorderBufferCleanupSerializedTXNs(), SLAB_DEFAULT_BLOCK_SIZE, SLAB_LARGE_BLOCK_SIZE, SlabContextCreate(), ReorderBuffer::toplevel_by_lsn, ReorderBuffer::tup_context, ReorderBuffer::txn_context, and ReorderBuffer::txns_by_base_snapshot_lsn.

Referenced by StartupDecodingContext().

227 {
228  ReorderBuffer *buffer;
229  HASHCTL hash_ctl;
230  MemoryContext new_ctx;
231 
232  Assert(MyReplicationSlot != NULL);
233 
234  /* allocate memory in own context, to have better accountability */
236  "ReorderBuffer",
238 
239  buffer =
240  (ReorderBuffer *) MemoryContextAlloc(new_ctx, sizeof(ReorderBuffer));
241 
242  memset(&hash_ctl, 0, sizeof(hash_ctl));
243 
244  buffer->context = new_ctx;
245 
246  buffer->change_context = SlabContextCreate(new_ctx,
247  "Change",
249  sizeof(ReorderBufferChange));
250 
251  buffer->txn_context = SlabContextCreate(new_ctx,
252  "TXN",
254  sizeof(ReorderBufferTXN));
255 
256  buffer->tup_context = GenerationContextCreate(new_ctx,
257  "Tuples",
259 
260  hash_ctl.keysize = sizeof(TransactionId);
261  hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
262  hash_ctl.hcxt = buffer->context;
263 
264  buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
266 
268  buffer->by_txn_last_txn = NULL;
269 
270  buffer->outbuf = NULL;
271  buffer->outbufsize = 0;
272 
274 
275  dlist_init(&buffer->toplevel_by_lsn);
277 
278  /*
279  * Ensure there's no stale data from prior uses of this slot, in case some
280  * prior exit avoided calling ReorderBufferFree. Failure to do this can
281  * produce duplicated txns, and it's very cheap if there's nothing there.
282  */
284 
285  return buffer;
286 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define AllocSetContextCreate
Definition: memutils.h:170
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
uint32 TransactionId
Definition: c.h:507
MemoryContext hcxt
Definition: hsearch.h:78
TransactionId by_txn_last_xid
XLogRecPtr current_restart_decoding_lsn
Size entrysize
Definition: hsearch.h:73
MemoryContext SlabContextCreate(MemoryContext parent, const char *name, Size blockSize, Size chunkSize)
Definition: slab.c:188
ReplicationSlotPersistentData data
Definition: slot.h:132
MemoryContext change_context
#define SLAB_LARGE_BLOCK_SIZE
Definition: memutils.h:222
dlist_head txns_by_base_snapshot_lsn
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define InvalidTransactionId
Definition: transam.h:31
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define HASH_BLOBS
Definition: hsearch.h:88
MemoryContext GenerationContextCreate(MemoryContext parent, const char *name, Size blockSize)
Definition: generation.c:212
MemoryContext context
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
ReorderBufferTXN * by_txn_last_txn
dlist_head toplevel_by_lsn
Size keysize
Definition: hsearch.h:72
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
ReplicationSlot * MyReplicationSlot
Definition: slot.c:96
#define Assert(condition)
Definition: c.h:732
#define SLAB_DEFAULT_BLOCK_SIZE
Definition: memutils.h:221
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define NameStr(name)
Definition: c.h:609
struct ReorderBufferTXNByIdEnt ReorderBufferTXNByIdEnt
MemoryContext tup_context
static void ReorderBufferCleanupSerializedTXNs(const char *slotname)
MemoryContext txn_context

◆ ReorderBufferAssignChild()

void ReorderBufferAssignChild ( ReorderBuffer ,
TransactionId  ,
TransactionId  ,
XLogRecPtr  commit_lsn 
)

Definition at line 770 of file reorderbuffer.c.

References Assert, AssertTXNLsnOrder(), dlist_delete(), dlist_push_tail(), elog, ERROR, ReorderBufferTXN::is_known_as_subxact, ReorderBufferTXN::node, ReorderBufferTXN::nsubtxns, ReorderBufferTransferSnapToParent(), ReorderBufferTXNByXid(), ReorderBufferTXN::subtxns, ReorderBufferTXN::toplevel_xid, ReorderBufferTXNByIdEnt::txn, and ReorderBufferTXNByIdEnt::xid.

Referenced by DecodeXactOp(), and ReorderBufferCommitChild().

772 {
773  ReorderBufferTXN *txn;
774  ReorderBufferTXN *subtxn;
775  bool new_top;
776  bool new_sub;
777 
778  txn = ReorderBufferTXNByXid(rb, xid, true, &new_top, lsn, true);
779  subtxn = ReorderBufferTXNByXid(rb, subxid, true, &new_sub, lsn, false);
780 
781  if (new_top && !new_sub)
782  elog(ERROR, "subtransaction logged without previous top-level txn record");
783 
784  if (!new_sub)
785  {
786  if (subtxn->is_known_as_subxact)
787  {
788  /* already associated, nothing to do */
789  return;
790  }
791  else
792  {
793  /*
794  * We already saw this transaction, but initially added it to the
795  * list of top-level txns. Now that we know it's not top-level,
796  * remove it from there.
797  */
798  dlist_delete(&subtxn->node);
799  }
800  }
801 
802  subtxn->is_known_as_subxact = true;
803  subtxn->toplevel_xid = xid;
804  Assert(subtxn->nsubtxns == 0);
805 
806  /* add to subtransaction list */
807  dlist_push_tail(&txn->subtxns, &subtxn->node);
808  txn->nsubtxns++;
809 
810  /* Possibly transfer the subtxn's snapshot to its top-level txn. */
812 
813  /* Verify LSN-ordering invariant */
814  AssertTXNLsnOrder(rb);
815 }
static void ReorderBufferTransferSnapToParent(ReorderBufferTXN *txn, ReorderBufferTXN *subtxn)
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
#define ERROR
Definition: elog.h:43
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
static void AssertTXNLsnOrder(ReorderBuffer *rb)
#define Assert(condition)
Definition: c.h:732
dlist_head subtxns
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
#define elog(elevel,...)
Definition: elog.h:226
TransactionId toplevel_xid

◆ ReorderBufferCommit()

void ReorderBufferCommit ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  commit_lsn,
XLogRecPtr  end_lsn,
TimestampTz  commit_time,
RepOriginId  origin_id,
XLogRecPtr  origin_lsn 
)

Definition at line 1434 of file reorderbuffer.c.

References AbortCurrentTransaction(), ReorderBufferChange::action, ReorderBuffer::apply_change, ReorderBuffer::apply_truncate, Assert, ReorderBufferTXN::base_snapshot, ReorderBuffer::begin, BeginInternalSubTransaction(), ReorderBufferChange::command_id, ReorderBuffer::commit, ReorderBufferTXN::commit_time, SnapshotData::copied, SnapshotData::curcid, ReorderBufferChange::data, dlist_delete(), elog, ReorderBufferTXN::end_lsn, ERROR, ReorderBufferTXN::final_lsn, FirstCommandId, GetCurrentTransactionId(), GetCurrentTransactionIdIfAny(), i, InvalidCommandId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsToastRelation(), IsTransactionOrTransactionBlock(), ReorderBufferChange::lsn, MAIN_FORKNUM, ReorderBuffer::message, ReorderBufferChange::msg, ReorderBufferTXN::ninvalidations, ReorderBufferChange::node, ReorderBufferTXN::origin_id, ReorderBufferTXN::origin_lsn, ReorderBuffer::output_rewrites, palloc0(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, RelationData::rd_rel, RelationClose(), RelationIdGetRelation(), RelationIsLogicallyLogged, RelationIsValid, RelidByRelfilenode(), relpathperm, REORDER_BUFFER_CHANGE_DELETE, REORDER_BUFFER_CHANGE_INSERT, REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID, REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT, REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM, REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT, REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID, REORDER_BUFFER_CHANGE_MESSAGE, REORDER_BUFFER_CHANGE_TRUNCATE, REORDER_BUFFER_CHANGE_UPDATE, ReorderBufferBuildTupleCidHash(), ReorderBufferCleanupTXN(), ReorderBufferCopySnap(), ReorderBufferExecuteInvalidations(), ReorderBufferFreeSnap(), ReorderBufferIterTXNFinish(), ReorderBufferIterTXNInit(), ReorderBufferIterTXNNext(), ReorderBufferReturnChange(), ReorderBufferToastAppendChunk(), ReorderBufferToastReplace(), ReorderBufferToastReset(), ReorderBufferTXNByXid(), RollbackAndReleaseCurrentSubTransaction(), SetupHistoricSnapshot(), ReorderBufferChange::snapshot, StartTransactionCommand(), TeardownHistoricSnapshot(), ReorderBufferChange::tp, ReorderBufferChange::truncate, ReorderBufferTXN::tuplecid_hash, and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeCommit().

1438 {
1439  ReorderBufferTXN *txn;
1440  volatile Snapshot snapshot_now;
1441  volatile CommandId command_id = FirstCommandId;
1442  bool using_subtxn;
1443  ReorderBufferIterTXNState *volatile iterstate = NULL;
1444 
1445  txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
1446  false);
1447 
1448  /* unknown transaction, nothing to replay */
1449  if (txn == NULL)
1450  return;
1451 
1452  txn->final_lsn = commit_lsn;
1453  txn->end_lsn = end_lsn;
1454  txn->commit_time = commit_time;
1455  txn->origin_id = origin_id;
1456  txn->origin_lsn = origin_lsn;
1457 
1458  /*
1459  * If this transaction has no snapshot, it didn't make any changes to the
1460  * database, so there's nothing to decode. Note that
1461  * ReorderBufferCommitChild will have transferred any snapshots from
1462  * subtransactions if there were any.
1463  */
1464  if (txn->base_snapshot == NULL)
1465  {
1466  Assert(txn->ninvalidations == 0);
1467  ReorderBufferCleanupTXN(rb, txn);
1468  return;
1469  }
1470 
1471  snapshot_now = txn->base_snapshot;
1472 
1473  /* build data to be able to lookup the CommandIds of catalog tuples */
1475 
1476  /* setup the initial snapshot */
1477  SetupHistoricSnapshot(snapshot_now, txn->tuplecid_hash);
1478 
1479  /*
1480  * Decoding needs access to syscaches et al., which in turn use
1481  * heavyweight locks and such. Thus we need to have enough state around to
1482  * keep track of those. The easiest way is to simply use a transaction
1483  * internally. That also allows us to easily enforce that nothing writes
1484  * to the database by checking for xid assignments.
1485  *
1486  * When we're called via the SQL SRF there's already a transaction
1487  * started, so start an explicit subtransaction there.
1488  */
1489  using_subtxn = IsTransactionOrTransactionBlock();
1490 
1491  PG_TRY();
1492  {
1493  ReorderBufferChange *change;
1494  ReorderBufferChange *specinsert = NULL;
1495 
1496  if (using_subtxn)
1497  BeginInternalSubTransaction("replay");
1498  else
1500 
1501  rb->begin(rb, txn);
1502 
1503  iterstate = ReorderBufferIterTXNInit(rb, txn);
1504  while ((change = ReorderBufferIterTXNNext(rb, iterstate)) != NULL)
1505  {
1506  Relation relation = NULL;
1507  Oid reloid;
1508 
1509  switch (change->action)
1510  {
1512 
1513  /*
1514  * Confirmation for speculative insertion arrived. Simply
1515  * use as a normal record. It'll be cleaned up at the end
1516  * of INSERT processing.
1517  */
1518  if (specinsert == NULL)
1519  elog(ERROR, "invalid ordering of speculative insertion changes");
1520  Assert(specinsert->data.tp.oldtuple == NULL);
1521  change = specinsert;
1523 
1524  /* intentionally fall through */
1528  Assert(snapshot_now);
1529 
1530  reloid = RelidByRelfilenode(change->data.tp.relnode.spcNode,
1531  change->data.tp.relnode.relNode);
1532 
1533  /*
1534  * Mapped catalog tuple without data, emitted while
1535  * catalog table was in the process of being rewritten. We
1536  * can fail to look up the relfilenode, because the
1537  * relmapper has no "historic" view, in contrast to normal
1538  * the normal catalog during decoding. Thus repeated
1539  * rewrites can cause a lookup failure. That's OK because
1540  * we do not decode catalog changes anyway. Normally such
1541  * tuples would be skipped over below, but we can't
1542  * identify whether the table should be logically logged
1543  * without mapping the relfilenode to the oid.
1544  */
1545  if (reloid == InvalidOid &&
1546  change->data.tp.newtuple == NULL &&
1547  change->data.tp.oldtuple == NULL)
1548  goto change_done;
1549  else if (reloid == InvalidOid)
1550  elog(ERROR, "could not map filenode \"%s\" to relation OID",
1551  relpathperm(change->data.tp.relnode,
1552  MAIN_FORKNUM));
1553 
1554  relation = RelationIdGetRelation(reloid);
1555 
1556  if (!RelationIsValid(relation))
1557  elog(ERROR, "could not open relation with OID %u (for filenode \"%s\")",
1558  reloid,
1559  relpathperm(change->data.tp.relnode,
1560  MAIN_FORKNUM));
1561 
1562  if (!RelationIsLogicallyLogged(relation))
1563  goto change_done;
1564 
1565  /*
1566  * Ignore temporary heaps created during DDL unless the
1567  * plugin has asked for them.
1568  */
1569  if (relation->rd_rel->relrewrite && !rb->output_rewrites)
1570  goto change_done;
1571 
1572  /*
1573  * For now ignore sequence changes entirely. Most of the
1574  * time they don't log changes using records we
1575  * understand, so it doesn't make sense to handle the few
1576  * cases we do.
1577  */
1578  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1579  goto change_done;
1580 
1581  /* user-triggered change */
1582  if (!IsToastRelation(relation))
1583  {
1584  ReorderBufferToastReplace(rb, txn, relation, change);
1585  rb->apply_change(rb, txn, relation, change);
1586 
1587  /*
1588  * Only clear reassembled toast chunks if we're sure
1589  * they're not required anymore. The creator of the
1590  * tuple tells us.
1591  */
1592  if (change->data.tp.clear_toast_afterwards)
1593  ReorderBufferToastReset(rb, txn);
1594  }
1595  /* we're not interested in toast deletions */
1596  else if (change->action == REORDER_BUFFER_CHANGE_INSERT)
1597  {
1598  /*
1599  * Need to reassemble the full toasted Datum in
1600  * memory, to ensure the chunks don't get reused till
1601  * we're done remove it from the list of this
1602  * transaction's changes. Otherwise it will get
1603  * freed/reused while restoring spooled data from
1604  * disk.
1605  */
1606  Assert(change->data.tp.newtuple != NULL);
1607 
1608  dlist_delete(&change->node);
1609  ReorderBufferToastAppendChunk(rb, txn, relation,
1610  change);
1611  }
1612 
1613  change_done:
1614 
1615  /*
1616  * Either speculative insertion was confirmed, or it was
1617  * unsuccessful and the record isn't needed anymore.
1618  */
1619  if (specinsert != NULL)
1620  {
1621  ReorderBufferReturnChange(rb, specinsert);
1622  specinsert = NULL;
1623  }
1624 
1625  if (relation != NULL)
1626  {
1627  RelationClose(relation);
1628  relation = NULL;
1629  }
1630  break;
1631 
1633 
1634  /*
1635  * Speculative insertions are dealt with by delaying the
1636  * processing of the insert until the confirmation record
1637  * arrives. For that we simply unlink the record from the
1638  * chain, so it does not get freed/reused while restoring
1639  * spooled data from disk.
1640  *
1641  * This is safe in the face of concurrent catalog changes
1642  * because the relevant relation can't be changed between
1643  * speculative insertion and confirmation due to
1644  * CheckTableNotInUse() and locking.
1645  */
1646 
1647  /* clear out a pending (and thus failed) speculation */
1648  if (specinsert != NULL)
1649  {
1650  ReorderBufferReturnChange(rb, specinsert);
1651  specinsert = NULL;
1652  }
1653 
1654  /* and memorize the pending insertion */
1655  dlist_delete(&change->node);
1656  specinsert = change;
1657  break;
1658 
1660  {
1661  int i;
1662  int nrelids = change->data.truncate.nrelids;
1663  int nrelations = 0;
1664  Relation *relations;
1665 
1666  relations = palloc0(nrelids * sizeof(Relation));
1667  for (i = 0; i < nrelids; i++)
1668  {
1669  Oid relid = change->data.truncate.relids[i];
1670  Relation relation;
1671 
1672  relation = RelationIdGetRelation(relid);
1673 
1674  if (!RelationIsValid(relation))
1675  elog(ERROR, "could not open relation with OID %u", relid);
1676 
1677  if (!RelationIsLogicallyLogged(relation))
1678  continue;
1679 
1680  relations[nrelations++] = relation;
1681  }
1682 
1683  rb->apply_truncate(rb, txn, nrelations, relations, change);
1684 
1685  for (i = 0; i < nrelations; i++)
1686  RelationClose(relations[i]);
1687 
1688  break;
1689  }
1690 
1692  rb->message(rb, txn, change->lsn, true,
1693  change->data.msg.prefix,
1694  change->data.msg.message_size,
1695  change->data.msg.message);
1696  break;
1697 
1699  /* get rid of the old */
1700  TeardownHistoricSnapshot(false);
1701 
1702  if (snapshot_now->copied)
1703  {
1704  ReorderBufferFreeSnap(rb, snapshot_now);
1705  snapshot_now =
1706  ReorderBufferCopySnap(rb, change->data.snapshot,
1707  txn, command_id);
1708  }
1709 
1710  /*
1711  * Restored from disk, need to be careful not to double
1712  * free. We could introduce refcounting for that, but for
1713  * now this seems infrequent enough not to care.
1714  */
1715  else if (change->data.snapshot->copied)
1716  {
1717  snapshot_now =
1718  ReorderBufferCopySnap(rb, change->data.snapshot,
1719  txn, command_id);
1720  }
1721  else
1722  {
1723  snapshot_now = change->data.snapshot;
1724  }
1725 
1726 
1727  /* and continue with the new one */
1728  SetupHistoricSnapshot(snapshot_now, txn->tuplecid_hash);
1729  break;
1730 
1732  Assert(change->data.command_id != InvalidCommandId);
1733 
1734  if (command_id < change->data.command_id)
1735  {
1736  command_id = change->data.command_id;
1737 
1738  if (!snapshot_now->copied)
1739  {
1740  /* we don't use the global one anymore */
1741  snapshot_now = ReorderBufferCopySnap(rb, snapshot_now,
1742  txn, command_id);
1743  }
1744 
1745  snapshot_now->curcid = command_id;
1746 
1747  TeardownHistoricSnapshot(false);
1748  SetupHistoricSnapshot(snapshot_now, txn->tuplecid_hash);
1749 
1750  /*
1751  * Every time the CommandId is incremented, we could
1752  * see new catalog contents, so execute all
1753  * invalidations.
1754  */
1756  }
1757 
1758  break;
1759 
1761  elog(ERROR, "tuplecid value in changequeue");
1762  break;
1763  }
1764  }
1765 
1766  /*
1767  * There's a speculative insertion remaining, just clean in up, it
1768  * can't have been successful, otherwise we'd gotten a confirmation
1769  * record.
1770  */
1771  if (specinsert)
1772  {
1773  ReorderBufferReturnChange(rb, specinsert);
1774  specinsert = NULL;
1775  }
1776 
1777  /* clean up the iterator */
1778  ReorderBufferIterTXNFinish(rb, iterstate);
1779  iterstate = NULL;
1780 
1781  /* call commit callback */
1782  rb->commit(rb, txn, commit_lsn);
1783 
1784  /* this is just a sanity check against bad output plugin behaviour */
1786  elog(ERROR, "output plugin used XID %u",
1788 
1789  /* cleanup */
1790  TeardownHistoricSnapshot(false);
1791 
1792  /*
1793  * Aborting the current (sub-)transaction as a whole has the right
1794  * semantics. We want all locks acquired in here to be released, not
1795  * reassigned to the parent and we do not want any database access
1796  * have persistent effects.
1797  */
1799 
1800  /* make sure there's no cache pollution */
1802 
1803  if (using_subtxn)
1805 
1806  if (snapshot_now->copied)
1807  ReorderBufferFreeSnap(rb, snapshot_now);
1808 
1809  /* remove potential on-disk data, and deallocate */
1810  ReorderBufferCleanupTXN(rb, txn);
1811  }
1812  PG_CATCH();
1813  {
1814  /* TODO: Encapsulate cleanup from the PG_TRY and PG_CATCH blocks */
1815  if (iterstate)
1816  ReorderBufferIterTXNFinish(rb, iterstate);
1817 
1819 
1820  /*
1821  * Force cache invalidation to happen outside of a valid transaction
1822  * to prevent catalog access as we just caught an error.
1823  */
1825 
1826  /* make sure there's no cache pollution */
1828 
1829  if (using_subtxn)
1831 
1832  if (snapshot_now->copied)
1833  ReorderBufferFreeSnap(rb, snapshot_now);
1834 
1835  /* remove potential on-disk data, and deallocate */
1836  ReorderBufferCleanupTXN(rb, txn);
1837 
1838  PG_RE_THROW();
1839  }
1840  PG_END_TRY();
1841 }
static void ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
uint32 CommandId
Definition: c.h:521
void ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change)
TimestampTz commit_time
void AbortCurrentTransaction(void)
Definition: xact.c:3159
bool IsToastRelation(Relation relation)
Definition: catalog.c:142
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
Snapshot base_snapshot
static void ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)
RepOriginId origin_id
bool copied
Definition: snapshot.h:185
struct ReorderBufferChange::@101::@102 tp
struct ReorderBufferChange::@101::@104 msg
Oid RelidByRelfilenode(Oid reltablespace, Oid relfilenode)
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4651
static void ReorderBufferIterTXNFinish(ReorderBuffer *rb, ReorderBufferIterTXNState *state)
void TeardownHistoricSnapshot(bool is_error)
Definition: snapmgr.c:2051
#define RelationIsLogicallyLogged(relation)
Definition: rel.h:591
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
enum ReorderBufferChangeType action
Definition: reorderbuffer.h:78
XLogRecPtr origin_lsn
#define FirstCommandId
Definition: c.h:523
#define ERROR
Definition: elog.h:43
#define RelationIsValid(relation)
Definition: rel.h:392
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:423
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4462
TransactionId GetCurrentTransactionIdIfAny(void)
Definition: xact.c:440
#define InvalidTransactionId
Definition: transam.h:31
XLogRecPtr final_lsn
void RelationClose(Relation relation)
Definition: relcache.c:2089
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
static Snapshot ReorderBufferCopySnap(ReorderBuffer *rb, Snapshot orig_snap, ReorderBufferTXN *txn, CommandId cid)
void * palloc0(Size size)
Definition: mcxt.c:980
#define InvalidCommandId
Definition: c.h:524
static void ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
static void ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:187
static void ReorderBufferExecuteInvalidations(ReorderBuffer *rb, ReorderBufferTXN *txn)
#define PG_CATCH()
Definition: elog.h:310
#define Assert(condition)
Definition: c.h:732
union ReorderBufferChange::@101 data
static void ReorderBufferToastReset(ReorderBuffer *rb, ReorderBufferTXN *txn)
static ReorderBufferChange * ReorderBufferIterTXNNext(ReorderBuffer *rb, ReorderBufferIterTXNState *state)
XLogRecPtr end_lsn
void StartTransactionCommand(void)
Definition: xact.c:2794
void BeginInternalSubTransaction(const char *name)
Definition: xact.c:4357
#define PG_RE_THROW()
Definition: elog.h:331
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
void SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
Definition: snapmgr.c:2035
#define elog(elevel,...)
Definition: elog.h:226
int i
#define PG_TRY()
Definition: elog.h:301
static void ReorderBufferFreeSnap(ReorderBuffer *rb, Snapshot snap)
static ReorderBufferIterTXNState * ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn)
Relation RelationIdGetRelation(Oid relationId)
Definition: relcache.c:1990
#define PG_END_TRY()
Definition: elog.h:317
struct ReorderBufferChange::@101::@103 truncate

◆ ReorderBufferCommitChild()

void ReorderBufferCommitChild ( ReorderBuffer ,
TransactionId  ,
TransactionId  ,
XLogRecPtr  commit_lsn,
XLogRecPtr  end_lsn 
)

Definition at line 890 of file reorderbuffer.c.

References ReorderBufferTXN::end_lsn, ReorderBufferTXN::final_lsn, InvalidXLogRecPtr, ReorderBufferAssignChild(), and ReorderBufferTXNByXid().

Referenced by DecodeCommit().

893 {
894  ReorderBufferTXN *subtxn;
895 
896  subtxn = ReorderBufferTXNByXid(rb, subxid, false, NULL,
897  InvalidXLogRecPtr, false);
898 
899  /*
900  * No need to do anything if that subtxn didn't contain any changes
901  */
902  if (!subtxn)
903  return;
904 
905  subtxn->final_lsn = commit_lsn;
906  subtxn->end_lsn = end_lsn;
907 
908  /*
909  * Assign this subxact as a child of the toplevel xact (no-op if already
910  * done.)
911  */
913 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr final_lsn
void ReorderBufferAssignChild(ReorderBuffer *rb, TransactionId xid, TransactionId subxid, XLogRecPtr lsn)
XLogRecPtr end_lsn
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ ReorderBufferForget()

void ReorderBufferForget ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn 
)

Definition at line 1940 of file reorderbuffer.c.

References Assert, ReorderBufferTXN::base_snapshot, ReorderBufferTXN::final_lsn, ReorderBufferTXN::invalidations, InvalidXLogRecPtr, ReorderBufferTXN::ninvalidations, ReorderBufferCleanupTXN(), ReorderBufferImmediateInvalidation(), ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeCommit().

1941 {
1942  ReorderBufferTXN *txn;
1943 
1944  txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
1945  false);
1946 
1947  /* unknown, nothing to forget */
1948  if (txn == NULL)
1949  return;
1950 
1951  /* cosmetic... */
1952  txn->final_lsn = lsn;
1953 
1954  /*
1955  * Process cache invalidation messages if there are any. Even if we're not
1956  * interested in the transaction's contents, it could have manipulated the
1957  * catalog and we need to update the caches according to that.
1958  */
1959  if (txn->base_snapshot != NULL && txn->ninvalidations > 0)
1961  txn->invalidations);
1962  else
1963  Assert(txn->ninvalidations == 0);
1964 
1965  /* remove potential on-disk data, and deallocate */
1966  ReorderBufferCleanupTXN(rb, txn);
1967 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
Snapshot base_snapshot
void ReorderBufferImmediateInvalidation(ReorderBuffer *rb, uint32 ninvalidations, SharedInvalidationMessage *invalidations)
XLogRecPtr final_lsn
static void ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
#define Assert(condition)
Definition: c.h:732
SharedInvalidationMessage * invalidations
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ ReorderBufferFree()

void ReorderBufferFree ( ReorderBuffer )

Definition at line 292 of file reorderbuffer.c.

References ReorderBuffer::context, ReplicationSlot::data, MemoryContextDelete(), MyReplicationSlot, ReplicationSlotPersistentData::name, NameStr, and ReorderBufferCleanupSerializedTXNs().

Referenced by FreeDecodingContext().

293 {
294  MemoryContext context = rb->context;
295 
296  /*
297  * We free separately allocated data by entirely scrapping reorderbuffer's
298  * memory context.
299  */
300  MemoryContextDelete(context);
301 
302  /* Free disk space used by unconsumed reorder buffers */
304 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
ReplicationSlotPersistentData data
Definition: slot.h:132
ReplicationSlot * MyReplicationSlot
Definition: slot.c:96
#define NameStr(name)
Definition: c.h:609
static void ReorderBufferCleanupSerializedTXNs(const char *slotname)

◆ ReorderBufferGetChange()

ReorderBufferChange* ReorderBufferGetChange ( ReorderBuffer )

Definition at line 360 of file reorderbuffer.c.

References ReorderBuffer::change_context, and MemoryContextAlloc().

Referenced by DecodeDelete(), DecodeInsert(), DecodeMultiInsert(), DecodeSpecConfirm(), DecodeTruncate(), DecodeUpdate(), ReorderBufferAddNewCommandId(), ReorderBufferAddNewTupleCids(), ReorderBufferAddSnapshot(), ReorderBufferQueueMessage(), and ReorderBufferRestoreChange().

361 {
362  ReorderBufferChange *change;
363 
364  change = (ReorderBufferChange *)
365  MemoryContextAlloc(rb->change_context, sizeof(ReorderBufferChange));
366 
367  memset(change, 0, sizeof(ReorderBufferChange));
368  return change;
369 }
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796

◆ ReorderBufferGetOldestTXN()

ReorderBufferTXN* ReorderBufferGetOldestTXN ( ReorderBuffer )

Definition at line 715 of file reorderbuffer.c.

References Assert, AssertTXNLsnOrder(), dlist_head_element, dlist_is_empty(), ReorderBufferTXN::first_lsn, InvalidXLogRecPtr, ReorderBufferTXN::is_known_as_subxact, ReorderBuffer::toplevel_by_lsn, and ReorderBufferTXNByIdEnt::txn.

Referenced by SnapBuildProcessRunningXacts().

716 {
717  ReorderBufferTXN *txn;
718 
719  AssertTXNLsnOrder(rb);
720 
721  if (dlist_is_empty(&rb->toplevel_by_lsn))
722  return NULL;
723 
724  txn = dlist_head_element(ReorderBufferTXN, node, &rb->toplevel_by_lsn);
725 
728  return txn;
729 }
XLogRecPtr first_lsn
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:487
static void AssertTXNLsnOrder(ReorderBuffer *rb)
#define Assert(condition)
Definition: c.h:732
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289

◆ ReorderBufferGetOldestXmin()

TransactionId ReorderBufferGetOldestXmin ( ReorderBuffer rb)

Definition at line 743 of file reorderbuffer.c.

References AssertTXNLsnOrder(), ReorderBufferTXN::base_snapshot, dlist_head_element, dlist_is_empty(), InvalidTransactionId, ReorderBufferTXNByIdEnt::txn, ReorderBuffer::txns_by_base_snapshot_lsn, and SnapshotData::xmin.

Referenced by SnapBuildProcessRunningXacts().

744 {
745  ReorderBufferTXN *txn;
746 
747  AssertTXNLsnOrder(rb);
748 
750  return InvalidTransactionId;
751 
752  txn = dlist_head_element(ReorderBufferTXN, base_snapshot_node,
754  return txn->base_snapshot->xmin;
755 }
Snapshot base_snapshot
dlist_head txns_by_base_snapshot_lsn
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmin
Definition: snapshot.h:157
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:487
static void AssertTXNLsnOrder(ReorderBuffer *rb)
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289

◆ ReorderBufferGetRelids()

Oid* ReorderBufferGetRelids ( ReorderBuffer ,
int  nrelids 
)

Definition at line 469 of file reorderbuffer.c.

References ReorderBuffer::context, and MemoryContextAlloc().

Referenced by DecodeTruncate(), and ReorderBufferRestoreChange().

470 {
471  Oid *relids;
472  Size alloc_len;
473 
474  alloc_len = sizeof(Oid) * nrelids;
475 
476  relids = (Oid *) MemoryContextAlloc(rb->context, alloc_len);
477 
478  return relids;
479 }
unsigned int Oid
Definition: postgres_ext.h:31
size_t Size
Definition: c.h:466
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796

◆ ReorderBufferGetTupleBuf()

ReorderBufferTupleBuf* ReorderBufferGetTupleBuf ( ReorderBuffer ,
Size  tuple_len 
)

Definition at line 433 of file reorderbuffer.c.

References ReorderBufferTupleBuf::alloc_tuple_size, MemoryContextAlloc(), ReorderBufferTupleBufData, SizeofHeapTupleHeader, HeapTupleData::t_data, ReorderBuffer::tup_context, and ReorderBufferTupleBuf::tuple.

Referenced by DecodeDelete(), DecodeInsert(), DecodeMultiInsert(), DecodeUpdate(), and ReorderBufferRestoreChange().

434 {
435  ReorderBufferTupleBuf *tuple;
436  Size alloc_len;
437 
438  alloc_len = tuple_len + SizeofHeapTupleHeader;
439 
440  tuple = (ReorderBufferTupleBuf *)
441  MemoryContextAlloc(rb->tup_context,
442  sizeof(ReorderBufferTupleBuf) +
443  MAXIMUM_ALIGNOF + alloc_len);
444  tuple->alloc_tuple_size = alloc_len;
445  tuple->tuple.t_data = ReorderBufferTupleBufData(tuple);
446 
447  return tuple;
448 }
#define SizeofHeapTupleHeader
Definition: htup_details.h:184
HeapTupleHeader t_data
Definition: htup.h:68
#define ReorderBufferTupleBufData(p)
Definition: reorderbuffer.h:36
HeapTupleData tuple
Definition: reorderbuffer.h:27
size_t Size
Definition: c.h:466
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796

◆ ReorderBufferImmediateInvalidation()

void ReorderBufferImmediateInvalidation ( ReorderBuffer ,
uint32  ninvalidations,
SharedInvalidationMessage invalidations 
)

Definition at line 1976 of file reorderbuffer.c.

References AbortCurrentTransaction(), BeginInternalSubTransaction(), i, IsTransactionOrTransactionBlock(), LocalExecuteInvalidationMessage(), and RollbackAndReleaseCurrentSubTransaction().

Referenced by DecodeStandbyOp(), and ReorderBufferForget().

1978 {
1979  bool use_subtxn = IsTransactionOrTransactionBlock();
1980  int i;
1981 
1982  if (use_subtxn)
1983  BeginInternalSubTransaction("replay");
1984 
1985  /*
1986  * Force invalidations to happen outside of a valid transaction - that way
1987  * entries will just be marked as invalid without accessing the catalog.
1988  * That's advantageous because we don't need to setup the full state
1989  * necessary for catalog access.
1990  */
1991  if (use_subtxn)
1993 
1994  for (i = 0; i < ninvalidations; i++)
1995  LocalExecuteInvalidationMessage(&invalidations[i]);
1996 
1997  if (use_subtxn)
1999 }
void AbortCurrentTransaction(void)
Definition: xact.c:3159
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4651
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4462
void BeginInternalSubTransaction(const char *name)
Definition: xact.c:4357
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:556
int i

◆ ReorderBufferProcessXid()

void ReorderBufferProcessXid ( ReorderBuffer ,
TransactionId  xid,
XLogRecPtr  lsn 
)

Definition at line 2012 of file reorderbuffer.c.

References InvalidTransactionId, and ReorderBufferTXNByXid().

Referenced by DecodeHeap2Op(), DecodeHeapOp(), DecodeLogicalMsgOp(), DecodeStandbyOp(), DecodeXactOp(), DecodeXLogOp(), and LogicalDecodingProcessRecord().

2013 {
2014  /* many records won't have an xid assigned, centralize check here */
2015  if (xid != InvalidTransactionId)
2016  ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
2017 }
#define InvalidTransactionId
Definition: transam.h:31
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ ReorderBufferQueueChange()

void ReorderBufferQueueChange ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
ReorderBufferChange  
)

Definition at line 580 of file reorderbuffer.c.

References Assert, ReorderBufferTXN::changes, dlist_push_tail(), InvalidXLogRecPtr, ReorderBufferChange::lsn, ReorderBufferTXN::nentries, ReorderBufferTXN::nentries_mem, ReorderBufferChange::node, ReorderBufferCheckSerializeTXN(), ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeDelete(), DecodeInsert(), DecodeMultiInsert(), DecodeSpecConfirm(), DecodeTruncate(), DecodeUpdate(), ReorderBufferAddNewCommandId(), ReorderBufferAddSnapshot(), and ReorderBufferQueueMessage().

582 {
583  ReorderBufferTXN *txn;
584 
585  txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
586 
587  change->lsn = lsn;
588  Assert(InvalidXLogRecPtr != lsn);
589  dlist_push_tail(&txn->changes, &change->node);
590  txn->nentries++;
591  txn->nentries_mem++;
592 
594 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
dlist_head changes
#define Assert(condition)
Definition: c.h:732
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
static void ReorderBufferCheckSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)

◆ ReorderBufferQueueMessage()

void ReorderBufferQueueMessage ( ReorderBuffer ,
TransactionId  ,
Snapshot  snapshot,
XLogRecPtr  lsn,
bool  transactional,
const char *  prefix,
Size  message_size,
const char *  message 
)

Definition at line 600 of file reorderbuffer.c.

References ReorderBufferChange::action, Assert, ReorderBuffer::context, ReorderBufferChange::data, InvalidTransactionId, MemoryContextSwitchTo(), ReorderBuffer::message, ReorderBufferChange::msg, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pstrdup(), REORDER_BUFFER_CHANGE_MESSAGE, ReorderBufferGetChange(), ReorderBufferQueueChange(), ReorderBufferTXNByXid(), SetupHistoricSnapshot(), TeardownHistoricSnapshot(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeLogicalMsgOp().

604 {
605  if (transactional)
606  {
607  MemoryContext oldcontext;
608  ReorderBufferChange *change;
609 
611 
612  oldcontext = MemoryContextSwitchTo(rb->context);
613 
614  change = ReorderBufferGetChange(rb);
616  change->data.msg.prefix = pstrdup(prefix);
617  change->data.msg.message_size = message_size;
618  change->data.msg.message = palloc(message_size);
619  memcpy(change->data.msg.message, message, message_size);
620 
621  ReorderBufferQueueChange(rb, xid, lsn, change);
622 
623  MemoryContextSwitchTo(oldcontext);
624  }
625  else
626  {
627  ReorderBufferTXN *txn = NULL;
628  volatile Snapshot snapshot_now = snapshot;
629 
630  if (xid != InvalidTransactionId)
631  txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
632 
633  /* setup snapshot to allow catalog access */
634  SetupHistoricSnapshot(snapshot_now, NULL);
635  PG_TRY();
636  {
637  rb->message(rb, txn, lsn, false, prefix, message_size, message);
638 
640  }
641  PG_CATCH();
642  {
644  PG_RE_THROW();
645  }
646  PG_END_TRY();
647  }
648 }
struct ReorderBufferChange::@101::@104 msg
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void TeardownHistoricSnapshot(bool is_error)
Definition: snapmgr.c:2051
ReorderBufferChange * ReorderBufferGetChange(ReorderBuffer *rb)
enum ReorderBufferChangeType action
Definition: reorderbuffer.h:78
#define InvalidTransactionId
Definition: transam.h:31
#define PG_CATCH()
Definition: elog.h:310
#define Assert(condition)
Definition: c.h:732
union ReorderBufferChange::@101 data
#define PG_RE_THROW()
Definition: elog.h:331
void ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, ReorderBufferChange *change)
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
void * palloc(Size size)
Definition: mcxt.c:949
void SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
Definition: snapmgr.c:2035
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317

◆ ReorderBufferReturnChange()

void ReorderBufferReturnChange ( ReorderBuffer ,
ReorderBufferChange  
)

Definition at line 375 of file reorderbuffer.c.

References ReorderBufferChange::action, ReorderBufferChange::data, ReorderBufferChange::msg, pfree(), REORDER_BUFFER_CHANGE_DELETE, REORDER_BUFFER_CHANGE_INSERT, REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID, REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT, REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM, REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT, REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID, REORDER_BUFFER_CHANGE_MESSAGE, REORDER_BUFFER_CHANGE_TRUNCATE, REORDER_BUFFER_CHANGE_UPDATE, ReorderBufferFreeSnap(), ReorderBufferReturnRelids(), ReorderBufferReturnTupleBuf(), ReorderBufferChange::snapshot, ReorderBufferChange::tp, and ReorderBufferChange::truncate.

Referenced by ReorderBufferCleanupTXN(), ReorderBufferCommit(), ReorderBufferIterTXNFinish(), ReorderBufferIterTXNNext(), ReorderBufferRestoreChanges(), ReorderBufferSerializeTXN(), and ReorderBufferToastReset().

376 {
377  /* free contained data */
378  switch (change->action)
379  {
384  if (change->data.tp.newtuple)
385  {
386  ReorderBufferReturnTupleBuf(rb, change->data.tp.newtuple);
387  change->data.tp.newtuple = NULL;
388  }
389 
390  if (change->data.tp.oldtuple)
391  {
392  ReorderBufferReturnTupleBuf(rb, change->data.tp.oldtuple);
393  change->data.tp.oldtuple = NULL;
394  }
395  break;
397  if (change->data.msg.prefix != NULL)
398  pfree(change->data.msg.prefix);
399  change->data.msg.prefix = NULL;
400  if (change->data.msg.message != NULL)
401  pfree(change->data.msg.message);
402  change->data.msg.message = NULL;
403  break;
405  if (change->data.snapshot)
406  {
407  ReorderBufferFreeSnap(rb, change->data.snapshot);
408  change->data.snapshot = NULL;
409  }
410  break;
411  /* no data in addition to the struct itself */
413  if (change->data.truncate.relids != NULL)
414  {
415  ReorderBufferReturnRelids(rb, change->data.truncate.relids);
416  change->data.truncate.relids = NULL;
417  }
418  break;
422  break;
423  }
424 
425  pfree(change);
426 }
void pfree(void *pointer)
Definition: mcxt.c:1056
void ReorderBufferReturnRelids(ReorderBuffer *rb, Oid *relids)
void ReorderBufferReturnTupleBuf(ReorderBuffer *rb, ReorderBufferTupleBuf *tuple)
static void ReorderBufferFreeSnap(ReorderBuffer *rb, Snapshot snap)

◆ ReorderBufferReturnRelids()

void ReorderBufferReturnRelids ( ReorderBuffer ,
Oid relids 
)

Definition at line 485 of file reorderbuffer.c.

References pfree().

Referenced by ReorderBufferReturnChange().

486 {
487  pfree(relids);
488 }
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ ReorderBufferReturnTupleBuf()

void ReorderBufferReturnTupleBuf ( ReorderBuffer ,
ReorderBufferTupleBuf tuple 
)

Definition at line 454 of file reorderbuffer.c.

References pfree().

Referenced by ReorderBufferReturnChange().

455 {
456  pfree(tuple);
457 }
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ ReorderBufferSetBaseSnapshot()

void ReorderBufferSetBaseSnapshot ( ReorderBuffer ,
TransactionId  ,
XLogRecPtr  lsn,
struct SnapshotData snap 
)

◆ ReorderBufferSetRestartPoint()

void ReorderBufferSetRestartPoint ( ReorderBuffer ,
XLogRecPtr  ptr 
)

Definition at line 758 of file reorderbuffer.c.

References ReorderBuffer::current_restart_decoding_lsn.

Referenced by SnapBuildRestore(), and SnapBuildSerialize().

759 {
760  rb->current_restart_decoding_lsn = ptr;
761 }

◆ ReorderBufferXidHasBaseSnapshot()

bool ReorderBufferXidHasBaseSnapshot ( ReorderBuffer ,
TransactionId  xid 
)

Definition at line 2188 of file reorderbuffer.c.

References ReorderBufferTXN::base_snapshot, InvalidXLogRecPtr, ReorderBufferTXN::is_known_as_subxact, ReorderBufferTXNByXid(), ReorderBufferTXN::toplevel_xid, and ReorderBufferTXNByIdEnt::txn.

Referenced by SnapBuildCommitTxn(), SnapBuildDistributeNewCatalogSnapshot(), and SnapBuildProcessChange().

2189 {
2190  ReorderBufferTXN *txn;
2191 
2192  txn = ReorderBufferTXNByXid(rb, xid, false,
2193  NULL, InvalidXLogRecPtr, false);
2194 
2195  /* transaction isn't known yet, ergo no snapshot */
2196  if (txn == NULL)
2197  return false;
2198 
2199  /* a known subtxn? operate on top-level txn instead */
2200  if (txn->is_known_as_subxact)
2201  txn = ReorderBufferTXNByXid(rb, txn->toplevel_xid, false,
2202  NULL, InvalidXLogRecPtr, false);
2203 
2204  return txn->base_snapshot != NULL;
2205 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
Snapshot base_snapshot
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)
TransactionId toplevel_xid

◆ ReorderBufferXidHasCatalogChanges()

bool ReorderBufferXidHasCatalogChanges ( ReorderBuffer ,
TransactionId  xid 
)

Definition at line 2171 of file reorderbuffer.c.

References ReorderBufferTXN::has_catalog_changes, InvalidXLogRecPtr, ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by SnapBuildCommitTxn().

2172 {
2173  ReorderBufferTXN *txn;
2174 
2175  txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
2176  false);
2177  if (txn == NULL)
2178  return false;
2179 
2180  return txn->has_catalog_changes;
2181 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ ReorderBufferXidSetCatalogChanges()

void ReorderBufferXidSetCatalogChanges ( ReorderBuffer ,
TransactionId  xid,
XLogRecPtr  lsn 
)

Definition at line 2156 of file reorderbuffer.c.

References ReorderBufferTXN::has_catalog_changes, ReorderBufferTXNByXid(), and ReorderBufferTXNByIdEnt::txn.

Referenced by DecodeCommit(), DecodeHeapOp(), and SnapBuildProcessNewCid().

2158 {
2159  ReorderBufferTXN *txn;
2160 
2161  txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
2162 
2163  txn->has_catalog_changes = true;
2164 }
static ReorderBufferTXN * ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top)

◆ StartupReorderBuffer()

void StartupReorderBuffer ( void  )

Definition at line 2880 of file reorderbuffer.c.

References AllocateDir(), dirent::d_name, DEBUG2, FreeDir(), ReadDir(), ReorderBufferCleanupSerializedTXNs(), and ReplicationSlotValidateName().

Referenced by StartupXLOG().

2881 {
2882  DIR *logical_dir;
2883  struct dirent *logical_de;
2884 
2885  logical_dir = AllocateDir("pg_replslot");
2886  while ((logical_de = ReadDir(logical_dir, "pg_replslot")) != NULL)
2887  {
2888  if (strcmp(logical_de->d_name, ".") == 0 ||
2889  strcmp(logical_de->d_name, "..") == 0)
2890  continue;
2891 
2892  /* if it cannot be a slot, skip the directory */
2893  if (!ReplicationSlotValidateName(logical_de->d_name, DEBUG2))
2894  continue;
2895 
2896  /*
2897  * ok, has to be a surviving logical slot, iterate and delete
2898  * everything starting with xid-*
2899  */
2901  }
2902  FreeDir(logical_dir);
2903 }
Definition: dirent.h:9
bool ReplicationSlotValidateName(const char *name, int elevel)
Definition: slot.c:174
Definition: dirent.c:25
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2466
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2532
char d_name[MAX_PATH]
Definition: dirent.h:14
static void ReorderBufferCleanupSerializedTXNs(const char *slotname)
int FreeDir(DIR *dir)
Definition: fd.c:2584