LCOV - code coverage report
Current view: top level - contrib/old_snapshot - time_mapping.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 0 44 0.0 %
Date: 2021-12-03 04:09:03 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : {
      28             :     int         current_index;
      29             :     int         head_offset;
      30             :     TimestampTz head_timestamp;
      31             :     int         count_used;
      32             :     TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER];
      33             : } OldSnapshotTimeMapping;
      34             : 
      35             : #define NUM_TIME_MAPPING_COLUMNS 3
      36             : 
      37           0 : PG_MODULE_MAGIC;
      38           0 : PG_FUNCTION_INFO_V1(pg_old_snapshot_time_mapping);
      39             : 
      40             : static OldSnapshotTimeMapping *GetOldSnapshotTimeMapping(void);
      41             : static TupleDesc MakeOldSnapshotTimeMappingTupleDesc(void);
      42             : static HeapTuple MakeOldSnapshotTimeMappingTuple(TupleDesc tupdesc,
      43             :                                                  OldSnapshotTimeMapping *mapping);
      44             : 
      45             : /*
      46             :  * SQL-callable set-returning function.
      47             :  */
      48             : Datum
      49           0 : pg_old_snapshot_time_mapping(PG_FUNCTION_ARGS)
      50             : {
      51             :     FuncCallContext *funcctx;
      52             :     OldSnapshotTimeMapping *mapping;
      53             : 
      54           0 :     if (SRF_IS_FIRSTCALL())
      55             :     {
      56             :         MemoryContext oldcontext;
      57             : 
      58           0 :         funcctx = SRF_FIRSTCALL_INIT();
      59           0 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
      60           0 :         mapping = GetOldSnapshotTimeMapping();
      61           0 :         funcctx->user_fctx = mapping;
      62           0 :         funcctx->tuple_desc = MakeOldSnapshotTimeMappingTupleDesc();
      63           0 :         MemoryContextSwitchTo(oldcontext);
      64             :     }
      65             : 
      66           0 :     funcctx = SRF_PERCALL_SETUP();
      67           0 :     mapping = (OldSnapshotTimeMapping *) funcctx->user_fctx;
      68             : 
      69           0 :     while (mapping->current_index < mapping->count_used)
      70             :     {
      71             :         HeapTuple   tuple;
      72             : 
      73           0 :         tuple = MakeOldSnapshotTimeMappingTuple(funcctx->tuple_desc, mapping);
      74           0 :         ++mapping->current_index;
      75           0 :         SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
      76             :     }
      77             : 
      78           0 :     SRF_RETURN_DONE(funcctx);
      79             : }
      80             : 
      81             : /*
      82             :  * Get the old snapshot time mapping data from shared memory.
      83             :  */
      84             : static OldSnapshotTimeMapping *
      85           0 : GetOldSnapshotTimeMapping(void)
      86             : {
      87             :     OldSnapshotTimeMapping *mapping;
      88             : 
      89           0 :     mapping = palloc(offsetof(OldSnapshotTimeMapping, xid_by_minute)
      90           0 :                      + sizeof(TransactionId) * OLD_SNAPSHOT_TIME_MAP_ENTRIES);
      91           0 :     mapping->current_index = 0;
      92             : 
      93           0 :     LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
      94           0 :     mapping->head_offset = oldSnapshotControl->head_offset;
      95           0 :     mapping->head_timestamp = oldSnapshotControl->head_timestamp;
      96           0 :     mapping->count_used = oldSnapshotControl->count_used;
      97           0 :     for (int i = 0; i < OLD_SNAPSHOT_TIME_MAP_ENTRIES; ++i)
      98           0 :         mapping->xid_by_minute[i] = oldSnapshotControl->xid_by_minute[i];
      99           0 :     LWLockRelease(OldSnapshotTimeMapLock);
     100             : 
     101           0 :     return mapping;
     102             : }
     103             : 
     104             : /*
     105             :  * Build a tuple descriptor for the pg_old_snapshot_time_mapping() SRF.
     106             :  */
     107             : static TupleDesc
     108           0 : MakeOldSnapshotTimeMappingTupleDesc(void)
     109             : {
     110             :     TupleDesc   tupdesc;
     111             : 
     112           0 :     tupdesc = CreateTemplateTupleDesc(NUM_TIME_MAPPING_COLUMNS);
     113             : 
     114           0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "array_offset",
     115             :                        INT4OID, -1, 0);
     116           0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "end_timestamp",
     117             :                        TIMESTAMPTZOID, -1, 0);
     118           0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "newest_xmin",
     119             :                        XIDOID, -1, 0);
     120             : 
     121           0 :     return BlessTupleDesc(tupdesc);
     122             : }
     123             : 
     124             : /*
     125             :  * Convert one entry from the old snapshot time mapping to a HeapTuple.
     126             :  */
     127             : static HeapTuple
     128           0 : MakeOldSnapshotTimeMappingTuple(TupleDesc tupdesc, OldSnapshotTimeMapping *mapping)
     129             : {
     130             :     Datum       values[NUM_TIME_MAPPING_COLUMNS];
     131             :     bool        nulls[NUM_TIME_MAPPING_COLUMNS];
     132             :     int         array_position;
     133             :     TimestampTz timestamp;
     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           0 :     array_position = (mapping->head_offset + mapping->current_index)
     144           0 :         % OLD_SNAPSHOT_TIME_MAP_ENTRIES;
     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           0 :     timestamp = TimestampTzPlusMilliseconds(mapping->head_timestamp,
     151             :                                             mapping->current_index * 60000);
     152             : 
     153             :     /* Initialize nulls and values arrays. */
     154           0 :     memset(nulls, 0, sizeof(nulls));
     155           0 :     values[0] = Int32GetDatum(array_position);
     156           0 :     values[1] = TimestampTzGetDatum(timestamp);
     157           0 :     values[2] = TransactionIdGetDatum(mapping->xid_by_minute[array_position]);
     158             : 
     159           0 :     return heap_form_tuple(tupdesc, values, nulls);
     160             : }

Generated by: LCOV version 1.14