PostgreSQL Source Code: src/test/modules/injection_points/injection_points.c Source File

PostgreSQL Source Code git master
injection_points.c
Go to the documentation of this file.
1/*--------------------------------------------------------------------------
2 *
3 * injection_points.c
4 * Code for testing injection points.
5 *
6 * Injection points are able to trigger user-defined callbacks in pre-defined
7 * code paths.
8 *
9 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
11 *
12 * IDENTIFICATION
13 * src/test/modules/injection_points/injection_points.c
14 *
15 * -------------------------------------------------------------------------
16 */
17
18#include "postgres.h"
19
20#include "fmgr.h"
21#include "funcapi.h"
22#include "injection_stats.h"
23#include "miscadmin.h"
24#include "nodes/pg_list.h"
25#include "nodes/value.h"
26#include "storage/condition_variable.h"
27#include "storage/dsm_registry.h"
28#include "storage/ipc.h"
29#include "storage/lwlock.h"
30#include "storage/shmem.h"
31#include "utils/builtins.h"
32#include "utils/guc.h"
33#include "utils/injection_point.h"
34#include "utils/memutils.h"
35#include "utils/wait_event.h"
36
37 PG_MODULE_MAGIC;
38
39/* Maximum number of waits usable in injection points at once */
40 #define INJ_MAX_WAIT 8
41 #define INJ_NAME_MAXLEN 64
42
43/*
44 * Conditions related to injection points. This tracks in shared memory the
45 * runtime conditions under which an injection point is allowed to run,
46 * stored as private_data when an injection point is attached, and passed as
47 * argument to the callback.
48 *
49 * If more types of runtime conditions need to be tracked, this structure
50 * should be expanded.
51 */
52 typedef enum InjectionPointConditionType
53{
54 INJ_CONDITION_ALWAYS = 0, /* always run */
55 INJ_CONDITION_PID, /* PID restriction */
56 } InjectionPointConditionType;
57
58 typedef struct InjectionPointCondition
59{
60 /* Type of the condition */
61 InjectionPointConditionType type;
62
63 /* ID of the process where the injection point is allowed to run */
64 int pid;
65 } InjectionPointCondition;
66
67/*
68 * List of injection points stored in TopMemoryContext attached
69 * locally to this process.
70 */
71 static List *inj_list_local = NIL;
72
73/*
74 * Shared state information for injection points.
75 *
76 * This state data can be initialized in two ways: dynamically with a DSM
77 * or when loading the module.
78 */
79 typedef struct InjectionPointSharedState
80{
81 /* Protects access to other fields */
82 slock_t lock;
83
84 /* Counters advancing when injection_points_wakeup() is called */
85 uint32 wait_counts[INJ_MAX_WAIT];
86
87 /* Names of injection points attached to wait counters */
88 char name[INJ_MAX_WAIT][INJ_NAME_MAXLEN];
89
90 /* Condition variable used for waits and wakeups */
91 ConditionVariable wait_point;
92 } InjectionPointSharedState;
93
94/* Pointer to shared-memory state. */
95 static InjectionPointSharedState *inj_state = NULL;
96
97extern PGDLLEXPORT void injection_error(const char *name,
98 const void *private_data,
99 void *arg);
100extern PGDLLEXPORT void injection_notice(const char *name,
101 const void *private_data,
102 void *arg);
103extern PGDLLEXPORT void injection_wait(const char *name,
104 const void *private_data,
105 void *arg);
106
107/* track if injection points attached in this process are linked to it */
108 static bool injection_point_local = false;
109
110/*
111 * GUC variable
112 *
113 * This GUC is useful to control if statistics should be enabled or not
114 * during a test with injection points, like for example if a test relies
115 * on a callback run in a critical section where no allocation should happen.
116 */
117 bool inj_stats_enabled = false;
118
119/* Shared memory init callbacks */
120 static shmem_request_hook_type prev_shmem_request_hook = NULL;
121 static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
122
123/*
124 * Routine for shared memory area initialization, used as a callback
125 * when initializing dynamically with a DSM or when loading the module.
126 */
127static void
128 injection_point_init_state(void *ptr)
129{
130 InjectionPointSharedState *state = (InjectionPointSharedState *) ptr;
131
132 SpinLockInit(&state->lock);
133 memset(state->wait_counts, 0, sizeof(state->wait_counts));
134 memset(state->name, 0, sizeof(state->name));
135 ConditionVariableInit(&state->wait_point);
136}
137
138/* Shared memory initialization when loading module */
139static void
140 injection_shmem_request(void)
141{
142 Size size;
143
144 if (prev_shmem_request_hook)
145 prev_shmem_request_hook();
146
147 size = MAXALIGN(sizeof(InjectionPointSharedState));
148 RequestAddinShmemSpace(size);
149}
150
151static void
152 injection_shmem_startup(void)
153{
154 bool found;
155
156 if (prev_shmem_startup_hook)
157 prev_shmem_startup_hook();
158
159 /* Create or attach to the shared memory state */
160 LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
161
162 inj_state = ShmemInitStruct("injection_points",
163 sizeof(InjectionPointSharedState),
164 &found);
165
166 if (!found)
167 {
168 /*
169 * First time through, so initialize. This is shared with the dynamic
170 * initialization using a DSM.
171 */
172 injection_point_init_state(inj_state);
173 }
174
175 LWLockRelease(AddinShmemInitLock);
176}
177
178/*
179 * Initialize shared memory area for this module through DSM.
180 */
181static void
182 injection_init_shmem(void)
183{
184 bool found;
185
186 if (inj_state != NULL)
187 return;
188
189 inj_state = GetNamedDSMSegment("injection_points",
190 sizeof(InjectionPointSharedState),
191 injection_point_init_state,
192 &found);
193}
194
195/*
196 * Check runtime conditions associated to an injection point.
197 *
198 * Returns true if the named injection point is allowed to run, and false
199 * otherwise.
200 */
201static bool
202 injection_point_allowed(InjectionPointCondition *condition)
203{
204 bool result = true;
205
206 switch (condition->type)
207 {
208 case INJ_CONDITION_PID:
209 if (MyProcPid != condition->pid)
210 result = false;
211 break;
212 case INJ_CONDITION_ALWAYS:
213 break;
214 }
215
216 return result;
217}
218
219/*
220 * before_shmem_exit callback to remove injection points linked to a
221 * specific process.
222 */
223static void
224 injection_points_cleanup(int code, Datum arg)
225{
226 ListCell *lc;
227
228 /* Leave if nothing is tracked locally */
229 if (!injection_point_local)
230 return;
231
232 /* Detach all the local points */
233 foreach(lc, inj_list_local)
234 {
235 char *name = strVal(lfirst(lc));
236
237 (void) InjectionPointDetach(name);
238
239 /* Remove stats entry */
240 pgstat_drop_inj(name);
241 }
242}
243
244/* Set of callbacks available to be attached to an injection point. */
245void
246 injection_error(const char *name, const void *private_data, void *arg)
247{
248 InjectionPointCondition *condition = (InjectionPointCondition *) private_data;
249 char *argstr = (char *) arg;
250
251 if (!injection_point_allowed(condition))
252 return;
253
254 pgstat_report_inj(name);
255
256 if (argstr)
257 elog(ERROR, "error triggered for injection point %s (%s)",
258 name, argstr);
259 else
260 elog(ERROR, "error triggered for injection point %s", name);
261}
262
263void
264 injection_notice(const char *name, const void *private_data, void *arg)
265{
266 InjectionPointCondition *condition = (InjectionPointCondition *) private_data;
267 char *argstr = (char *) arg;
268
269 if (!injection_point_allowed(condition))
270 return;
271
272 pgstat_report_inj(name);
273
274 if (argstr)
275 elog(NOTICE, "notice triggered for injection point %s (%s)",
276 name, argstr);
277 else
278 elog(NOTICE, "notice triggered for injection point %s", name);
279}
280
281/* Wait on a condition variable, awaken by injection_points_wakeup() */
282void
283 injection_wait(const char *name, const void *private_data, void *arg)
284{
285 uint32 old_wait_counts = 0;
286 int index = -1;
287 uint32 injection_wait_event = 0;
288 InjectionPointCondition *condition = (InjectionPointCondition *) private_data;
289
290 if (inj_state == NULL)
291 injection_init_shmem();
292
293 if (!injection_point_allowed(condition))
294 return;
295
296 pgstat_report_inj(name);
297
298 /*
299 * Use the injection point name for this custom wait event. Note that
300 * this custom wait event name is not released, but we don't care much for
301 * testing as this should be short-lived.
302 */
303 injection_wait_event = WaitEventInjectionPointNew(name);
304
305 /*
306 * Find a free slot to wait for, and register this injection point's name.
307 */
308 SpinLockAcquire(&inj_state->lock);
309 for (int i = 0; i < INJ_MAX_WAIT; i++)
310 {
311 if (inj_state->name[i][0] == '0円')
312 {
313 index = i;
314 strlcpy(inj_state->name[i], name, INJ_NAME_MAXLEN);
315 old_wait_counts = inj_state->wait_counts[i];
316 break;
317 }
318 }
319 SpinLockRelease(&inj_state->lock);
320
321 if (index < 0)
322 elog(ERROR, "could not find free slot for wait of injection point %s ",
323 name);
324
325 /* And sleep.. */
326 ConditionVariablePrepareToSleep(&inj_state->wait_point);
327 for (;;)
328 {
329 uint32 new_wait_counts;
330
331 SpinLockAcquire(&inj_state->lock);
332 new_wait_counts = inj_state->wait_counts[index];
333 SpinLockRelease(&inj_state->lock);
334
335 if (old_wait_counts != new_wait_counts)
336 break;
337 ConditionVariableSleep(&inj_state->wait_point, injection_wait_event);
338 }
339 ConditionVariableCancelSleep();
340
341 /* Remove this injection point from the waiters. */
342 SpinLockAcquire(&inj_state->lock);
343 inj_state->name[index][0] = '0円';
344 SpinLockRelease(&inj_state->lock);
345}
346
347/*
348 * SQL function for creating an injection point.
349 */
350 PG_FUNCTION_INFO_V1(injection_points_attach);
351Datum
352 injection_points_attach(PG_FUNCTION_ARGS)
353{
354 char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
355 char *action = text_to_cstring(PG_GETARG_TEXT_PP(1));
356 char *function;
357 InjectionPointCondition condition = {0};
358
359 if (strcmp(action, "error") == 0)
360 function = "injection_error";
361 else if (strcmp(action, "notice") == 0)
362 function = "injection_notice";
363 else if (strcmp(action, "wait") == 0)
364 function = "injection_wait";
365 else
366 elog(ERROR, "incorrect action \"%s\" for injection point creation", action);
367
368 if (injection_point_local)
369 {
370 condition.type = INJ_CONDITION_PID;
371 condition.pid = MyProcPid;
372 }
373
374 pgstat_report_inj_fixed(1, 0, 0, 0, 0);
375 InjectionPointAttach(name, "injection_points", function, &condition,
376 sizeof(InjectionPointCondition));
377
378 if (injection_point_local)
379 {
380 MemoryContext oldctx;
381
382 /* Local injection point, so track it for automated cleanup */
383 oldctx = MemoryContextSwitchTo(TopMemoryContext);
384 inj_list_local = lappend(inj_list_local, makeString(pstrdup(name)));
385 MemoryContextSwitchTo(oldctx);
386 }
387
388 /* Add entry for stats */
389 pgstat_create_inj(name);
390
391 PG_RETURN_VOID();
392}
393
394/*
395 * SQL function for loading an injection point.
396 */
397 PG_FUNCTION_INFO_V1(injection_points_load);
398Datum
399 injection_points_load(PG_FUNCTION_ARGS)
400{
401 char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
402
403 if (inj_state == NULL)
404 injection_init_shmem();
405
406 pgstat_report_inj_fixed(0, 0, 0, 0, 1);
407 INJECTION_POINT_LOAD(name);
408
409 PG_RETURN_VOID();
410}
411
412/*
413 * SQL function for triggering an injection point.
414 */
415 PG_FUNCTION_INFO_V1(injection_points_run);
416Datum
417 injection_points_run(PG_FUNCTION_ARGS)
418{
419 char *name;
420 char *arg = NULL;
421
422 if (PG_ARGISNULL(0))
423 PG_RETURN_VOID();
424 name = text_to_cstring(PG_GETARG_TEXT_PP(0));
425
426 if (!PG_ARGISNULL(1))
427 arg = text_to_cstring(PG_GETARG_TEXT_PP(1));
428
429 pgstat_report_inj_fixed(0, 0, 1, 0, 0);
430 INJECTION_POINT(name, arg);
431
432 PG_RETURN_VOID();
433}
434
435/*
436 * SQL function for triggering an injection point from cache.
437 */
438 PG_FUNCTION_INFO_V1(injection_points_cached);
439Datum
440 injection_points_cached(PG_FUNCTION_ARGS)
441{
442 char *name;
443 char *arg = NULL;
444
445 if (PG_ARGISNULL(0))
446 PG_RETURN_VOID();
447 name = text_to_cstring(PG_GETARG_TEXT_PP(0));
448
449 if (!PG_ARGISNULL(1))
450 arg = text_to_cstring(PG_GETARG_TEXT_PP(1));
451
452 pgstat_report_inj_fixed(0, 0, 0, 1, 0);
453 INJECTION_POINT_CACHED(name, arg);
454
455 PG_RETURN_VOID();
456}
457
458/*
459 * SQL function for waking up an injection point waiting in injection_wait().
460 */
461 PG_FUNCTION_INFO_V1(injection_points_wakeup);
462Datum
463 injection_points_wakeup(PG_FUNCTION_ARGS)
464{
465 char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
466 int index = -1;
467
468 if (inj_state == NULL)
469 injection_init_shmem();
470
471 /* First bump the wait counter for the injection point to wake up */
472 SpinLockAcquire(&inj_state->lock);
473 for (int i = 0; i < INJ_MAX_WAIT; i++)
474 {
475 if (strcmp(name, inj_state->name[i]) == 0)
476 {
477 index = i;
478 break;
479 }
480 }
481 if (index < 0)
482 {
483 SpinLockRelease(&inj_state->lock);
484 elog(ERROR, "could not find injection point %s to wake up", name);
485 }
486 inj_state->wait_counts[index]++;
487 SpinLockRelease(&inj_state->lock);
488
489 /* And broadcast the change to the waiters */
490 ConditionVariableBroadcast(&inj_state->wait_point);
491 PG_RETURN_VOID();
492}
493
494/*
495 * injection_points_set_local
496 *
497 * Track if any injection point created in this process ought to run only
498 * in this process. Such injection points are detached automatically when
499 * this process exits. This is useful to make test suites concurrent-safe.
500 */
501 PG_FUNCTION_INFO_V1(injection_points_set_local);
502Datum
503 injection_points_set_local(PG_FUNCTION_ARGS)
504{
505 /* Enable flag to add a runtime condition based on this process ID */
506 injection_point_local = true;
507
508 if (inj_state == NULL)
509 injection_init_shmem();
510
511 /*
512 * Register a before_shmem_exit callback to remove any injection points
513 * linked to this process.
514 */
515 before_shmem_exit(injection_points_cleanup, (Datum) 0);
516
517 PG_RETURN_VOID();
518}
519
520/*
521 * SQL function for dropping an injection point.
522 */
523 PG_FUNCTION_INFO_V1(injection_points_detach);
524Datum
525 injection_points_detach(PG_FUNCTION_ARGS)
526{
527 char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
528
529 pgstat_report_inj_fixed(0, 1, 0, 0, 0);
530 if (!InjectionPointDetach(name))
531 elog(ERROR, "could not detach injection point \"%s\"", name);
532
533 /* Remove point from local list, if required */
534 if (inj_list_local != NIL)
535 {
536 MemoryContext oldctx;
537
538 oldctx = MemoryContextSwitchTo(TopMemoryContext);
539 inj_list_local = list_delete(inj_list_local, makeString(name));
540 MemoryContextSwitchTo(oldctx);
541 }
542
543 /* Remove stats entry */
544 pgstat_drop_inj(name);
545
546 PG_RETURN_VOID();
547}
548
549/*
550 * SQL function for listing all the injection points attached.
551 */
552 PG_FUNCTION_INFO_V1(injection_points_list);
553Datum
554 injection_points_list(PG_FUNCTION_ARGS)
555{
556#define NUM_INJECTION_POINTS_LIST 3
557 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
558 List *inj_points;
559 ListCell *lc;
560
561 /* Build a tuplestore to return our results in */
562 InitMaterializedSRF(fcinfo, 0);
563
564 inj_points = InjectionPointList();
565
566 foreach(lc, inj_points)
567 {
568 Datum values[NUM_INJECTION_POINTS_LIST];
569 bool nulls[NUM_INJECTION_POINTS_LIST];
570 InjectionPointData *inj_point = lfirst(lc);
571
572 memset(values, 0, sizeof(values));
573 memset(nulls, 0, sizeof(nulls));
574
575 values[0] = PointerGetDatum(cstring_to_text(inj_point->name));
576 values[1] = PointerGetDatum(cstring_to_text(inj_point->library));
577 values[2] = PointerGetDatum(cstring_to_text(inj_point->function));
578
579 /* shove row into tuplestore */
580 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
581 }
582
583 return (Datum) 0;
584#undef NUM_INJECTION_POINTS_LIST
585}
586
587
588void
589 _PG_init(void)
590{
591 if (!process_shared_preload_libraries_in_progress)
592 return;
593
594 DefineCustomBoolVariable("injection_points.stats",
595 "Enables statistics for injection points.",
596 NULL,
597 &inj_stats_enabled,
598 false,
599 PGC_POSTMASTER,
600 0,
601 NULL,
602 NULL,
603 NULL);
604
605 MarkGUCPrefixReserved("injection_points");
606
607 /* Shared memory initialization */
608 prev_shmem_request_hook = shmem_request_hook;
609 shmem_request_hook = injection_shmem_request;
610 prev_shmem_startup_hook = shmem_startup_hook;
611 shmem_startup_hook = injection_shmem_startup;
612
613 pgstat_register_inj();
614 pgstat_register_inj_fixed();
615}
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define MAXALIGN(LEN)
Definition: c.h:810
#define PGDLLEXPORT
Definition: c.h:1334
uint32_t uint32
Definition: c.h:538
size_t Size
Definition: c.h:610
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariablePrepareToSleep(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
void * GetNamedDSMSegment(const char *name, size_t size, void(*init_callback)(void *ptr), bool *found)
Definition: dsm_registry.c:185
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define NOTICE
Definition: elog.h:35
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
int MyProcPid
Definition: globals.c:47
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:5154
void MarkGUCPrefixReserved(const char *className)
Definition: guc.c:5301
@ PGC_POSTMASTER
Definition: guc.h:74
bool InjectionPointDetach(const char *name)
List * InjectionPointList(void)
void InjectionPointAttach(const char *name, const char *library, const char *function, const void *private_data, int private_data_size)
#define INJECTION_POINT(name, arg)
#define INJECTION_POINT_CACHED(name, arg)
#define INJECTION_POINT_LOAD(name)
Datum injection_points_detach(PG_FUNCTION_ARGS)
static bool injection_point_local
static void injection_shmem_request(void)
#define INJ_MAX_WAIT
PG_FUNCTION_INFO_V1(injection_points_attach)
void _PG_init(void)
PGDLLEXPORT void injection_wait(const char *name, const void *private_data, void *arg)
InjectionPointConditionType
@ INJ_CONDITION_PID
@ INJ_CONDITION_ALWAYS
static void injection_init_shmem(void)
Datum injection_points_cached(PG_FUNCTION_ARGS)
PG_MODULE_MAGIC
Datum injection_points_attach(PG_FUNCTION_ARGS)
struct InjectionPointCondition InjectionPointCondition
Datum injection_points_run(PG_FUNCTION_ARGS)
static List * inj_list_local
Datum injection_points_set_local(PG_FUNCTION_ARGS)
bool inj_stats_enabled
static shmem_startup_hook_type prev_shmem_startup_hook
static bool injection_point_allowed(InjectionPointCondition *condition)
static shmem_request_hook_type prev_shmem_request_hook
#define INJ_NAME_MAXLEN
static void injection_points_cleanup(int code, Datum arg)
static void injection_shmem_startup(void)
PGDLLEXPORT void injection_error(const char *name, const void *private_data, void *arg)
struct InjectionPointSharedState InjectionPointSharedState
#define NUM_INJECTION_POINTS_LIST
Datum injection_points_wakeup(PG_FUNCTION_ARGS)
PGDLLEXPORT void injection_notice(const char *name, const void *private_data, void *arg)
Datum injection_points_list(PG_FUNCTION_ARGS)
static void injection_point_init_state(void *ptr)
static InjectionPointSharedState * inj_state
Datum injection_points_load(PG_FUNCTION_ARGS)
void pgstat_report_inj(const char *name)
void pgstat_register_inj(void)
void pgstat_create_inj(const char *name)
void pgstat_drop_inj(const char *name)
void pgstat_register_inj_fixed(void)
void pgstat_report_inj_fixed(uint32 numattach, uint32 numdetach, uint32 numrun, uint32 numcached, uint32 numloaded)
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337
void(* shmem_startup_hook_type)(void)
Definition: ipc.h:22
shmem_startup_hook_type shmem_startup_hook
Definition: ipci.c:58
void RequestAddinShmemSpace(Size size)
Definition: ipci.c:74
i
int i
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_delete(List *list, void *datum)
Definition: list.c:853
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_EXCLUSIVE
Definition: lwlock.h:112
char * pstrdup(const char *in)
Definition: mcxt.c:1759
MemoryContext TopMemoryContext
Definition: mcxt.c:166
void(* shmem_request_hook_type)(void)
Definition: miscadmin.h:532
shmem_request_hook_type shmem_request_hook
Definition: miscinit.c:1789
bool process_shared_preload_libraries_in_progress
Definition: miscinit.c:1786
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
on_exit_nicely_callback function
void * arg
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
#define SpinLockInit(lock)
Definition: spin.h:57
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
InjectionPointConditionType type
const char * library
const char * name
const char * function
uint32 wait_counts[INJ_MAX_WAIT]
char name[INJ_MAX_WAIT][INJ_NAME_MAXLEN]
ConditionVariable wait_point
Definition: pg_list.h:54
TupleDesc setDesc
Definition: execnodes.h:364
Tuplestorestate * setResult
Definition: execnodes.h:363
Definition: type.h:96
Definition: regguts.h:323
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
Definition: pg_list.h:46
String * makeString(char *str)
Definition: value.c:63
#define strVal(v)
Definition: value.h:82
text * cstring_to_text(const char *s)
Definition: varlena.c:181
char * text_to_cstring(const text *t)
Definition: varlena.c:214
uint32 WaitEventInjectionPointNew(const char *wait_event_name)
Definition: wait_event.c:169
const char * name

AltStyle によって変換されたページ (->オリジナル) /