PostgreSQL Source Code  git master
time_mapping.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * time_mapping.c
4  * time to XID mapping information
5  *
6  * Copyright (c) 2020-2021, PostgreSQL Global Development Group
7  *
8  * contrib/old_snapshot/time_mapping.c
9  *-------------------------------------------------------------------------
10  */
11 #include "postgres.h"
12 
13 #include "funcapi.h"
14 #include "storage/lwlock.h"
15 #include "utils/old_snapshot.h"
16 #include "utils/snapmgr.h"
17 #include "utils/timestamp.h"
18 
19 /*
20  * Backend-private copy of the information from oldSnapshotControl which relates
21  * to the time to XID mapping, plus an index so that we can iterate.
22  *
23  * Note that the length of the xid_by_minute array is given by
24  * OLD_SNAPSHOT_TIME_MAP_ENTRIES (which is not a compile-time constant).
25  */
26 typedef struct
27 {
34 
35 #define NUM_TIME_MAPPING_COLUMNS 3
36 
39 
43  OldSnapshotTimeMapping *mapping);
44 
45 /*
46  * SQL-callable set-returning function.
47  */
48 Datum
50 {
51  FuncCallContext *funcctx;
52  OldSnapshotTimeMapping *mapping;
53 
54  if (SRF_IS_FIRSTCALL())
55  {
56  MemoryContext oldcontext;
57 
58  funcctx = SRF_FIRSTCALL_INIT();
59  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
60  mapping = GetOldSnapshotTimeMapping();
61  funcctx->user_fctx = mapping;
63  MemoryContextSwitchTo(oldcontext);
64  }
65 
66  funcctx = SRF_PERCALL_SETUP();
67  mapping = (OldSnapshotTimeMapping *) funcctx->user_fctx;
68 
69  while (mapping->current_index < mapping->count_used)
70  {
71  HeapTuple tuple;
72 
73  tuple = MakeOldSnapshotTimeMappingTuple(funcctx->tuple_desc, mapping);
74  ++mapping->current_index;
75  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
76  }
77 
78  SRF_RETURN_DONE(funcctx);
79 }
80 
81 /*
82  * Get the old snapshot time mapping data from shared memory.
83  */
86 {
87  OldSnapshotTimeMapping *mapping;
88 
89  mapping = palloc(offsetof(OldSnapshotTimeMapping, xid_by_minute)
91  mapping->current_index = 0;
92 
93  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
97  for (int i = 0; i < OLD_SNAPSHOT_TIME_MAP_ENTRIES; ++i)
99  LWLockRelease(OldSnapshotTimeMapLock);
100 
101  return mapping;
102 }
103 
104 /*
105  * Build a tuple descriptor for the pg_old_snapshot_time_mapping() SRF.
106  */
107 static TupleDesc
109 {
110  TupleDesc tupdesc;
111 
113 
114  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "array_offset",
115  INT4OID, -1, 0);
116  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "end_timestamp",
117  TIMESTAMPTZOID, -1, 0);
118  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "newest_xmin",
119  XIDOID, -1, 0);
120 
121  return BlessTupleDesc(tupdesc);
122 }
123 
124 /*
125  * Convert one entry from the old snapshot time mapping to a HeapTuple.
126  */
127 static HeapTuple
129 {
131  bool nulls[NUM_TIME_MAPPING_COLUMNS];
132  int array_position;
134 
135  /*
136  * Figure out the array position corresponding to the current index.
137  *
138  * Index 0 means the oldest entry in the mapping, which is stored at
139  * mapping->head_offset. Index 1 means the next-oldest entry, which is a
140  * the following index, and so on. We wrap around when we reach the end of
141  * the array.
142  */
143  array_position = (mapping->head_offset + mapping->current_index)
145 
146  /*
147  * No explicit timestamp is stored for any entry other than the oldest
148  * one, but each entry corresponds to 1-minute period, so we can just add.
149  */
150  timestamp = TimestampTzPlusMilliseconds(mapping->head_timestamp,
151  mapping->current_index * 60000);
152 
153  /* Initialize nulls and values arrays. */
154  memset(nulls, 0, sizeof(nulls));
155  values[0] = Int32GetDatum(array_position);
156  values[1] = TimestampTzGetDatum(timestamp);
157  values[2] = TransactionIdGetDatum(mapping->xid_by_minute[array_position]);
158 
159  return heap_form_tuple(tupdesc, values, nulls);
160 }
static OldSnapshotTimeMapping * GetOldSnapshotTimeMapping(void)
Definition: time_mapping.c:85
PG_FUNCTION_INFO_V1(pg_old_snapshot_time_mapping)
uint32 TransactionId
Definition: c.h:587
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
int64 timestamp
int64 TimestampTz
Definition: timestamp.h:39
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:350
static TupleDesc MakeOldSnapshotTimeMappingTupleDesc(void)
Definition: time_mapping.c:108
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
TupleDesc tuple_desc
Definition: funcapi.h:112
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1816
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
Datum pg_old_snapshot_time_mapping(PG_FUNCTION_ARGS)
Definition: time_mapping.c:49
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
Datum array_position(PG_FUNCTION_ARGS)
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:580
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: time_mapping.c:32
#define TransactionIdGetDatum(X)
Definition: postgres.h:565
uintptr_t Datum
Definition: postgres.h:411
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
TimestampTz head_timestamp
Definition: time_mapping.c:30
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:1062
#define NUM_TIME_MAPPING_COLUMNS
Definition: time_mapping.c:35
TimestampTz head_timestamp
Definition: old_snapshot.h:68
int i
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
int16 AttrNumber
Definition: attnum.h:21
#define offsetof(type, field)
Definition: c.h:727
PG_MODULE_MAGIC
Definition: time_mapping.c:37
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
static HeapTuple MakeOldSnapshotTimeMappingTuple(TupleDesc tupdesc, OldSnapshotTimeMapping *mapping)
Definition: time_mapping.c:128
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296