Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/test/modules/injection_points/injection_points.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "postgres.h"
#include <time.h>

#include "fmgr.h"
#include "miscadmin.h"
Expand Down Expand Up @@ -59,6 +60,8 @@ typedef struct InjectionPointCondition

/* ID of the process where the injection point is allowed to run */
int pid;
/* probability in [0,1], 1.0 = always */
double prob;
} InjectionPointCondition;

/*
Expand Down Expand Up @@ -88,13 +91,16 @@ static InjectionPointSharedState *inj_state = NULL;

extern PGDLLEXPORT void injection_error(const char *name,
const void *private_data);
extern PGDLLEXPORT void injection_error_prob(const char *name,
const void *private_data);
extern PGDLLEXPORT void injection_notice(const char *name,
const void *private_data);
extern PGDLLEXPORT void injection_wait(const char *name,
const void *private_data);

/* track if injection points attached in this process are linked to it */
static bool injection_point_local = false;
static double action2prob(const char *action, int pos);

/*
* Callback for shared memory area initialization.
Expand Down Expand Up @@ -185,6 +191,21 @@ injection_error(const char *name, const void *private_data)
elog(ERROR, "error triggered for injection point %s", name);
}

void
injection_error_prob(const char *name, const void *private_data)
{
InjectionPointCondition *condition = (InjectionPointCondition *) private_data;

if (!injection_point_allowed(condition))
return;

/* Use the probability stored in the condition. */
if ((double) rand() / (double) RAND_MAX > condition->prob)
return;

elog(ERROR, "error triggered for injection point %s", name);
}

void
injection_notice(const char *name, const void *private_data)
{
Expand Down Expand Up @@ -278,6 +299,11 @@ injection_points_attach(PG_FUNCTION_ARGS)
function = "injection_notice";
else if (strcmp(action, "wait") == 0)
function = "injection_wait";
else if (strncmp(action, "error-prob-", 11) == 0)
{
condition.prob = action2prob(action, 11);
function = "injection_error_prob";
}
else
elog(ERROR, "incorrect action \"%s\" for injection point creation", action);

Expand Down Expand Up @@ -402,3 +428,30 @@ injection_points_detach(PG_FUNCTION_ARGS)

PG_RETURN_VOID();
}

/*
* Coverts the action name into probability
*/
static double action2prob(const char *action, const int pos)
{
/*
* Simple parser: convert "0-01" -> "0.01" then strtod().
*/
const char *p = action + pos; /* points to "0-01" */
double prob;
char *endptr;
char buf[32];
int i,
j;

for (i = 0, j = 0; p[i] != '\0' && j < (int) sizeof(buf) - 1; i++)
{
buf[j++] = (p[i] == '-') ? '.' : p[i];
}
buf[j] = '\0';
errno = 0;
prob = strtod(buf, &endptr);
if (errno != 0 || endptr == buf || prob < 0.0 || prob > 1.0)
elog(ERROR, "invalid probability in action \"%s\"", action);
return prob;
}