mirror of
https://github.com/postgres/postgres.git
synced 2026-01-13 12:22:55 +03:00
When serialization or deadlock errors are reported by backend, allow to retry and continue the benchmarking. For this purpose new options "--max-tries", "--failures-detailed" and "--verbose-errors" are added. Transactions with serialization errors or deadlock errors will be repeated after rollbacks until they complete successfully or reach the maximum number of tries (specified by the --max-tries option), or the maximum time of tries (specified by the --latency-limit option). These options can be specified at the same time. It is not possible to use an unlimited number of tries (--max-tries=0) without the --latency-limit option or the --time option. By default the option --max-tries is set to 1, which means transactions with serialization/deadlock errors are not retried. If the last try fails, this transaction will be reported as failed, and the client variables will be set as they were before the first run of this transaction. Statistics on retries and failures are printed in the progress, transaction / aggregation logs and in the end with other results (all and for each script). Also retries and failures are printed per-command with average latency by using option (--report-per-command, -r). Option --failures-detailed prints group failures by basic types (serialization failures / deadlock failures). Option --verbose-errors prints distinct reports on errors and failures (errors without retrying) by type with detailed information like which limit for retries was violated and how far it was exceeded for the serialization/deadlock failures. Patch originally written by Marina Polyakova then Yugo Nagata inherited the discussion and heavily modified the patch to make it commitable. Authors: Yugo Nagata, Marina Polyakova Reviewed-by: Fabien Coelho, Tatsuo Ishii, Alvaro Herrera, Kevin Grittner, Andres Freund, Arthur Zakirov, Alexander Korotkov, Teodor Sigaev, Ildus Kurbangaliev Discussion: https://postgr.es/m/flat/72a0d590d6ba06f242d75c2e641820ec%40postgrespro.ru
103 lines
3.7 KiB
C
103 lines
3.7 KiB
C
/*-------------------------------------------------------------------------
|
|
* A stack of automaton states to handle nested conditionals.
|
|
*
|
|
* This file describes a stack of automaton states which
|
|
* allow a manage nested conditionals.
|
|
*
|
|
* It is used by:
|
|
* - "psql" interpreter for handling \if ... \endif
|
|
* - "pgbench" interpreter for handling \if ... \endif
|
|
* - "pgbench" syntax checker to test for proper nesting
|
|
*
|
|
* The stack holds the state of enclosing conditionals (are we in
|
|
* a true branch? in a false branch? have we already encountered
|
|
* a true branch?) so that the interpreter knows whether to execute
|
|
* code and whether to evaluate conditions.
|
|
*
|
|
* Copyright (c) 2000-2022, PostgreSQL Global Development Group
|
|
*
|
|
* src/include/fe_utils/conditional.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef CONDITIONAL_H
|
|
#define CONDITIONAL_H
|
|
|
|
/*
|
|
* Possible states of a single level of \if block.
|
|
*/
|
|
typedef enum ifState
|
|
{
|
|
IFSTATE_NONE = 0, /* not currently in an \if block */
|
|
IFSTATE_TRUE, /* currently in an \if or \elif that is true
|
|
* and all parent branches (if any) are true */
|
|
IFSTATE_FALSE, /* currently in an \if or \elif that is false
|
|
* but no true branch has yet been seen, and
|
|
* all parent branches (if any) are true */
|
|
IFSTATE_IGNORED, /* currently in an \elif that follows a true
|
|
* branch, or the whole \if is a child of a
|
|
* false parent branch */
|
|
IFSTATE_ELSE_TRUE, /* currently in an \else that is true and all
|
|
* parent branches (if any) are true */
|
|
IFSTATE_ELSE_FALSE /* currently in an \else that is false or
|
|
* ignored */
|
|
} ifState;
|
|
|
|
/*
|
|
* The state of nested \ifs is stored in a stack.
|
|
*
|
|
* query_len is used to determine what accumulated text to throw away at the
|
|
* end of an inactive branch. (We could, perhaps, teach the lexer to not add
|
|
* stuff to the query buffer in the first place when inside an inactive branch;
|
|
* but that would be very invasive.) We also need to save and restore the
|
|
* lexer's parenthesis nesting depth when throwing away text. (We don't need
|
|
* to save and restore any of its other state, such as comment nesting depth,
|
|
* because a backslash command could never appear inside a comment or SQL
|
|
* literal.)
|
|
*/
|
|
typedef struct IfStackElem
|
|
{
|
|
ifState if_state; /* current state, see enum above */
|
|
int query_len; /* length of query_buf at last branch start */
|
|
int paren_depth; /* parenthesis depth at last branch start */
|
|
struct IfStackElem *next; /* next surrounding \if, if any */
|
|
} IfStackElem;
|
|
|
|
typedef struct ConditionalStackData
|
|
{
|
|
IfStackElem *head;
|
|
} ConditionalStackData;
|
|
|
|
typedef struct ConditionalStackData *ConditionalStack;
|
|
|
|
|
|
extern ConditionalStack conditional_stack_create(void);
|
|
|
|
extern void conditional_stack_reset(ConditionalStack cstack);
|
|
|
|
extern void conditional_stack_destroy(ConditionalStack cstack);
|
|
|
|
extern int conditional_stack_depth(ConditionalStack cstack);
|
|
|
|
extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
|
|
|
|
extern bool conditional_stack_pop(ConditionalStack cstack);
|
|
|
|
extern ifState conditional_stack_peek(ConditionalStack cstack);
|
|
|
|
extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
|
|
|
|
extern bool conditional_stack_empty(ConditionalStack cstack);
|
|
|
|
extern bool conditional_active(ConditionalStack cstack);
|
|
|
|
extern void conditional_stack_set_query_len(ConditionalStack cstack, int len);
|
|
|
|
extern int conditional_stack_get_query_len(ConditionalStack cstack);
|
|
|
|
extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
|
|
|
|
extern int conditional_stack_get_paren_depth(ConditionalStack cstack);
|
|
|
|
#endif /* CONDITIONAL_H */
|