PostgreSQL Source Code  git master
injection_point.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define INJECTION_POINT_LOAD(name)   ((void) name)
 
#define INJECTION_POINT(name)   ((void) name)
 
#define INJECTION_POINT_CACHED(name)   ((void) name)
 
#define IS_INJECTION_POINT_ATTACHED(name)   (false)
 

Typedefs

typedef void(* InjectionPointCallback) (const char *name, const void *private_data)
 

Functions

Size InjectionPointShmemSize (void)
 
void InjectionPointShmemInit (void)
 
void InjectionPointAttach (const char *name, const char *library, const char *function, const void *private_data, int private_data_size)
 
void InjectionPointLoad (const char *name)
 
void InjectionPointRun (const char *name)
 
void InjectionPointCached (const char *name)
 
bool IsInjectionPointAttached (const char *name)
 
bool InjectionPointDetach (const char *name)
 

Macro Definition Documentation

◆ INJECTION_POINT

#define INJECTION_POINT (   name)    ((void) name)

Definition at line 24 of file injection_point.h.

◆ INJECTION_POINT_CACHED

#define INJECTION_POINT_CACHED (   name)    ((void) name)

Definition at line 25 of file injection_point.h.

◆ INJECTION_POINT_LOAD

#define INJECTION_POINT_LOAD (   name)    ((void) name)

Definition at line 23 of file injection_point.h.

◆ IS_INJECTION_POINT_ATTACHED

#define IS_INJECTION_POINT_ATTACHED (   name)    (false)

Definition at line 26 of file injection_point.h.

Typedef Documentation

◆ InjectionPointCallback

typedef void(* InjectionPointCallback) (const char *name, const void *private_data)

Definition at line 32 of file injection_point.h.

Function Documentation

◆ InjectionPointAttach()

void InjectionPointAttach ( const char *  name,
const char *  library,
const char *  function,
const void *  private_data,
int  private_data_size 
)

Definition at line 272 of file injection_point.c.

277 {
278 #ifdef USE_INJECTION_POINTS
279  InjectionPointEntry *entry;
280  uint64 generation;
281  uint32 max_inuse;
282  int free_idx;
283 
284  if (strlen(name) >= INJ_NAME_MAXLEN)
285  elog(ERROR, "injection point name %s too long (maximum of %u)",
287  if (strlen(library) >= INJ_LIB_MAXLEN)
288  elog(ERROR, "injection point library %s too long (maximum of %u)",
289  library, INJ_LIB_MAXLEN);
290  if (strlen(function) >= INJ_FUNC_MAXLEN)
291  elog(ERROR, "injection point function %s too long (maximum of %u)",
292  function, INJ_FUNC_MAXLEN);
293  if (private_data_size >= INJ_PRIVATE_MAXLEN)
294  elog(ERROR, "injection point data too long (maximum of %u)",
295  INJ_PRIVATE_MAXLEN);
296 
297  /*
298  * Allocate and register a new injection point. A new point should not
299  * exist. For testing purposes this should be fine.
300  */
301  LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE);
302  max_inuse = pg_atomic_read_u32(&ActiveInjectionPoints->max_inuse);
303  free_idx = -1;
304 
305  for (int idx = 0; idx < max_inuse; idx++)
306  {
307  entry = &ActiveInjectionPoints->entries[idx];
308  generation = pg_atomic_read_u64(&entry->generation);
309  if (generation % 2 == 0)
310  {
311  /*
312  * Found a free slot where we can add the new entry, but keep
313  * going so that we will find out if the entry already exists.
314  */
315  if (free_idx == -1)
316  free_idx = idx;
317  }
318  else if (strcmp(entry->name, name) == 0)
319  elog(ERROR, "injection point \"%s\" already defined", name);
320  }
321  if (free_idx == -1)
322  {
323  if (max_inuse == MAX_INJECTION_POINTS)
324  elog(ERROR, "too many injection points");
325  free_idx = max_inuse;
326  }
327  entry = &ActiveInjectionPoints->entries[free_idx];
328  generation = pg_atomic_read_u64(&entry->generation);
329  Assert(generation % 2 == 0);
330 
331  /* Save the entry */
332  strlcpy(entry->name, name, sizeof(entry->name));
333  entry->name[INJ_NAME_MAXLEN - 1] = '\0';
334  strlcpy(entry->library, library, sizeof(entry->library));
335  entry->library[INJ_LIB_MAXLEN - 1] = '\0';
336  strlcpy(entry->function, function, sizeof(entry->function));
337  entry->function[INJ_FUNC_MAXLEN - 1] = '\0';
338  if (private_data != NULL)
339  memcpy(entry->private_data, private_data, private_data_size);
340 
342  pg_atomic_write_u64(&entry->generation, generation + 1);
343 
344  if (free_idx + 1 > max_inuse)
345  pg_atomic_write_u32(&ActiveInjectionPoints->max_inuse, free_idx + 1);
346 
347  LWLockRelease(InjectionPointLock);
348 
349 #else
350  elog(ERROR, "injection points are not supported by this build");
351 #endif
352 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:485
#define pg_write_barrier()
Definition: atomics.h:157
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:276
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:467
unsigned int uint32
Definition: c.h:509
#define Assert(condition)
Definition: c.h:861
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define INJ_NAME_MAXLEN
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * name

References Assert, elog, ERROR, idx(), INJ_NAME_MAXLEN, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), name, pg_atomic_read_u32(), pg_atomic_read_u64(), pg_atomic_write_u32(), pg_atomic_write_u64(), pg_write_barrier, and strlcpy().

Referenced by injection_points_attach().

◆ InjectionPointCached()

void InjectionPointCached ( const char *  name)

Definition at line 560 of file injection_point.c.

561 {
562 #ifdef USE_INJECTION_POINTS
563  InjectionPointCacheEntry *cache_entry;
564 
565  cache_entry = injection_point_cache_get(name);
566  if (cache_entry)
567  cache_entry->callback(name, cache_entry->private_data);
568 #else
569  elog(ERROR, "Injection points are not supported by this build");
570 #endif
571 }

References elog, ERROR, and name.

◆ InjectionPointDetach()

bool InjectionPointDetach ( const char *  name)

Definition at line 360 of file injection_point.c.

361 {
362 #ifdef USE_INJECTION_POINTS
363  bool found = false;
364  int idx;
365  int max_inuse;
366 
367  LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE);
368 
369  /* Find it in the shmem array, and mark the slot as unused */
370  max_inuse = (int) pg_atomic_read_u32(&ActiveInjectionPoints->max_inuse);
371  for (idx = max_inuse - 1; idx >= 0; --idx)
372  {
373  InjectionPointEntry *entry = &ActiveInjectionPoints->entries[idx];
374  uint64 generation;
375 
376  generation = pg_atomic_read_u64(&entry->generation);
377  if (generation % 2 == 0)
378  continue; /* empty slot */
379 
380  if (strcmp(entry->name, name) == 0)
381  {
382  Assert(!found);
383  found = true;
384  pg_atomic_write_u64(&entry->generation, generation + 1);
385  break;
386  }
387  }
388 
389  /* If we just removed the highest-numbered entry, update 'max_inuse' */
390  if (found && idx == max_inuse - 1)
391  {
392  for (; idx >= 0; --idx)
393  {
394  InjectionPointEntry *entry = &ActiveInjectionPoints->entries[idx];
395  uint64 generation;
396 
397  generation = pg_atomic_read_u64(&entry->generation);
398  if (generation % 2 != 0)
399  break;
400  }
401  pg_atomic_write_u32(&ActiveInjectionPoints->max_inuse, idx + 1);
402  }
403  LWLockRelease(InjectionPointLock);
404 
405  return found;
406 #else
407  elog(ERROR, "Injection points are not supported by this build");
408  return true; /* silence compiler */
409 #endif
410 }

References Assert, elog, ERROR, idx(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), name, pg_atomic_read_u32(), pg_atomic_read_u64(), pg_atomic_write_u32(), and pg_atomic_write_u64().

Referenced by injection_points_cleanup(), and injection_points_detach().

◆ InjectionPointLoad()

void InjectionPointLoad ( const char *  name)

Definition at line 530 of file injection_point.c.

531 {
532 #ifdef USE_INJECTION_POINTS
533  InjectionPointCacheRefresh(name);
534 #else
535  elog(ERROR, "Injection points are not supported by this build");
536 #endif
537 }

References elog, ERROR, and name.

◆ InjectionPointRun()

void InjectionPointRun ( const char *  name)

Definition at line 543 of file injection_point.c.

544 {
545 #ifdef USE_INJECTION_POINTS
546  InjectionPointCacheEntry *cache_entry;
547 
548  cache_entry = InjectionPointCacheRefresh(name);
549  if (cache_entry)
550  cache_entry->callback(name, cache_entry->private_data);
551 #else
552  elog(ERROR, "Injection points are not supported by this build");
553 #endif
554 }

References elog, ERROR, and name.

◆ InjectionPointShmemInit()

void InjectionPointShmemInit ( void  )

Definition at line 248 of file injection_point.c.

249 {
250 #ifdef USE_INJECTION_POINTS
251  bool found;
252 
253  ActiveInjectionPoints = ShmemInitStruct("InjectionPoint hash",
254  sizeof(InjectionPointsCtl),
255  &found);
256  if (!IsUnderPostmaster)
257  {
258  Assert(!found);
259  pg_atomic_init_u32(&ActiveInjectionPoints->max_inuse, 0);
260  for (int i = 0; i < MAX_INJECTION_POINTS; i++)
261  pg_atomic_init_u64(&ActiveInjectionPoints->entries[i].generation, 0);
262  }
263  else
264  Assert(found);
265 #endif
266 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:453
bool IsUnderPostmaster
Definition: globals.c:119
int i
Definition: isn.c:73
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387

References Assert, i, IsUnderPostmaster, pg_atomic_init_u32(), pg_atomic_init_u64(), and ShmemInitStruct().

Referenced by CreateOrAttachShmemStructs().

◆ InjectionPointShmemSize()

Size InjectionPointShmemSize ( void  )

Definition at line 232 of file injection_point.c.

233 {
234 #ifdef USE_INJECTION_POINTS
235  Size sz = 0;
236 
237  sz = add_size(sz, sizeof(InjectionPointsCtl));
238  return sz;
239 #else
240  return 0;
241 #endif
242 }
size_t Size
Definition: c.h:608
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size().

Referenced by CalculateShmemSize().

◆ IsInjectionPointAttached()

bool IsInjectionPointAttached ( const char *  name)

Definition at line 577 of file injection_point.c.

578 {
579 #ifdef USE_INJECTION_POINTS
580  return InjectionPointCacheRefresh(name) != NULL;
581 #else
582  elog(ERROR, "Injection points are not supported by this build");
583  return false; /* silence compiler */
584 #endif
585 }

References elog, ERROR, and name.