Skip to content
Closed
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion src/backend/storage/buffer/bufmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include "utils/resowner.h"
#include "utils/timestamp.h"

uint32 (*get_pin_limit_hook)(void);

/* Note: these two macros only work on shared buffers, not local ones! */
#define BufHdrGetBlock(bufHdr) ((Block) (BufferBlocks + ((Size) (bufHdr)->buf_id) * BLCKSZ))
Expand Down Expand Up @@ -2131,7 +2132,7 @@ LimitAdditionalPins(uint32 *additional_pins)
return;

max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
max_proportional_pins = NBuffers / max_backends;
max_proportional_pins = get_pin_limit_hook ? get_pin_limit_hook() : NBuffers / max_backends;

/*
* Subtract the approximate number of buffers already pinned by this
Expand Down
10 changes: 10 additions & 0 deletions src/backend/tcop/postgres.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ int client_connection_check_interval = 0;
/* flags for non-system relation kinds to restrict use */
int restrict_nonsystem_relation_kind;

#ifdef USE_INJECTION_POINTS
/* Counter which can show us if we are in SMGR */
int inside_smgr_api = 0;
#endif
/* ----------------
* private typedefs etc
* ----------------
Expand Down Expand Up @@ -3275,6 +3279,12 @@ ProcessInterrupts(void)
/* OK to accept any interrupts now? */
if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
return;
#ifdef USE_INJECTION_POINTS
if (inside_smgr_api > 0)
{
INJECTION_POINT("SMGR_API");
}
#endif
InterruptPending = false;

retry:
Expand Down
5 changes: 5 additions & 0 deletions src/include/postgres.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,8 @@ extern Datum Float8GetDatum(float8 X);
#endif

#endif /* POSTGRES_H */

/* Declare for neon use */
#ifdef USE_INJECTION_POINTS
extern int inside_smgr_api;
#endif
1 change: 1 addition & 0 deletions src/include/storage/bufmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ extern int GetAccessStrategyPinLimit(BufferAccessStrategy strategy);

extern void FreeAccessStrategy(BufferAccessStrategy strategy);

extern uint32 (*get_pin_limit_hook)(void);

/* inline functions */

Expand Down
50 changes: 50 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,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just call this `injection_error_probability" so its clear its not "prob"lem. Do we have tests that utilize this or is it for manual testing. Good function to have though.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it was not my commit.
It is from PR #878
Have no idea why it was included in this PR (looks like it is because of merge with vanilla).
Should I create new PR without this changes?
Or should we merge them?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets create a new PR so its clean

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 @@ -184,7 +190,20 @@ 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 +297,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 +426,29 @@ 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;
}