PostgreSQL Source Code  git master
evtcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "catalog/indexing.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "tcop/cmdtag.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/evtcache.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for evtcache.c:

Go to the source code of this file.

Data Structures

struct  EventTriggerCacheEntry
 

Enumerations

enum  EventTriggerCacheStateType { ETCS_NEEDS_REBUILD, ETCS_REBUILD_STARTED, ETCS_VALID }
 

Functions

static void BuildEventTriggerCache (void)
 
static void InvalidateEventCacheCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static BitmapsetDecodeTextArrayToBitmapset (Datum array)
 
ListEventCacheLookup (EventTriggerEvent event)
 

Variables

static HTABEventTriggerCache
 
static MemoryContext EventTriggerCacheContext
 
static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
 

Enumeration Type Documentation

◆ EventTriggerCacheStateType

Enumerator
ETCS_NEEDS_REBUILD 
ETCS_REBUILD_STARTED 
ETCS_VALID 

Definition at line 35 of file evtcache.c.

Function Documentation

◆ BuildEventTriggerCache()

static void BuildEventTriggerCache ( void  )
static

Definition at line 79 of file evtcache.c.

References AccessShareLock, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), DecodeTextArrayToBitmapset(), EventTriggerCacheItem::enabled, HASHCTL::entrysize, ETCS_REBUILD_STARTED, ETCS_VALID, EventTriggerCacheContext, EventTriggerCacheState, EventTriggerNameIndexId, EVENTTRIGGEROID, EVT_DDLCommandEnd, EVT_DDLCommandStart, EVT_SQLDrop, EVT_TableRewrite, EventTriggerCacheItem::fnoid, ForwardScanDirection, GETSTRUCT, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::hcxt, heap_getattr, HeapTupleIsValid, index_close(), index_open(), InvalidateEventCacheCallback(), HASHCTL::keysize, lappend(), list_make1, MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), MemSet, NameStr, palloc0(), relation_close(), relation_open(), RelationGetDescr, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), EventTriggerCacheItem::tagset, TRIGGER_DISABLED, and EventTriggerCacheEntry::triggerlist.

Referenced by EventCacheLookup().

80 {
81  HASHCTL ctl;
82  HTAB *cache;
83  MemoryContext oldcontext;
84  Relation rel;
85  Relation irel;
86  SysScanDesc scan;
87 
88  if (EventTriggerCacheContext != NULL)
89  {
90  /*
91  * Free up any memory already allocated in EventTriggerCacheContext.
92  * This can happen either because a previous rebuild failed, or
93  * because an invalidation happened before the rebuild was complete.
94  */
96  }
97  else
98  {
99  /*
100  * This is our first time attempting to build the cache, so we need to
101  * set up the memory context and register a syscache callback to
102  * capture future invalidation events.
103  */
104  if (CacheMemoryContext == NULL)
108  "EventTriggerCache",
112  (Datum) 0);
113  }
114 
115  /* Switch to correct memory context. */
117 
118  /* Prevent the memory context from being nuked while we're rebuilding. */
120 
121  /* Create new hash table. */
122  MemSet(&ctl, 0, sizeof(ctl));
123  ctl.keysize = sizeof(EventTriggerEvent);
124  ctl.entrysize = sizeof(EventTriggerCacheEntry);
126  cache = hash_create("Event Trigger Cache", 32, &ctl,
128 
129  /*
130  * Prepare to scan pg_event_trigger in name order.
131  */
132  rel = relation_open(EventTriggerRelationId, AccessShareLock);
134  scan = systable_beginscan_ordered(rel, irel, NULL, 0, NULL);
135 
136  /*
137  * Build a cache item for each pg_event_trigger tuple, and append each one
138  * to the appropriate cache entry.
139  */
140  for (;;)
141  {
142  HeapTuple tup;
144  char *evtevent;
145  EventTriggerEvent event;
146  EventTriggerCacheItem *item;
147  Datum evttags;
148  bool evttags_isnull;
149  EventTriggerCacheEntry *entry;
150  bool found;
151 
152  /* Get next tuple. */
154  if (!HeapTupleIsValid(tup))
155  break;
156 
157  /* Skip trigger if disabled. */
158  form = (Form_pg_event_trigger) GETSTRUCT(tup);
159  if (form->evtenabled == TRIGGER_DISABLED)
160  continue;
161 
162  /* Decode event name. */
163  evtevent = NameStr(form->evtevent);
164  if (strcmp(evtevent, "ddl_command_start") == 0)
165  event = EVT_DDLCommandStart;
166  else if (strcmp(evtevent, "ddl_command_end") == 0)
167  event = EVT_DDLCommandEnd;
168  else if (strcmp(evtevent, "sql_drop") == 0)
169  event = EVT_SQLDrop;
170  else if (strcmp(evtevent, "table_rewrite") == 0)
171  event = EVT_TableRewrite;
172  else
173  continue;
174 
175  /* Allocate new cache item. */
176  item = palloc0(sizeof(EventTriggerCacheItem));
177  item->fnoid = form->evtfoid;
178  item->enabled = form->evtenabled;
179 
180  /* Decode and sort tags array. */
181  evttags = heap_getattr(tup, Anum_pg_event_trigger_evttags,
182  RelationGetDescr(rel), &evttags_isnull);
183  if (!evttags_isnull)
184  item->tagset = DecodeTextArrayToBitmapset(evttags);
185 
186  /* Add to cache entry. */
187  entry = hash_search(cache, &event, HASH_ENTER, &found);
188  if (found)
189  entry->triggerlist = lappend(entry->triggerlist, item);
190  else
191  entry->triggerlist = list_make1(item);
192  }
193 
194  /* Done with pg_event_trigger scan. */
198 
199  /* Restore previous memory context. */
200  MemoryContextSwitchTo(oldcontext);
201 
202  /* Install new cache. */
203  EventTriggerCache = cache;
204 
205  /*
206  * If the cache has been invalidated since we entered this routine, we
207  * still use and return the cache we just finished constructing, to avoid
208  * infinite loops, but we leave the cache marked stale so that we'll
209  * rebuild it again on next access. Otherwise, we mark the cache valid.
210  */
213 }
static void InvalidateEventCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: evtcache.c:257
#define AllocSetContextCreate
Definition: memutils.h:170
static HTAB * EventTriggerCache
Definition: evtcache.c:48
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
#define RelationGetDescr(relation)
Definition: rel.h:482
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Size entrysize
Definition: hsearch.h:73
static MemoryContext EventTriggerCacheContext
Definition: evtcache.c:49
#define MemSet(start, val, len)
Definition: c.h:949
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:681
EventTriggerEvent
Definition: evtcache.h:20
#define list_make1(x1)
Definition: pg_list.h:227
Definition: dynahash.c:220
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
static Bitmapset * DecodeTextArrayToBitmapset(Datum array)
Definition: evtcache.c:223
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:50
List * lappend(List *list, void *datum)
Definition: list.c:321
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
void * palloc0(Size size)
Definition: mcxt.c:980
#define TRIGGER_DISABLED
Definition: trigger.h:159
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:328
uintptr_t Datum
Definition: postgres.h:367
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:706
Size keysize
Definition: hsearch.h:72
FormData_pg_event_trigger * Form_pg_event_trigger
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define EventTriggerNameIndexId
Definition: indexing.h:263
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Bitmapset * tagset
Definition: evtcache.h:32
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:616
#define NameStr(name)
Definition: c.h:622
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ DecodeTextArrayToBitmapset()

static Bitmapset * DecodeTextArrayToBitmapset ( Datum  array)
static

Definition at line 223 of file evtcache.c.

References ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, bms_add_member(), DatumGetArrayTypeP, deconstruct_array(), elog, ERROR, GetCommandTagEnum(), i, pfree(), generate_unaccent_rules::str, and TextDatumGetCString.

Referenced by BuildEventTriggerCache().

224 {
225  ArrayType *arr = DatumGetArrayTypeP(array);
226  Datum *elems;
227  Bitmapset *bms;
228  int i;
229  int nelems;
230 
231  if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID)
232  elog(ERROR, "expected 1-D text array");
233  deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
234  &elems, NULL, &nelems);
235 
236  for (bms = NULL, i = 0; i < nelems; ++i)
237  {
238  char *str = TextDatumGetCString(elems[i]);
239 
240  bms = bms_add_member(bms, GetCommandTagEnum(str));
241  pfree(str);
242  }
243 
244  pfree(elems);
245 
246  return bms;
247 }
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define ARR_HASNULL(a)
Definition: array.h:279
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define ARR_NDIM(a)
Definition: array.h:278
CommandTag GetCommandTagEnum(const char *commandname)
Definition: cmdtag.c:74
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3483
#define elog(elevel,...)
Definition: elog.h:214
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ EventCacheLookup()

List* EventCacheLookup ( EventTriggerEvent  event)

Definition at line 65 of file evtcache.c.

References BuildEventTriggerCache(), ETCS_VALID, EventTriggerCacheState, HASH_FIND, hash_search(), NIL, and EventTriggerCacheEntry::triggerlist.

Referenced by EventTriggerCommonSetup(), and trackDroppedObjectsNeeded().

66 {
68 
71  entry = hash_search(EventTriggerCache, &event, HASH_FIND, NULL);
72  return entry != NULL ? entry->triggerlist : NIL;
73 }
#define NIL
Definition: pg_list.h:65
static HTAB * EventTriggerCache
Definition: evtcache.c:48
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static void BuildEventTriggerCache(void)
Definition: evtcache.c:79
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:50

◆ InvalidateEventCacheCallback()

static void InvalidateEventCacheCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 257 of file evtcache.c.

References ETCS_NEEDS_REBUILD, ETCS_VALID, EventTriggerCacheState, and MemoryContextResetAndDeleteChildren.

Referenced by BuildEventTriggerCache().

258 {
259  /*
260  * If the cache isn't valid, then there might be a rebuild in progress, so
261  * we can't immediately blow it away. But it's advantageous to do this
262  * when possible, so as to immediately free memory.
263  */
265  {
267  EventTriggerCache = NULL;
268  }
269 
270  /* Mark cache for rebuild. */
272 }
static HTAB * EventTriggerCache
Definition: evtcache.c:48
static MemoryContext EventTriggerCacheContext
Definition: evtcache.c:49
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:50
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67

Variable Documentation

◆ EventTriggerCache

HTAB* EventTriggerCache
static

Definition at line 48 of file evtcache.c.

◆ EventTriggerCacheContext

MemoryContext EventTriggerCacheContext
static

Definition at line 49 of file evtcache.c.

Referenced by BuildEventTriggerCache().

◆ EventTriggerCacheState

EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
static