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)
 

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)
 
bool InjectionPointDetach (const char *name)
 

Macro Definition Documentation

◆ INJECTION_POINT

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

Definition at line 22 of file injection_point.h.

◆ INJECTION_POINT_LOAD

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

Definition at line 21 of file injection_point.h.

Typedef Documentation

◆ InjectionPointCallback

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

Definition at line 28 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 
319  if (strcmp(entry->name, name) == 0)
320  elog(ERROR, "injection point \"%s\" already defined", name);
321  }
322  if (free_idx == -1)
323  {
324  if (max_inuse == MAX_INJECTION_POINTS)
325  elog(ERROR, "too many injection points");
326  free_idx = max_inuse;
327  }
328  entry = &ActiveInjectionPoints->entries[free_idx];
329  generation = pg_atomic_read_u64(&entry->generation);
330  Assert(generation % 2 == 0);
331 
332  /* Save the entry */
333  strlcpy(entry->name, name, sizeof(entry->name));
334  entry->name[INJ_NAME_MAXLEN - 1] = '\0';
335  strlcpy(entry->library, library, sizeof(entry->library));
336  entry->library[INJ_LIB_MAXLEN - 1] = '\0';
337  strlcpy(entry->function, function, sizeof(entry->function));
338  entry->function[INJ_FUNC_MAXLEN - 1] = '\0';
339  if (private_data != NULL)
340  memcpy(entry->private_data, private_data, private_data_size);
341 
343  pg_atomic_write_u64(&entry->generation, generation + 1);
344 
345  if (free_idx + 1 > max_inuse)
346  pg_atomic_write_u32(&ActiveInjectionPoints->max_inuse, free_idx + 1);
347 
348  LWLockRelease(InjectionPointLock);
349 
350 #else
351  elog(ERROR, "injection points are not supported by this build");
352 #endif
353 }
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:478
#define pg_write_barrier()
Definition: atomics.h:150
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:269
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:232
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:460
unsigned int uint32
Definition: c.h:506
#define Assert(condition)
Definition: c.h:858
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#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().

◆ InjectionPointDetach()

bool InjectionPointDetach ( const char *  name)

Definition at line 361 of file injection_point.c.

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

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 531 of file injection_point.c.

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

References elog, ERROR, and name.

◆ InjectionPointRun()

void InjectionPointRun ( const char *  name)

Definition at line 544 of file injection_point.c.

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

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:214
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:446
bool IsUnderPostmaster
Definition: globals.c:118
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:605
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size().

Referenced by CalculateShmemSize().