PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 273 of file injection_point.c.

278{
279#ifdef USE_INJECTION_POINTS
280 InjectionPointEntry *entry;
281 uint64 generation;
282 uint32 max_inuse;
283 int free_idx;
284
285 if (strlen(name) >= INJ_NAME_MAXLEN)
286 elog(ERROR, "injection point name %s too long (maximum of %u)",
288 if (strlen(library) >= INJ_LIB_MAXLEN)
289 elog(ERROR, "injection point library %s too long (maximum of %u)",
290 library, INJ_LIB_MAXLEN);
291 if (strlen(function) >= INJ_FUNC_MAXLEN)
292 elog(ERROR, "injection point function %s too long (maximum of %u)",
293 function, INJ_FUNC_MAXLEN);
294 if (private_data_size >= INJ_PRIVATE_MAXLEN)
295 elog(ERROR, "injection point data too long (maximum of %u)",
296 INJ_PRIVATE_MAXLEN);
297
298 /*
299 * Allocate and register a new injection point. A new point should not
300 * exist. For testing purposes this should be fine.
301 */
302 LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE);
303 max_inuse = pg_atomic_read_u32(&ActiveInjectionPoints->max_inuse);
304 free_idx = -1;
305
306 for (int idx = 0; idx < max_inuse; idx++)
307 {
308 entry = &ActiveInjectionPoints->entries[idx];
309 generation = pg_atomic_read_u64(&entry->generation);
310 if (generation % 2 == 0)
311 {
312 /*
313 * Found a free slot where we can add the new entry, but keep
314 * going so that we will find out if the entry already exists.
315 */
316 if (free_idx == -1)
317 free_idx = idx;
318 }
319 else 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: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
#define Assert(condition)
Definition: c.h:812
uint64_t uint64
Definition: c.h:486
uint32_t uint32
Definition: c.h:485
#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
on_exit_nicely_callback function
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * name

References Assert, elog, ERROR, function, 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 561 of file injection_point.c.

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

References elog, ERROR, and name.

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

250{
251#ifdef USE_INJECTION_POINTS
252 bool found;
253
254 ActiveInjectionPoints = ShmemInitStruct("InjectionPoint hash",
255 sizeof(InjectionPointsCtl),
256 &found);
258 {
259 Assert(!found);
260 pg_atomic_init_u32(&ActiveInjectionPoints->max_inuse, 0);
261 for (int i = 0; i < MAX_INJECTION_POINTS; i++)
262 pg_atomic_init_u64(&ActiveInjectionPoints->entries[i].generation, 0);
263 }
264 else
265 Assert(found);
266#endif
267}
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:72
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:382

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

Referenced by CreateOrAttachShmemStructs().

◆ InjectionPointShmemSize()

Size InjectionPointShmemSize ( void  )

Definition at line 233 of file injection_point.c.

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

References add_size().

Referenced by CalculateShmemSize().

◆ IsInjectionPointAttached()

bool IsInjectionPointAttached ( const char *  name)

Definition at line 578 of file injection_point.c.

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

References elog, ERROR, and name.