From 8da1b1ba34f7c4a0e125c9e0e10a574d79db7e4e Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Fri, 24 Jul 2026 18:18:37 +0200 Subject: [PATCH 1/5] docs: document the region column/option and node.ini gap from PR #1149 PR #1149 (issue #997, 3-DC split-brain fix) added a --region option to pg_autoctl create postgres/coordinator/worker, a matching [settings] region key in pg_autoctl_node.ini, a REGION column in `pg_autoctl watch`, and a new pgautofailover.replication_stall_timeout GUC -- none of it made it into the docs. - docs/ref/pg_autoctl_create_postgres.rst: add --region to the usage synopsis and options list (create_coordinator.rst/create_worker.rst already defer common options here, matching the existing pattern for --candidate-priority etc., so no change needed there). - docs/ref/pg_autoctl_node.rst: add region to the [settings] section reference. Verified in the source (keeper.c, nodespec.c, and the absence of a "region" case in cli_get_set_properties.c) that, unlike its section-mates candidate_priority/replication_quorum, region has no live "pg_autoctl set node region" path -- it's read from [settings] but only takes effect at node creation time. Documented that distinction explicitly and corrected the section's blanket "applied live" claim. - docs/ref/pg_autoctl_watch.rst: add the Region column to the column list. Confirmed via cli_show.c that `pg_autoctl show state` has its own, separate, unaffected column set -- only `watch` gained this column. - docs/ref/configuration.rst: add pgautofailover.replication_stall_timeout to the sample pg_settings query output and give it its own subsection (matching the existing guard_data_loss subsection), explaining the 3-DC split-brain scenario it addresses. - docs/ref/pgaftest.rst: add the `region ` node modifier to the DSL reference table (verified against the actual grammar rule and the replication_stall_3dc.pgaf spec's real usage: `node1 region dc1`). Also documents the manual docker-compose trick asked about separately: `compose start`/`compose stop` are DSL keywords usable only inside a spec's step{} block, with no standalone `pgaftest compose ...` command for ad hoc use from the `pgaftest tmux` bottom pane. Added a "Manually starting/ stopping a node" section showing the equivalent raw `docker compose -f $PGAFTEST_HOST_WORK_DIR/docker-compose.yml start/stop ` invocation, cross-referenced from the failure-simulation semantics section. Verified: `make -C docs html` builds clean; also checked with `sphinx-build -E -n` (full rebuild, nitpicky mode) -- no new warnings. --- docs/ref/configuration.rst | 25 +++++++++++++++++++++ docs/ref/pg_autoctl_create_postgres.rst | 10 +++++++++ docs/ref/pg_autoctl_node.rst | 14 +++++++++++- docs/ref/pg_autoctl_watch.rst | 8 +++++++ docs/ref/pgaftest.rst | 30 +++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/docs/ref/configuration.rst b/docs/ref/configuration.rst index b09939bda..cf554823b 100644 --- a/docs/ref/configuration.rst +++ b/docs/ref/configuration.rst @@ -106,6 +106,11 @@ database where the extension has been deployed:: setting | true unit | short_desc | Refuse to proceed with failover when quorum nodes have not yet reported their LSN. + -[ RECORD 11 ]--------------------------------------------------------------------------------------------------- + name | pgautofailover.replication_stall_timeout + setting | 10000 + unit | ms + short_desc | Assign wait_primary when the primary has had no standby connected in pg_stat_replication for this long. pgautofailover.guard_data_loss ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -130,6 +135,26 @@ failovers. Use ``ALTER DATABASE pg_auto_failover SET pgautofailover.guard_data_loss = false;`` only if you want the setting to persist across monitor restarts with explicit intent, and document the reason. +pgautofailover.replication_stall_timeout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This setting addresses a 3-datacentre split-brain scenario: the primary and +its standby lose connectivity to each other, but both remain reachable from +the monitor. In that situation the primary can neither detect the standby +is gone (it's still reachable, just not to the standby) nor get demoted by +the monitor (the monitor still sees it as healthy), so +``synchronous_standby_names`` stays set and every ``COMMIT`` on the primary +hangs indefinitely waiting for a standby acknowledgement that will never +come. + +When a ``PRIMARY`` node reports an empty ``pg_stat_replication`` sync state +for longer than ``pgautofailover.replication_stall_timeout`` (default +``10s``), the monitor assigns ``wait_primary``. This clears +``synchronous_standby_names`` and unblocks writes, without initiating a +failover — the standby simply rejoins as ``secondary`` once the link is +restored. See :ref:`pg_autoctl_show_state` and :ref:`pg_autoctl_watch` for +how to observe a node in ``wait_primary``. + You can edit the parameters as usual with PostgreSQL, either in the ``postgresql.conf`` file or using ``ALTER DATABASE pg_auto_failover SET parameter = value;`` commands, then issuing a reload. diff --git a/docs/ref/pg_autoctl_create_postgres.rst b/docs/ref/pg_autoctl_create_postgres.rst index b2d8b2089..0f04a2612 100644 --- a/docs/ref/pg_autoctl_create_postgres.rst +++ b/docs/ref/pg_autoctl_create_postgres.rst @@ -41,6 +41,7 @@ registered too, and is known to be healthy). --candidate-priority priority of the node to be promoted to become primary --replication-quorum true if node participates in write quorum --maximum-backup-rate maximum transfer rate of data transferred from the server during initial sync + --region data-centre or availability-zone label for this node Description ----------- @@ -268,6 +269,15 @@ The following options are available to ``pg_autoctl create postgres``: initial sync. This is used by ``pg_basebackup``. Defaults to ``100M``. +--region + + Sets a free-form label identifying the data-centre or availability zone + this node runs in, at node registration on the monitor. Defaults to + ``default``. Purely informational at the moment: it is displayed as its + own column by ``pg_autoctl watch`` in the verbose and higher policies, to + help make sense of the topology of a multi-region deployment. It does not + currently affect any failover or quorum decision. + --run Immediately run the ``pg_autoctl`` service after having created this node. diff --git a/docs/ref/pg_autoctl_node.rst b/docs/ref/pg_autoctl_node.rst index e84a32b44..ceb1ad0a8 100644 --- a/docs/ref/pg_autoctl_node.rst +++ b/docs/ref/pg_autoctl_node.rst @@ -152,7 +152,8 @@ node is created or started from scratch. ``[settings]`` ^^^^^^^^^^^^^^ -Settings in this section are applied live without restarting the node. +Most settings in this section are applied live without restarting the +node; ``region`` is the one exception, marked as such below. ``candidate_priority`` @@ -164,6 +165,17 @@ Settings in this section are applied live without restarting the node. Whether this node participates in the synchronous replication quorum. Boolean, defaults to ``true``. **Mutable**. +``region`` + + Free-form label identifying the data-centre or availability zone this + node runs in. Defaults to ``default``. Read from this section, but + unlike ``candidate_priority`` and ``replication_quorum`` it is applied + only at node creation time (there is no ``pg_autoctl set node region`` + command) — editing it in the ini file of an already-created node has no + effect. Purely informational: shown as its own column by ``pg_autoctl + watch`` in the verbose and higher policies, and does not currently + affect any failover or quorum decision. + ``[options]`` ^^^^^^^^^^^^^ diff --git a/docs/ref/pg_autoctl_watch.rst b/docs/ref/pg_autoctl_watch.rst index 04370b30f..2a18b940b 100644 --- a/docs/ref/pg_autoctl_watch.rst +++ b/docs/ref/pg_autoctl_watch.rst @@ -103,6 +103,14 @@ your terminal window size changes: the Node column contains the groupId and the nodeId, separated by a colon, such as ``0:1`` for the first coordinator node. + - Region + + The data-centre or availability zone label set for the node at + creation time, either with ``--region`` or the ``[settings] region`` + property of a ``pg_autoctl_node.ini`` file. Only shown in wider + terminal windows, alongside more detailed columns. Defaults to + ``default`` when not set. + - Last Report, or Report Time interval between now and the last known time when a node has diff --git a/docs/ref/pgaftest.rst b/docs/ref/pgaftest.rst index b655e8a10..559ce3027 100644 --- a/docs/ref/pgaftest.rst +++ b/docs/ref/pgaftest.rst @@ -127,6 +127,29 @@ The top pane streams ``docker compose logs -f``. The middle pane runs The ``pg_autoctl watch`` output in the top tmux pane updates in real time throughout this session. +Manually starting/stopping a node +---------------------------------- + +``compose start `` / ``compose stop `` (see +:ref:`pgaftest-failure-semantics` below) are DSL keywords understood only inside a +spec's ``step { }`` block — there is no standalone ``pgaftest compose ...`` +command to run them ad hoc from the bottom pane. To do the same thing +interactively, without adding a step to the spec, use plain Docker Compose +directly. The ``pgaftest`` service container already exports +``COMPOSE_PROJECT_NAME`` for you, so only ``-f`` is needed to point at the +compose file, which lives at ``$PGAFTEST_HOST_WORK_DIR`` rather than the +container's default working directory:: + + docker compose -f $PGAFTEST_HOST_WORK_DIR/docker-compose.yml stop node2 + docker compose -f $PGAFTEST_HOST_WORK_DIR/docker-compose.yml start node2 + +or equivalently, ``cd`` there first since the same path is bind-mounted +identically inside and outside the container:: + + cd $PGAFTEST_HOST_WORK_DIR + docker compose stop node2 + docker compose start node2 + Docker-out-of-Docker (DooD) architecture ----------------------------------------- @@ -362,6 +385,8 @@ Node modifiers: ============================================ ============================================= ``async`` Mark as async standby (no sync quorum) ``candidate-priority `` Failover priority 0–100 (default: 50) +``region `` Data-centre / availability-zone label + (``--region``; default: ``default``) ``launch deferred`` Container starts with ``sleep infinity``; use ``exec node pg_autoctl node start`` ``coordinator`` / ``worker group `` Citus role @@ -530,6 +555,11 @@ is actually testing, not whichever one happens to make the test pass. simply stopped and the process exits, falling back to the monitor's own health-check-driven failover. + ``compose start``/``compose stop`` are DSL keywords, only usable inside + a spec's ``step { }`` block. To do the same thing ad hoc from the + ``pgaftest tmux`` bottom pane, see `Manually starting/stopping a node`_ + above. + ``compose kill `` ``docker compose kill`` — immediate SIGKILL, no grace period at all. Exercises hard-crash recovery: the process gets zero chance to shut From 6bdefe6e9319b33d39294216188afe0feeeed41b Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Sat, 25 Jul 2026 00:26:36 +0200 Subject: [PATCH 2/5] Add region mutability: monitor SQL/C, pg_autoctl CLI, docs PR #1149 introduced `region` (data-centre/availability-zone label) as create-time only: a `--region` flag and a `[settings] region` key in node.ini, stored on `pgautofailover.node`, but with no way to change it on an already-registered, running node. Monitor side: - ReportAutoFailoverNodeRegion() (node_metadata.c/.h): UPDATE pgautofailover.node SET region = ... for a given node. - set_node_region() SQL function (node_active_protocol.c + pgautofailover.sql): validates the node exists and the new region is non-empty, updates it, and notifies listeners. No quorum/FSM impact, unlike candidate_priority/replication_quorum -- a straight passthrough. No extension version bump: 2.3 is still unreleased on origin/main, so this is incremental development on the current version. - Monitor regression coverage added to the existing node_active_protocol.sql/.out (not a new test file): direct set/get, unknown-node error, empty-value error. pg_autoctl CLI side: - monitor_set_node_region()/monitor_get_node_region() (monitor.c/.h). - `pg_autoctl set node region ` / `pg_autoctl get node region` (cli_get_set_properties.c), mirroring the existing candidate-priority/ replication-quorum commands but without their FSM-convergence wait, since region has none. Docs: pg_autoctl_node.rst flips region to "Mutable" under [settings]; new pg_autoctl_set_node_region.rst / pg_autoctl_get_node_region.rst reference pages, registered in pg_autoctl_set.rst/pg_autoctl_get.rst and pg_autoctl.rst's command listings. --- docs/ref/pg_autoctl.rst | 2 + docs/ref/pg_autoctl_get.rst | 1 + docs/ref/pg_autoctl_get_node_region.rst | 60 +++++++ docs/ref/pg_autoctl_node.rst | 17 +- docs/ref/pg_autoctl_set.rst | 1 + docs/ref/pg_autoctl_set_node_region.rst | 98 ++++++++++++ src/bin/pg_autoctl/cli_get_set_properties.c | 150 ++++++++++++++++++ src/bin/pg_autoctl/monitor.c | 108 +++++++++++++ src/bin/pg_autoctl/monitor.h | 6 + src/monitor/expected/node_active_protocol.out | 22 +++ src/monitor/node_active_protocol.c | 61 +++++++ src/monitor/node_metadata.c | 45 ++++++ src/monitor/node_metadata.h | 4 + src/monitor/pgautofailover.sql | 16 ++ src/monitor/sql/node_active_protocol.sql | 17 ++ 15 files changed, 598 insertions(+), 10 deletions(-) create mode 100644 docs/ref/pg_autoctl_get_node_region.rst create mode 100644 docs/ref/pg_autoctl_set_node_region.rst diff --git a/docs/ref/pg_autoctl.rst b/docs/ref/pg_autoctl.rst index 211a0f172..c1e94d22b 100644 --- a/docs/ref/pg_autoctl.rst +++ b/docs/ref/pg_autoctl.rst @@ -73,6 +73,7 @@ pg_autoctl provides the following commands:: pg_autoctl get node replication-quorum get replication-quorum property from the monitor candidate-priority get candidate property from the monitor + region get region property from the monitor pg_autoctl get formation settings get replication settings for a formation from the monitor @@ -86,6 +87,7 @@ pg_autoctl provides the following commands:: metadata set metadata on the monitor replication-quorum set replication-quorum property on the monitor candidate-priority set candidate property on the monitor + region set region property on the monitor pg_autoctl set formation number-sync-standbys set number-sync-standbys for a formation on the monitor diff --git a/docs/ref/pg_autoctl_get.rst b/docs/ref/pg_autoctl_get.rst index 7847f7905..af5966a24 100644 --- a/docs/ref/pg_autoctl_get.rst +++ b/docs/ref/pg_autoctl_get.rst @@ -12,3 +12,4 @@ pg_autoctl get - Get a pg_auto_failover node, or formation setting pg_autoctl_get_formation_number_sync_standbys pg_autoctl_get_node_replication_quorum pg_autoctl_get_node_candidate_priority + pg_autoctl_get_node_region diff --git a/docs/ref/pg_autoctl_get_node_region.rst b/docs/ref/pg_autoctl_get_node_region.rst new file mode 100644 index 000000000..f04c0e470 --- /dev/null +++ b/docs/ref/pg_autoctl_get_node_region.rst @@ -0,0 +1,60 @@ +.. _pg_autoctl_get_node_region: + +pg_autoctl get node region +=========================== + +pg_autoctl get region - get region property from the monitor + +Synopsis +-------- + +This command prints the ``pg_autoctl`` region label for a given node:: + + usage: pg_autoctl get node region [ --pgdata ] [ --json ] [ --formation ] [ --name ] + + --pgdata path to data directory + --formation pg_auto_failover formation + --name pg_auto_failover node name + --json output data in the JSON format + +Description +----------- + +See also :ref:`pg_autoctl_set_node_region` to change the value, and +:ref:`pg_autoctl_show_settings` for the full list of replication settings. + +Options +------- + +--pgdata + + Location of the Postgres node being managed locally. Defaults to the + environment variable ``PGDATA``. Use ``--monitor`` to connect to a monitor + from anywhere, rather than the monitor URI used by a local Postgres node + managed with ``pg_autoctl``. + +--json + + Output JSON formatted data. + +--formation + + Show replication settings for given formation. Defaults to ``default``. + +--name + + Show replication settings for given node, selected by name. + +Examples +-------- + +:: + + $ pg_autoctl get node region --name node1 + dc1 + + $ pg_autoctl get node region --name node1 --json + { + "name": "node1", + "region": "dc1" + } diff --git a/docs/ref/pg_autoctl_node.rst b/docs/ref/pg_autoctl_node.rst index ceb1ad0a8..ad4b05840 100644 --- a/docs/ref/pg_autoctl_node.rst +++ b/docs/ref/pg_autoctl_node.rst @@ -152,8 +152,7 @@ node is created or started from scratch. ``[settings]`` ^^^^^^^^^^^^^^ -Most settings in this section are applied live without restarting the -node; ``region`` is the one exception, marked as such below. +Settings in this section are applied live without restarting the node. ``candidate_priority`` @@ -168,13 +167,11 @@ node; ``region`` is the one exception, marked as such below. ``region`` Free-form label identifying the data-centre or availability zone this - node runs in. Defaults to ``default``. Read from this section, but - unlike ``candidate_priority`` and ``replication_quorum`` it is applied - only at node creation time (there is no ``pg_autoctl set node region`` - command) — editing it in the ini file of an already-created node has no - effect. Purely informational: shown as its own column by ``pg_autoctl - watch`` in the verbose and higher policies, and does not currently - affect any failover or quorum decision. + node runs in. Defaults to ``default``. **Mutable**: changes are applied + via ``pg_autoctl set node region`` (see :ref:`pg_autoctl_set_node_region`). + Purely informational: shown as its own column by ``pg_autoctl watch`` in + the verbose and higher policies, and does not currently affect any + failover or quorum decision. ``[options]`` ^^^^^^^^^^^^^ @@ -260,7 +257,7 @@ The supervisor that ``pg_autoctl node run`` exec's into watches the ini file for changes. When it detects a write it re-reads the file and converges any **mutable** fields without restarting the node or interrupting replication: -``candidate_priority`` and ``replication_quorum`` +``candidate_priority``, ``replication_quorum``, and ``region`` Applied by calling ``pg_autoctl set node`` against the running node. ``ssl``, ``ca_file``, ``cert_file``, ``key_file`` diff --git a/docs/ref/pg_autoctl_set.rst b/docs/ref/pg_autoctl_set.rst index de66c88d4..466bb5d9a 100644 --- a/docs/ref/pg_autoctl_set.rst +++ b/docs/ref/pg_autoctl_set.rst @@ -11,3 +11,4 @@ pg_autoctl set - Set a pg_auto_failover node, or formation setting pg_autoctl_set_formation_number_sync_standbys pg_autoctl_set_node_replication_quorum pg_autoctl_set_node_candidate_priority + pg_autoctl_set_node_region diff --git a/docs/ref/pg_autoctl_set_node_region.rst b/docs/ref/pg_autoctl_set_node_region.rst new file mode 100644 index 000000000..89898ba12 --- /dev/null +++ b/docs/ref/pg_autoctl_set_node_region.rst @@ -0,0 +1,98 @@ +.. _pg_autoctl_set_node_region: + +pg_autoctl set node region +=========================== + +pg_autoctl set region - set region property on the monitor + +Synopsis +-------- + +This command sets the ``pg_autoctl`` region label for a given node:: + + usage: pg_autoctl set node region [ --pgdata ] [ --json ] [ --formation ] [ --name ] + + --pgdata path to data directory + --formation pg_auto_failover formation + --name pg_auto_failover node name + --json output data in the JSON format + +Description +----------- + +Sets the data-centre or availability-zone label for a node that is already +registered on the monitor. Unlike :ref:`pg_autoctl_set_node_candidate_priority` +and :ref:`pg_autoctl_set_node_replication_quorum`, this never triggers a +failover or a replication settings change on the primary: region is purely +informational, displayed by :ref:`pg_autoctl_watch` in the verbose and +higher policies. The command takes effect immediately, with no wait. + +This is also the mechanism ``pg_autoctl node run`` uses to apply a live edit +of the ``region`` property in a ``pg_autoctl_node.ini`` file — see +:ref:`pg_autoctl_node` for the full ``[settings]`` reference. + +See also :ref:`pg_autoctl_show_settings` for the full list of replication +settings. + +Options +------- + +--pgdata + + Location of the Postgres node being managed locally. Defaults to the + environment variable ``PGDATA``. Use ``--monitor`` to connect to a monitor + from anywhere, rather than the monitor URI used by a local Postgres node + managed with ``pg_autoctl``. + +--json + + Output JSON formatted data. + +--formation + + Show replication settings for given formation. Defaults to ``default``. + +--name + + Show replication settings for given node, selected by name. + +Environment +----------- + +PGDATA + + Postgres directory location. Can be used instead of the ``--pgdata`` + option. + +PG_AUTOCTL_MONITOR + + Postgres URI to connect to the monitor node, can be used instead of the + ``--monitor`` option. + +XDG_CONFIG_HOME + + The pg_autoctl command stores its configuration files in the standard + place XDG_CONFIG_HOME. See the `XDG Base Directory Specification`__. + + __ https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +XDG_DATA_HOME + + The pg_autoctl command stores its internal states files in the standard + place XDG_DATA_HOME, which defaults to ``~/.local/share``. See the `XDG + Base Directory Specification`__. + + __ https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +Examples +-------- + +:: + + $ pg_autoctl set node region --name node1 dc2 + dc2 + + $ pg_autoctl set node region --name node1 dc2 --json + { + "region": "dc2" + } diff --git a/src/bin/pg_autoctl/cli_get_set_properties.c b/src/bin/pg_autoctl/cli_get_set_properties.c index 7999977ac..f080cf55e 100644 --- a/src/bin/pg_autoctl/cli_get_set_properties.c +++ b/src/bin/pg_autoctl/cli_get_set_properties.c @@ -16,15 +16,18 @@ static bool get_node_replication_settings(NodeReplicationSettings *settings); static void cli_get_node_replication_quorum(int argc, char **argv); static void cli_get_node_candidate_priority(int argc, char **argv); +static void cli_get_node_region(int argc, char **argv); static void cli_get_formation_number_sync_standbys(int argc, char **argv); static void cli_set_node_replication_quorum(int argc, char **argv); static void cli_set_node_candidate_priority(int argc, char **argv); +static void cli_set_node_region(int argc, char **argv); static void cli_set_node_metadata(int argc, char **argv); static void cli_set_formation_number_sync_standbys(int arc, char **argv); static bool set_node_candidate_priority(Keeper *keeper, int candidatePriority); static bool set_node_replication_quorum(Keeper *keeper, bool replicationQuorum); +static bool set_node_region(Keeper *keeper, const char *region); static bool set_formation_number_sync_standbys(Monitor *monitor, char *formation, int groupId, @@ -52,10 +55,22 @@ CommandLine get_node_candidate_priority = cli_get_name_getopts, cli_get_node_candidate_priority); +CommandLine get_node_region = + make_command("region", + "get region property from the monitor", + " [ --pgdata ] [ --json ] [ --formation ] [ --name ]", + " --pgdata path to data directory\n" + " --formation pg_auto_failover formation\n" + " --name pg_auto_failover node name\n" + " --json output data in the JSON format\n", + cli_get_name_getopts, + cli_get_node_region); + static CommandLine *get_node_subcommands[] = { &get_node_replication_quorum, &get_node_candidate_priority, + &get_node_region, NULL }; @@ -144,11 +159,24 @@ static CommandLine set_node_metadata_command = cli_node_metadata_getopts, cli_set_node_metadata); +static CommandLine set_node_region_command = + make_command("region", + "set region property on the monitor", + " [ --pgdata ] [ --json ] [ --formation ] [ --name ] " + "", + " --pgdata path to data directory\n" + " --formation pg_auto_failover formation\n" + " --name pg_auto_failover node name\n" + " --json output data in the JSON format\n", + cli_get_name_getopts, + cli_set_node_region); + static CommandLine *set_node_subcommands[] = { &set_node_metadata_command, &set_node_replication_quorum_command, &set_node_candidate_priority_command, + &set_node_region_command, NULL }; @@ -287,6 +315,48 @@ cli_get_node_candidate_priority(int argc, char **argv) } +/* + * cli_get_node_region function prints the region property of this node to + * standard output. + */ +static void +cli_get_node_region(int argc, char **argv) +{ + Keeper keeper = { 0 }; + Monitor *monitor = &(keeper.monitor); + char region[NAMEDATALEN] = { 0 }; + + keeper.config = keeperOptions; + + (void) cli_monitor_init_from_option_or_config(monitor, &(keeper.config)); + + /* grab --name from either the command options or the configuration file */ + (void) cli_ensure_node_name(&keeper); + + if (!monitor_get_node_region(monitor, keeper.config.name, + region, sizeof(region))) + { + log_error("Unable to get region value from monitor"); + exit(EXIT_CODE_MONITOR); + } + + if (outputJSON) + { + JSON_Value *js = json_value_init_object(); + JSON_Object *jsObj = json_value_get_object(js); + + json_object_set_string(jsObj, "name", keeper.config.name); + json_object_set_string(jsObj, "region", region); + + (void) cli_pprint_json(js); + } + else + { + fformat(stdout, "%s\n", region); + } +} + + /* * cli_get_formation_settings function prints the replication settings for a * given formation. @@ -474,6 +544,62 @@ cli_set_node_candidate_priority(int argc, char **argv) } +/* + * cli_set_node_region sets the region property on the monitor for current + * pg_autoctl node. + */ +static void +cli_set_node_region(int argc, char **argv) +{ + Keeper keeper = { 0 }; + Monitor *monitor = &(keeper.monitor); + + keeper.config = keeperOptions; + + if (argc != 1) + { + log_error("Failed to parse command line arguments: " + "got %d when 1 is expected", + argc); + commandline_help(stderr); + exit(EXIT_CODE_BAD_ARGS); + } + + const char *region = argv[0]; + + if (IS_EMPTY_STRING_BUFFER(region)) + { + log_error("region value must not be empty"); + exit(EXIT_CODE_BAD_ARGS); + } + + (void) cli_monitor_init_from_option_or_config(monitor, &(keeper.config)); + + /* grab --name from either the command options or the configuration file */ + (void) cli_ensure_node_name(&keeper); + + if (!set_node_region(&keeper, region)) + { + /* errors have already been logged */ + exit(EXIT_CODE_MONITOR); + } + + if (outputJSON) + { + JSON_Value *js = json_value_init_object(); + JSON_Object *jsObj = json_value_get_object(js); + + json_object_set_string(jsObj, "region", region); + + (void) cli_pprint_json(js); + } + else + { + fformat(stdout, "%s\n", region); + } +} + + /* * cli_set_node_metadata sets this pg_autoctl node name, hostname, and port on * the monitor. That's the hostname that is used by every other node in the @@ -818,6 +944,30 @@ set_node_replication_quorum(Keeper *keeper, bool replicationQuorum) } +/* + * set_node_region sets the region label on the monitor. Unlike + * candidate-priority and replication-quorum, region is purely informational + * and never triggers an apply_settings transition on the primary, so there + * is nothing to wait for after the monitor call succeeds. + */ +static bool +set_node_region(Keeper *keeper, const char *region) +{ + KeeperConfig *config = &(keeper->config); + + if (!monitor_set_node_region(&(keeper->monitor), + config->formation, + config->name, + (char *) region)) + { + log_error("Failed to set \"region\" to \"%s\".", region); + return false; + } + + return true; +} + + /* * set_node_replication_quorum sets the number_sync_standbys on the monitor, * and if we have more than one node registered in the target formation, waits diff --git a/src/bin/pg_autoctl/monitor.c b/src/bin/pg_autoctl/monitor.c index e7d6d146e..0d517ee1b 100644 --- a/src/bin/pg_autoctl/monitor.c +++ b/src/bin/pg_autoctl/monitor.c @@ -72,6 +72,14 @@ typedef struct NodeReplicationSettingsParseContext bool parsedOK; } NodeReplicationSettingsParseContext; +typedef struct NodeRegionParseContext +{ + char sqlstate[SQLSTATE_LENGTH]; + char *region; + size_t size; + bool parsedOK; +} NodeRegionParseContext; + typedef struct CurrentNodeStateContext { char sqlstate[SQLSTATE_LENGTH]; @@ -113,6 +121,7 @@ static void parseNodeResult(void *ctx, PGresult *result); static void parseNodeArray(void *ctx, PGresult *result); static void parseNodeState(void *ctx, PGresult *result); static void parseNodeReplicationSettings(void *ctx, PGresult *result); +static void parseNodeRegion(void *ctx, PGresult *result); static bool parseCurrentNodeState(PGresult *result, int rowNumber, CurrentNodeState *nodeState); static bool parseCurrentNodeStateArray(CurrentNodeStateArray *nodesArray, @@ -1106,6 +1115,105 @@ monitor_set_node_replication_quorum(Monitor *monitor, } +/* + * monitor_set_node_region updates the monitor on the changes in the node + * region label. + */ +bool +monitor_set_node_region(Monitor *monitor, + char *formation, char *name, + char *region) +{ + PGSQL *pgsql = &monitor->pgsql; + const char *sql = + "SELECT pgautofailover.set_node_region($1, $2, $3)"; + int paramCount = 3; + Oid paramTypes[3] = { TEXTOID, TEXTOID, TEXTOID }; + const char *paramValues[3]; + bool success = true; + + paramValues[0] = formation; + paramValues[1] = name; + paramValues[2] = region; + + if (!pgsql_execute_with_params(pgsql, sql, paramCount, paramTypes, + paramValues, NULL, NULL)) + { + log_error("Failed to update node region on node \"%s\" " + "in formation \"%s\" to \"%s\"", + name, formation, region); + + success = false; + } + + return success; +} + + +/* + * monitor_get_node_region retrieves the region label of a node from the + * monitor. + */ +bool +monitor_get_node_region(Monitor *monitor, + char *name, + char *region, size_t size) +{ + PGSQL *pgsql = &monitor->pgsql; + const char *sql = + "SELECT region FROM pgautofailover.node WHERE nodename = $1"; + + int paramCount = 1; + Oid paramTypes[1] = { TEXTOID }; + const char *paramValues[1]; + + NodeRegionParseContext parseContext = { { 0 }, region, size, false }; + + paramValues[0] = name; + + if (!pgsql_execute_with_params(pgsql, sql, + paramCount, paramTypes, paramValues, + &parseContext, parseNodeRegion)) + { + log_error("Failed to retrieve region for node \"%s\".", name); + + return false; + } + + return parseContext.parsedOK; +} + + +/* + * parseNodeRegion parses the region label from query output. + */ +static void +parseNodeRegion(void *ctx, PGresult *result) +{ + NodeRegionParseContext *context = (NodeRegionParseContext *) ctx; + + if (PQntuples(result) != 1) + { + log_error("Query returned %d rows, expected 1", PQntuples(result)); + context->parsedOK = false; + return; + } + + if (PQnfields(result) != 1) + { + log_error("Query returned %d columns, expected 1", PQnfields(result)); + context->parsedOK = false; + return; + } + + char *value = PQgetvalue(result, 0, 0); + + strlcpy(context->region, value, context->size); + + context->parsedOK = true; +} + + /* * monitor_get_node_replication_settings retrieves replication settings * from the monitor. diff --git a/src/bin/pg_autoctl/monitor.h b/src/bin/pg_autoctl/monitor.h index 01285aac4..fc27dc6e3 100644 --- a/src/bin/pg_autoctl/monitor.h +++ b/src/bin/pg_autoctl/monitor.h @@ -157,6 +157,12 @@ bool monitor_set_node_candidate_priority(Monitor *monitor, bool monitor_set_node_replication_quorum(Monitor *monitor, char *formation, char *name, bool replicationQuorum); +bool monitor_set_node_region(Monitor *monitor, + char *formation, char *name, + char *region); +bool monitor_get_node_region(Monitor *monitor, + char *name, + char *region, size_t size); bool monitor_get_formation_number_sync_standbys(Monitor *monitor, char *formation, int *numberSyncStandbys); bool monitor_set_formation_number_sync_standbys(Monitor *monitor, char *formation, diff --git a/src/monitor/expected/node_active_protocol.out b/src/monitor/expected/node_active_protocol.out index 203e63f6e..91989cfa2 100644 --- a/src/monitor/expected/node_active_protocol.out +++ b/src/monitor/expected/node_active_protocol.out @@ -596,3 +596,25 @@ assigned_candidate_priority | 100 assigned_replication_quorum | t RESET pgautofailover.startup_grace_period; +-- ── test_007: set_node_region ──────────────────────────────────────────────── +-- +-- region is purely informational: setting it must not touch any FSM state, +-- and must be rejected for an unknown node or an empty value. +SELECT region FROM pgautofailover.node WHERE nodename = 'node1'; +-[ RECORD 1 ]--- +region | default + +SELECT pgautofailover.set_node_region('fsm_test', 'node1', 'dc2'); +-[ RECORD 1 ]---+-- +set_node_region | t + +SELECT region FROM pgautofailover.node WHERE nodename = 'node1'; +-[ RECORD 1 ] +region | dc2 + +-- unknown node: error +SELECT pgautofailover.set_node_region('fsm_test', 'unknown_node', 'dc2'); +ERROR: node "unknown_node" is not registered in formation "fsm_test" +-- empty region: error +SELECT pgautofailover.set_node_region('fsm_test', 'node1', ''); +ERROR: invalid value for region: expected a non-empty string diff --git a/src/monitor/node_active_protocol.c b/src/monitor/node_active_protocol.c index c75049cec..a0d1cf128 100644 --- a/src/monitor/node_active_protocol.c +++ b/src/monitor/node_active_protocol.c @@ -68,6 +68,7 @@ PG_FUNCTION_INFO_V1(start_maintenance); PG_FUNCTION_INFO_V1(stop_maintenance); PG_FUNCTION_INFO_V1(set_node_candidate_priority); PG_FUNCTION_INFO_V1(set_node_replication_quorum); +PG_FUNCTION_INFO_V1(set_node_region); PG_FUNCTION_INFO_V1(synchronous_standby_names); PG_FUNCTION_INFO_V1(testing_lock_formation); PG_FUNCTION_INFO_V1(testing_lock_node_group); @@ -2433,6 +2434,66 @@ set_node_replication_quorum(PG_FUNCTION_ARGS) } +/* + * set_node_region sets the node region property. Unlike candidate_priority + * and replication_quorum, region is purely an informational label: it does + * not affect replication settings or failover eligibility, so no FSM + * transition is needed on the primary after updating it. + */ +Datum +set_node_region(PG_FUNCTION_ARGS) +{ + checkPgAutoFailoverVersion(); + + text *formationIdText = PG_GETARG_TEXT_P(0); + char *formationId = text_to_cstring(formationIdText); + + text *nodeNameText = PG_GETARG_TEXT_P(1); + char *nodeName = text_to_cstring(nodeNameText); + + text *regionText = PG_GETARG_TEXT_P(2); + char *region = text_to_cstring(regionText); + + AutoFailoverNode *currentNode = + LockNodeGroupAndFetchByName(formationId, nodeName); + + if (currentNode == NULL) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("node \"%s\" is not registered in formation \"%s\"", + nodeName, formationId))); + } + + if (region == NULL || region[0] == '\0') + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid value for region: expected a non-empty " + "string"))); + } + + currentNode->region = region; + + ReportAutoFailoverNodeRegion(currentNode->nodeId, + currentNode->nodeHost, + currentNode->nodePort, + currentNode->region); + + char message[BUFSIZE]; + + LogAndNotifyMessage( + message, BUFSIZE, + "Updating region to \"%s\" for " NODE_FORMAT, + currentNode->region, + NODE_FORMAT_ARGS(currentNode)); + + NotifyStateChange(currentNode, message); + + PG_RETURN_BOOL(true); +} + + /* * update_node_metadata allows to update a node's nodename, hostname, and port. * diff --git a/src/monitor/node_metadata.c b/src/monitor/node_metadata.c index 73675ee90..a40ccb4b4 100644 --- a/src/monitor/node_metadata.c +++ b/src/monitor/node_metadata.c @@ -1729,6 +1729,51 @@ ReportAutoFailoverNodeReplicationSetting(int64 nodeid, } +/* + * ReportAutoFailoverNodeRegion persists the region label of a node. + * + * We use SPI to automatically handle triggers, function calls, etc. + */ +void +ReportAutoFailoverNodeRegion(int64 nodeid, + char *nodeHost, int nodePort, + char *region) +{ + Oid argTypes[] = { + TEXTOID, /* region */ + INT8OID, /* nodeid */ + TEXTOID, /* nodehost */ + INT4OID /* nodeport */ + }; + + Datum argValues[] = { + CStringGetTextDatum(region), /* region */ + Int64GetDatum(nodeid), /* nodeid */ + CStringGetTextDatum(nodeHost), /* nodehost */ + Int32GetDatum(nodePort) /* nodeport */ + }; + const int argCount = sizeof(argValues) / sizeof(argValues[0]); + + const char *updateQuery = + "UPDATE " AUTO_FAILOVER_NODE_TABLE + " SET region = $1 " + " WHERE nodeid = $2 and nodehost = $3 AND nodeport = $4"; + + SPI_connect(); + + int spiStatus = SPI_execute_with_args(updateQuery, + argCount, argTypes, argValues, + NULL, false, 0); + + if (spiStatus != SPI_OK_UPDATE) + { + elog(ERROR, "could not update " AUTO_FAILOVER_NODE_TABLE); + } + + SPI_finish(); +} + + /* * UpdateAutoFailoverNodeMetadata updates a node registration to a possibly new * nodeName, nodeHost, and nodePort. Those are NULL (or zero) when not changed. diff --git a/src/monitor/node_metadata.h b/src/monitor/node_metadata.h index e94685bbf..407de0a7d 100644 --- a/src/monitor/node_metadata.h +++ b/src/monitor/node_metadata.h @@ -234,6 +234,10 @@ extern void ReportAutoFailoverNodeReplicationSetting(int64 nodeid, int nodePort, int candidatePriority, bool replicationQuorum); +extern void ReportAutoFailoverNodeRegion(int64 nodeid, + char *nodeHost, + int nodePort, + char *region); extern void UpdateAutoFailoverNodeMetadata(int64 nodeid, char *nodeName, char *nodeHost, diff --git a/src/monitor/pgautofailover.sql b/src/monitor/pgautofailover.sql index bded410b2..ce2bda9e8 100644 --- a/src/monitor/pgautofailover.sql +++ b/src/monitor/pgautofailover.sql @@ -803,6 +803,22 @@ grant execute on function pgautofailover.set_node_replication_quorum(text, text, bool) to autoctl_node; +CREATE FUNCTION pgautofailover.set_node_region + ( + IN formation_id text, + IN node_name text, + IN region text + ) +RETURNS bool LANGUAGE C STRICT SECURITY DEFINER +AS 'MODULE_PATHNAME', $$set_node_region$$; + +comment on function pgautofailover.set_node_region(text, text, text) + is 'sets the region label for a node, identifying its data-centre or availability zone'; + +grant execute on function + pgautofailover.set_node_region(text, text, text) + to autoctl_node; + create function pgautofailover.synchronous_standby_names ( diff --git a/src/monitor/sql/node_active_protocol.sql b/src/monitor/sql/node_active_protocol.sql index 860baab35..35b0c9992 100644 --- a/src/monitor/sql/node_active_protocol.sql +++ b/src/monitor/sql/node_active_protocol.sql @@ -391,3 +391,20 @@ SELECT * current_lsn => '0/3000'); RESET pgautofailover.startup_grace_period; + +-- ── test_007: set_node_region ──────────────────────────────────────────────── +-- +-- region is purely informational: setting it must not touch any FSM state, +-- and must be rejected for an unknown node or an empty value. + +SELECT region FROM pgautofailover.node WHERE nodename = 'node1'; + +SELECT pgautofailover.set_node_region('fsm_test', 'node1', 'dc2'); + +SELECT region FROM pgautofailover.node WHERE nodename = 'node1'; + +-- unknown node: error +SELECT pgautofailover.set_node_region('fsm_test', 'unknown_node', 'dc2'); + +-- empty region: error +SELECT pgautofailover.set_node_region('fsm_test', 'node1', ''); From ec6a259cc00fb93e6bcd47973aa9e41bff14421f Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Sat, 25 Jul 2026 00:26:53 +0200 Subject: [PATCH 3/5] pgaftest: nodeini set/get DSL primitive + interactive nodeini/compose commands Testing region's node.ini live-apply path required editing a node's host-side .ini file directly (it's bind-mounted read-only inside the node's own container, so this can't go through exec/compose) -- there was no DSL primitive for that. - New `nodeini set ` / `nodeini get ` DSL commands (test_spec.h/.l/.y), sharing one file-I/O implementation (nodeini_write_value/nodeini_read_value in test_runner.c) between the DSL command execution and the new interactive commands below. - New interactive `pgaftest nodeini get|set` command, mirroring the existing `pgaftest network`/`pgaftest sql` interactive commands. - New interactive `pgaftest compose start|stop|kill|down|exec` command set, wrapping `docker compose ...` directly so the -p/-f flags don't need to be typed by hand from the tmux bottom pane -- previously documented as a manual docker compose invocation only. - docs/ref/pgaftest.rst updated: synopsis, new `pgaftest_nodeini`/ `pgaftest_compose` sub-command sections, the "Node .ini file access" DSL reference entry (with a note on Docker Desktop for macOS's virtiofs sometimes not relaying host-originated inotify events -- see the nodespec.c commit for how that's handled), and the "Manually starting/stopping a node" section now leads with the built-in command. - tests/tap/specs/config_get_set.pgaf: CLI round-trip (test_003_region_cli_roundtrip) and node.ini automated file-watch coverage (test_004_region_nodeini_live_apply) using the new `nodeini set`/`nodeini get` commands. --- docs/ref/pgaftest.rst | 84 +- src/bin/pgaftest/cli_indent.c | 14 + src/bin/pgaftest/cli_root.c | 283 +++++ src/bin/pgaftest/test_runner.c | 249 ++++ src/bin/pgaftest/test_runner.h | 6 + src/bin/pgaftest/test_spec.h | 11 + src/bin/pgaftest/test_spec_parse.c | 1625 ++++++++++++++------------- src/bin/pgaftest/test_spec_parse.h | 286 ++--- src/bin/pgaftest/test_spec_parse.y | 36 +- src/bin/pgaftest/test_spec_scan.c | 1355 +++++++++++----------- src/bin/pgaftest/test_spec_scan.l | 2 + tests/tap/specs/config_get_set.pgaf | 38 +- 12 files changed, 2381 insertions(+), 1608 deletions(-) diff --git a/docs/ref/pgaftest.rst b/docs/ref/pgaftest.rst index 559ce3027..7eed400bc 100644 --- a/docs/ref/pgaftest.rst +++ b/docs/ref/pgaftest.rst @@ -132,9 +132,20 @@ Manually starting/stopping a node ``compose start `` / ``compose stop `` (see :ref:`pgaftest-failure-semantics` below) are DSL keywords understood only inside a -spec's ``step { }`` block — there is no standalone ``pgaftest compose ...`` -command to run them ad hoc from the bottom pane. To do the same thing -interactively, without adding a step to the spec, use plain Docker Compose +spec's ``step { }`` block. To do the same thing ad hoc from the bottom pane — +without adding a step to the spec — use :ref:`pgaftest_compose`:: + + pgaftest compose stop node2 + pgaftest compose start node2 + pgaftest compose kill node2 + pgaftest compose exec node2 pg_autoctl show state + +``pgaftest compose`` resolves the spec/work-dir the same way every other +interactive sub-command does (``PGAFTEST_SPEC`` / ``PGAFTEST_HOST_WORK_DIR`` +inside the container, or ``--work-dir`` outside it), so it works both from +the ``pgaftest tmux`` bottom pane and directly on the host. + +Equivalently, the same thing can always be done with plain Docker Compose directly. The ``pgaftest`` service container already exports ``COMPOSE_PROJECT_NAME`` for you, so only ``-f`` is needed to point at the compose file, which lives at ``$PGAFTEST_HOST_WORK_DIR`` rather than the @@ -179,6 +190,8 @@ Synopsis pgaftest show compose|spec|steps|step|state [] pgaftest sql { } pgaftest network disconnect|connect + pgaftest nodeini get | set + pgaftest compose start|stop|kill | down | exec pgaftest indent pgaftest help @@ -320,6 +333,44 @@ Sub-commands for inspecting a spec or a running session: ``pg_autoctl show state`` output for the whole formation (container command). +.. _pgaftest_nodeini: + +``pgaftest nodeini`` +~~~~~~~~~~~~~~~~~~~~ + +Read or edit a node's host-side ``.ini`` ``[settings]`` entry directly, +bypassing ``pg_autoctl`` entirely — the interactive mirror of the ``nodeini +get``/``nodeini set`` DSL commands documented under "Node .ini file access" +further down this page:: + + pgaftest nodeini get node1 region + pgaftest nodeini set node1 region dc2 + +``set`` exercises the same supervisor file-watch live-apply path as the DSL +form, the same as hand-editing the file would; ``get`` prints the value +currently on disk, which may lag what ``pg_autoctl get node ...`` reports +from the monitor if the supervisor hasn't picked up a recent change yet (or, +under Docker Desktop for macOS, may never converge — same caveat as the DSL +form). + +.. _pgaftest_compose: + +``pgaftest compose`` +~~~~~~~~~~~~~~~~~~~~~ + +Thin wrappers around ``docker compose`` for the running stack, so you don't +need to remember the ``-p``/``-f`` flags by hand:: + + pgaftest compose start # up -d --no-recreate --no-deps + pgaftest compose stop # graceful (SIGTERM, grace period) + pgaftest compose kill # immediate SIGKILL + pgaftest compose down # docker compose down (no teardown{}) + pgaftest compose exec # interactive TTY, like `docker compose exec -it` + +``pgaftest compose down`` only runs ``docker compose down`` — it does not run +the spec's ``teardown {}`` block first. Use ``pgaftest cluster down`` when you +want the teardown block to run too. + Spec file format ---------------- @@ -479,6 +530,33 @@ Commands inside ``setup``, ``teardown``, and ``step`` blocks compose kill compose down +.. _pgaftest-nodeini-dsl: + +**Node .ini file access** + +.. code-block:: text + + nodeini set + nodeini get + +Reads or edits ````'s host-side ``pg_autoctl_node.ini`` ``[settings]`` +entry directly on the host side — the file is bind-mounted read-only inside +the node's own container, so this can't go through ``exec``/``compose``. +``nodeini set`` exercises the supervisor's automatic file-watch live-apply +path (``nodespec_watcher_check()``, on a ~100ms tick), distinct from calling +``pg_autoctl set node ...`` directly; ``nodeini get `` +asserts the on-disk value equals ````, distinct from ``pg_autoctl get +node ...`` which queries the running node/monitor instead of the file. + +.. note:: + Under Docker Desktop for macOS (virtiofs), a host-side ``nodeini set`` + syncs file *content* into the container immediately, but does not + reliably raise the inotify event the supervisor's watcher listens for — + so the change may never be picked up locally. This is a virtiofs/gRPC-fuse + gap in relaying host-originated filesystem events into the Linux guest, + not a bug in ``nodespec.c``. Native Linux Docker (including CI runners) + has no such VM boundary and picks the change up within one tick. + **PostgreSQL control** .. code-block:: text diff --git a/src/bin/pgaftest/cli_indent.c b/src/bin/pgaftest/cli_indent.c index 797e1990d..e849951fc 100644 --- a/src/bin/pgaftest/cli_indent.c +++ b/src/bin/pgaftest/cli_indent.c @@ -984,6 +984,20 @@ print_cmd(FILE *out, const TestCmd *cmd, int indent) break; } + case CMD_NODEINI_SET: + { + fformat(out, "%*snodeini set %s %s %s\n", + indent, "", cmd->service, cmd->state, cmd->args); + break; + } + + case CMD_NODEINI_GET: + { + fformat(out, "%*snodeini get %s %s %s\n", + indent, "", cmd->service, cmd->state, cmd->args); + break; + } + case CMD_COMPOSE_DOWN: { fformat(out, "%*scompose down\n", indent, ""); diff --git a/src/bin/pgaftest/cli_root.c b/src/bin/pgaftest/cli_root.c index 9924acac5..36ce655a2 100644 --- a/src/bin/pgaftest/cli_root.c +++ b/src/bin/pgaftest/cli_root.c @@ -969,6 +969,221 @@ cli_network(int argc, char **argv) } +/* ----------------------------------------------------------------------- + * pgaftest nodeini get + * pgaftest nodeini set + * ----------------------------------------------------------------------- */ +static void +cli_nodeini(int argc, char **argv) +{ + bool isGet = (argc >= 1 && strcmp(argv[0], "get") == 0); + bool isSet = (argc >= 1 && strcmp(argv[0], "set") == 0); + + if ((!isGet && !isSet) || + (isGet && argc < 3) || + (isSet && argc < 4)) + { + log_error("Usage: pgaftest nodeini get " + " | pgaftest nodeini set "); + exit(EXIT_CODE_BAD_ARGS); + } + + const char *nodeName = argv[1]; + const char *key = argv[2]; + + resolve_interactive_context(); + + if (pgaftestOpts.specFile[0] == '\0') + { + log_error("No spec file: pass one as argument or set PGAFTEST_SPEC"); + exit(EXIT_CODE_BAD_ARGS); + } + + TestSpec *spec = parse_test_spec(pgaftestOpts.specFile); + if (!spec) + { + exit(1); + } + + if (isSet) + { + const char *value = argv[3]; + bool ok = runner_nodeini_set(spec, pgaftestOpts.workDir, + nodeName, key, value); + exit(ok ? 0 : 1); + } + else + { + char value[4096] = ""; + bool ok = runner_nodeini_get(spec, pgaftestOpts.workDir, + nodeName, key, value, sizeof(value)); + if (ok) + { + fformat(stdout, "%s\n", value); + } + exit(ok ? 0 : 1); + } +} + + +/* ----------------------------------------------------------------------- + * pgaftest compose start|stop|kill|down|exec — thin wrappers around + * `docker compose ...` for the running stack, sparing users from having to + * remember the -p/-f flags by hand (see the "Manually starting/stopping a + * node" section in docs/ref/pgaftest.rst). + * ----------------------------------------------------------------------- */ +static bool +compose_base_cmd(char *buf, int buflen) +{ + resolve_interactive_context(); + + if (pgaftestOpts.workDir[0] == '\0') + { + log_error("Cannot determine work directory: " + "provide --work-dir, a spec file argument, " + "or run from inside the pgaftest container"); + return false; + } + + const char *base = strrchr(pgaftestOpts.workDir, '/'); + const char *projectName = (base && *(base + 1)) ? base + 1 + : pgaftestOpts.workDir; + + sformat(buf, buflen, "docker compose -p %s -f %s/docker-compose.yml", + projectName, pgaftestOpts.workDir); + return true; +} + + +static void +cli_compose_start(int argc, char **argv) +{ + if (argc < 1) + { + log_error("Usage: pgaftest compose start "); + exit(EXIT_CODE_BAD_ARGS); + } + + char base[2048]; + if (!compose_base_cmd(base, sizeof(base))) + { + exit(1); + } + + /* + * `up -d --no-recreate --no-deps` rather than `start`: `start` only + * works for already-created containers, but a node declared with + * "launch deferred" is never created during the initial compose up. + */ + char cmd[2200]; + sformat(cmd, sizeof(cmd), "%s up -d --no-recreate --no-deps %s", + base, argv[0]); + + int rc = system(cmd); /* IGNORE-BANNED */ + exit(rc == 0 ? 0 : 1); +} + + +static void +cli_compose_stop(int argc, char **argv) +{ + if (argc < 1) + { + log_error("Usage: pgaftest compose stop "); + exit(EXIT_CODE_BAD_ARGS); + } + + char base[2048]; + if (!compose_base_cmd(base, sizeof(base))) + { + exit(1); + } + + char cmd[2200]; + sformat(cmd, sizeof(cmd), "%s stop %s", base, argv[0]); + + int rc = system(cmd); /* IGNORE-BANNED */ + exit(rc == 0 ? 0 : 1); +} + + +static void +cli_compose_kill(int argc, char **argv) +{ + if (argc < 1) + { + log_error("Usage: pgaftest compose kill "); + exit(EXIT_CODE_BAD_ARGS); + } + + char base[2048]; + if (!compose_base_cmd(base, sizeof(base))) + { + exit(1); + } + + char cmd[2200]; + sformat(cmd, sizeof(cmd), "%s kill %s", base, argv[0]); + + int rc = system(cmd); /* IGNORE-BANNED */ + exit(rc == 0 ? 0 : 1); +} + + +static void +cli_compose_down(int argc, char **argv) +{ + (void) argc; + (void) argv; + + char base[2048]; + if (!compose_base_cmd(base, sizeof(base))) + { + exit(1); + } + + char cmd[2200]; + sformat(cmd, sizeof(cmd), "%s down", base); + + int rc = system(cmd); /* IGNORE-BANNED */ + exit(rc == 0 ? 0 : 1); +} + + +static void +cli_compose_exec(int argc, char **argv) +{ + if (argc < 2) + { + log_error("Usage: pgaftest compose exec "); + exit(EXIT_CODE_BAD_ARGS); + } + + char base[2048]; + if (!compose_base_cmd(base, sizeof(base))) + { + exit(1); + } + + /* re-join argv[1..] into a single shell-visible argument string */ + char rest[4096] = ""; + for (int i = 1; i < argc; i++) + { + if (i > 1) + { + strlcat(rest, " ", sizeof(rest)); + } + strlcat(rest, argv[i], sizeof(rest)); + } + + char cmd[8192]; + sformat(cmd, sizeof(cmd), "%s exec -it %s %s", base, argv[0], rest); + + int rc = system(cmd); /* IGNORE-BANNED */ + exit(rc == 0 ? 0 : 1); +} + + /* ----------------------------------------------------------------------- * Root command table * ----------------------------------------------------------------------- */ @@ -1144,6 +1359,70 @@ static CommandLine network_command = " disconnect Sever the node's network access\n", pgaftest_getopts, cli_network); +static CommandLine nodeini_command = + make_command("nodeini", + "Read or edit a node's host-side .ini [settings] entry directly (interactive)", + "get | set ", + " get Print the current value\n" + " set Write a new value (exercises the\n" + " supervisor's file-watch live-apply path)\n", + pgaftest_getopts, cli_nodeini); + +static CommandLine compose_start_command = + make_command("start", + "Start a stopped or deferred node", + "", + "", + pgaftest_getopts, cli_compose_start); + +static CommandLine compose_stop_command = + make_command("stop", + "Stop a running node (graceful)", + "", + "", + pgaftest_getopts, cli_compose_stop); + +static CommandLine compose_kill_command = + make_command("kill", + "Kill a running node (SIGKILL, no grace)", + "", + "", + pgaftest_getopts, cli_compose_kill); + +static CommandLine compose_down_command = + make_command("down", + "Tear down the compose stack (no teardown{} block; see `pgaftest down`)", + "", + "", + pgaftest_getopts, cli_compose_down); + +static CommandLine compose_exec_command = + make_command("exec", + "Run a command inside a node's container (interactive TTY)", + " ", + "", + pgaftest_getopts, cli_compose_exec); + +static CommandLine *compose_subcommands[] = { + &compose_start_command, + &compose_stop_command, + &compose_kill_command, + &compose_down_command, + &compose_exec_command, + NULL +}; + +static CommandLine compose_command = + make_command_set("compose", + "Control individual compose services directly (interactive)", + " [args...]", + " start Start a stopped or deferred node\n" + " stop Stop a running node (graceful)\n" + " kill Kill a running node (SIGKILL)\n" + " down Tear down the compose stack\n" + " exec Run a command inside a node's container\n", + pgaftest_getopts, compose_subcommands); + static void cli_help(int argc, char **argv) { @@ -1186,6 +1465,8 @@ static CommandLine *root_subcommands[] = { &indent_command, &sql_command, &network_command, + &nodeini_command, + &compose_command, &help_command, &internal_setup_command, &pgaftest_demo_command, @@ -1204,6 +1485,8 @@ CommandLine pgaftest_root = " indent Rewrite a spec with canonical indentation\n" " sql Run SQL on a node and print the result\n" " network Connect or disconnect a node from the network\n" + " nodeini Read or edit a node's .ini file directly\n" + " compose Control individual compose services (start/stop/kill/exec)\n" " help Show this help message\n" " demo Demo application\n", pgaftest_getopts, root_subcommands); diff --git a/src/bin/pgaftest/test_runner.c b/src/bin/pgaftest/test_runner.c index d64a4ba57..3f54d81df 100644 --- a/src/bin/pgaftest/test_runner.c +++ b/src/bin/pgaftest/test_runner.c @@ -146,6 +146,20 @@ test_cmd_print(FILE *f, const TestCmd *cmd, int indent) break; } + case CMD_NODEINI_SET: + { + fprintf(f, "%snodeini set %s %s %s\n", /* IGNORE-BANNED */ + pad, cmd->service, cmd->state, cmd->args); + break; + } + + case CMD_NODEINI_GET: + { + fprintf(f, "%snodeini get %s %s %s\n", /* IGNORE-BANNED */ + pad, cmd->service, cmd->state, cmd->args); + break; + } + case CMD_COMPOSE_DOWN: { fprintf(f, "%scompose down\n", pad); /* IGNORE-BANNED */ @@ -2767,6 +2781,152 @@ runner_network_on(TestRunner *r, const char *nodeName) } +/* ----------------------------------------------------------------------- + * nodeini_write_value / nodeini_read_value + * + * Edit or read a node's host-side .ini file [settings] entry directly (the + * file is bind-mounted read-only inside the node's own container, so this + * can't go through exec/compose). Used both by the `nodeini set|get` DSL + * commands (to exercise the supervisor's file-watch live-apply path) and by + * the `pgaftest nodeini get|set` interactive command. + * ----------------------------------------------------------------------- */ +static bool +nodeini_write_value(TestRunner *r, const char *nodeName, + const char *key, const char *value, + char *errBuf, int errLen) +{ + char path[MAXPGPATH]; + sformat(path, sizeof(path), "%s/%s.ini", r->workDir, nodeName); + + FILE *f = fopen(path, "r"); /* IGNORE-BANNED */ + if (!f) + { + sformat(errBuf, errLen, + "nodeini %s: could not open \"%s\"", nodeName, path); + return false; + } + + char buf[8192] = { 0 }; + size_t nr = fread(buf, 1, sizeof(buf) - 1, f); /* IGNORE-BANNED */ + fclose(f); /* IGNORE-BANNED */ + + char keyPrefix[128]; + sformat(keyPrefix, sizeof(keyPrefix), "%s =", key); + size_t keyPrefixLen = strlen(keyPrefix); + + char out[8192] = { 0 }; + int outPos = 0; + bool found = false; + const char *line = buf; + + while (line < buf + nr) + { + const char *nl = memchr(line, '\n', buf + nr - line); /* IGNORE-BANNED */ + int lineLen = nl ? (int) (nl - line) : (int) (buf + nr - line); + + if (!found && + (size_t) lineLen >= keyPrefixLen && + strncmp(line, keyPrefix, keyPrefixLen) == 0) + { + outPos += sformat(out + outPos, sizeof(out) - outPos, + "%s = %s\n", key, value); + found = true; + } + else + { + memcpy(out + outPos, line, lineLen); /* IGNORE-BANNED */ + outPos += lineLen; + if (nl) + { + out[outPos++] = '\n'; + } + } + + line = nl ? nl + 1 : buf + nr; + } + + if (!found) + { + sformat(errBuf, errLen, + "nodeini %s: key \"%s\" not found in \"%s\"", + nodeName, key, path); + return false; + } + + f = fopen(path, "w"); /* IGNORE-BANNED */ + if (!f) + { + sformat(errBuf, errLen, + "nodeini %s: could not write \"%s\"", nodeName, path); + return false; + } + fwrite(out, 1, outPos, f); /* IGNORE-BANNED */ + fclose(f); /* IGNORE-BANNED */ + + log_info("nodeini: set %s = %s in %s", key, value, path); + return true; +} + + +static bool +nodeini_read_value(TestRunner *r, const char *nodeName, + const char *key, char *value, int valueLen, + char *errBuf, int errLen) +{ + char path[MAXPGPATH]; + sformat(path, sizeof(path), "%s/%s.ini", r->workDir, nodeName); + + FILE *f = fopen(path, "r"); /* IGNORE-BANNED */ + if (!f) + { + sformat(errBuf, errLen, + "nodeini %s: could not open \"%s\"", nodeName, path); + return false; + } + + char buf[8192] = { 0 }; + size_t nr = fread(buf, 1, sizeof(buf) - 1, f); /* IGNORE-BANNED */ + fclose(f); /* IGNORE-BANNED */ + + char keyPrefix[128]; + sformat(keyPrefix, sizeof(keyPrefix), "%s =", key); + size_t keyPrefixLen = strlen(keyPrefix); + + const char *line = buf; + while (line < buf + nr) + { + const char *nl = memchr(line, '\n', buf + nr - line); /* IGNORE-BANNED */ + int lineLen = nl ? (int) (nl - line) : (int) (buf + nr - line); + + if ((size_t) lineLen >= keyPrefixLen && + strncmp(line, keyPrefix, keyPrefixLen) == 0) + { + const char *v = line + keyPrefixLen; + const char *lineEnd = line + lineLen; + while (v < lineEnd && (*v == ' ' || *v == '\t')) + { + v++; + } + int vlen = (int) (lineEnd - v); + if (vlen >= valueLen) + { + vlen = valueLen - 1; + } + memcpy(value, v, vlen); /* IGNORE-BANNED */ + value[vlen] = '\0'; + return true; + } + + line = nl ? nl + 1 : buf + nr; + } + + sformat(errBuf, errLen, + "nodeini %s: key \"%s\" not found in \"%s\"", + nodeName, key, path); + return false; +} + + /* ----------------------------------------------------------------------- * Execute a single command * ----------------------------------------------------------------------- */ @@ -3156,6 +3316,32 @@ runner_exec_cmd(TestRunner *r, TestCmd *cmd, char *errBuf, int errLen) return true; } + case CMD_NODEINI_SET: + { + return nodeini_write_value(r, cmd->service, cmd->state, cmd->args, + errBuf, errLen); + } + + case CMD_NODEINI_GET: + { + char value[4096] = ""; + if (!nodeini_read_value(r, cmd->service, cmd->state, + value, sizeof(value), errBuf, errLen)) + { + return false; + } + + if (strcmp(value, cmd->args) != 0) + { + sformat(errBuf, errLen, + "nodeini %s: expected %s = \"%s\", got \"%s\"", + cmd->service, cmd->state, cmd->args, value); + return false; + } + + return true; + } + case CMD_COMPOSE_DOWN: { return runner_compose_down(r); @@ -4062,6 +4248,20 @@ cmd_label(const TestCmd *cmd, char *buf, int len) break; } + case CMD_NODEINI_SET: + { + sformat(buf, len, "nodeini set %s %s %s", + cmd->service, cmd->state, cmd->args); + break; + } + + case CMD_NODEINI_GET: + { + sformat(buf, len, "nodeini get %s %s %s", + cmd->service, cmd->state, cmd->args); + break; + } + case CMD_COMPOSE_DOWN: { sformat(buf, len, "compose down"); @@ -5025,6 +5225,55 @@ runner_network(TestSpec *spec, const char *workDir, } +/* + * runner_nodeini_set — `pgaftest nodeini set ` + * + * Edits the node's host-side .ini file directly, same as the `nodeini set` + * DSL command. + */ +bool +runner_nodeini_set(TestSpec *spec, const char *workDir, + const char *nodeName, const char *key, + const char *value) +{ + TestRunner r; + runner_init(&r, spec, workDir); + + char errBuf[1024] = ""; + if (!nodeini_write_value(&r, nodeName, key, value, errBuf, sizeof(errBuf))) + { + log_error("%s", errBuf); + return false; + } + return true; +} + + +/* + * runner_nodeini_get — `pgaftest nodeini get ` + * + * Reads the node's host-side .ini file directly, same as the `nodeini get` + * DSL command (minus the assertion against an expected value). + */ +bool +runner_nodeini_get(TestSpec *spec, const char *workDir, + const char *nodeName, const char *key, + char *value, int valueLen) +{ + TestRunner r; + runner_init(&r, spec, workDir); + + char errBuf[1024] = ""; + if (!nodeini_read_value(&r, nodeName, key, value, valueLen, + errBuf, sizeof(errBuf))) + { + log_error("%s", errBuf); + return false; + } + return true; +} + + /* * runner_assert — `pgaftest assert state = ` * diff --git a/src/bin/pgaftest/test_runner.h b/src/bin/pgaftest/test_runner.h index b3942da4c..ccd98424a 100644 --- a/src/bin/pgaftest/test_runner.h +++ b/src/bin/pgaftest/test_runner.h @@ -156,6 +156,12 @@ bool runner_network(TestSpec *spec, const char *workDir, const char *nodeName, bool connect); bool runner_assert(TestSpec *spec, const char *workDir, const char *nodeName, const char *targetState); +bool runner_nodeini_set(TestSpec *spec, const char *workDir, + const char *nodeName, const char *key, + const char *value); +bool runner_nodeini_get(TestSpec *spec, const char *workDir, + const char *nodeName, const char *key, + char *value, int valueLen); /* * Prepare an output directory with docker-compose.yml, *.ini files, and a diff --git a/src/bin/pgaftest/test_spec.h b/src/bin/pgaftest/test_spec.h index 88260c33b..196a8826b 100644 --- a/src/bin/pgaftest/test_spec.h +++ b/src/bin/pgaftest/test_spec.h @@ -170,6 +170,17 @@ typedef enum TestCmdKind CMD_FAILOVER, /* perform failover [in formation F] [group G] * — calls pgautofailover.perform_failover() directly * on the monitor; service = formation, waitGroups[0] = group */ + CMD_NODEINI_SET, /* nodeini set — edits the + * node's host-side pg_autoctl_node.ini [settings] + * entry directly, exercising the supervisor's + * file-watch live-apply path (the ini is read-only + * inside the node's own container, so this can't go + * through exec/compose). service = node, + * state = key, args = value. */ + CMD_NODEINI_GET, /* nodeini get — reads the + * node's host-side .ini [settings] entry directly + * and asserts it equals . service = node, + * state = key, args = expected value. */ } TestCmdKind; typedef struct TestCmd diff --git a/src/bin/pgaftest/test_spec_parse.c b/src/bin/pgaftest/test_spec_parse.c index df56a72d7..f03a7f1e8 100644 --- a/src/bin/pgaftest/test_spec_parse.c +++ b/src/bin/pgaftest/test_spec_parse.c @@ -109,76 +109,78 @@ T_BIND_SOURCE = 298, T_LEGACY_STARTUP = 299, T_REGION = 300, - T_FS_INIT = 301, - T_FS_SINGLE = 302, - T_FS_PRIMARY = 303, - T_FS_WAIT_PRIMARY = 304, - T_FS_WAIT_STANDBY = 305, - T_FS_DEMOTED = 306, - T_FS_DEMOTE_TIMEOUT = 307, - T_FS_DRAINING = 308, - T_FS_SECONDARY = 309, - T_FS_CATCHINGUP = 310, - T_FS_PREP_PROMOTION = 311, - T_FS_STOP_REPLICATION = 312, - T_FS_MAINTENANCE = 313, - T_FS_JOIN_PRIMARY = 314, - T_FS_APPLY_SETTINGS = 315, - T_FS_PREPARE_MAINTENANCE = 316, - T_FS_WAIT_MAINTENANCE = 317, - T_FS_REPORT_LSN = 318, - T_FS_FAST_FORWARD = 319, - T_FS_JOIN_SECONDARY = 320, - T_FS_DROPPED = 321, - T_EXEC = 322, - T_EXEC_FAILS = 323, - T_RUN = 324, - T_PG_AUTOCTL = 325, - T_WAIT = 326, - T_UNTIL = 327, - T_TIMEOUT = 328, - T_AND = 329, - T_IS = 330, - T_WITH = 331, - T_ASSERT = 332, - T_SQL = 333, - T_EXPECT = 334, - T_ERROR = 335, - T_PROMOTE = 336, - T_PERFORM = 337, - T_FAILOVER = 338, - T_NETWORK = 339, - T_DISCONNECT = 340, - T_CONNECT = 341, - T_SLEEP = 342, - T_COMPOSE = 343, - T_DOWN = 344, - T_START = 345, - T_STOP = 346, - T_STOPPED = 347, - T_KILL = 348, - T_INJECT = 349, - T_STATE = 350, - T_ASSIGNED_STATE = 351, - T_IN = 352, - T_GROUP = 353, - T_LBRACE = 354, - T_RBRACE = 355, - T_COMMA = 356, - T_POSTGRES = 357, - T_STAYS = 358, - T_WHILE = 359, - T_THROUGH = 360, - T_SET = 361, - T_LOGS = 362, - T_NOT = 363, - T_CONTAINS = 364, - T_MATCHES = 365, - T_INTEGER = 366, - T_IDENT = 367, - T_STRING = 368, - T_BLOCK = 369, - T_SHELL_ARGS = 370 + T_NODEINI = 301, + T_FS_INIT = 302, + T_FS_SINGLE = 303, + T_FS_PRIMARY = 304, + T_FS_WAIT_PRIMARY = 305, + T_FS_WAIT_STANDBY = 306, + T_FS_DEMOTED = 307, + T_FS_DEMOTE_TIMEOUT = 308, + T_FS_DRAINING = 309, + T_FS_SECONDARY = 310, + T_FS_CATCHINGUP = 311, + T_FS_PREP_PROMOTION = 312, + T_FS_STOP_REPLICATION = 313, + T_FS_MAINTENANCE = 314, + T_FS_JOIN_PRIMARY = 315, + T_FS_APPLY_SETTINGS = 316, + T_FS_PREPARE_MAINTENANCE = 317, + T_FS_WAIT_MAINTENANCE = 318, + T_FS_REPORT_LSN = 319, + T_FS_FAST_FORWARD = 320, + T_FS_JOIN_SECONDARY = 321, + T_FS_DROPPED = 322, + T_EXEC = 323, + T_EXEC_FAILS = 324, + T_RUN = 325, + T_PG_AUTOCTL = 326, + T_WAIT = 327, + T_UNTIL = 328, + T_TIMEOUT = 329, + T_AND = 330, + T_IS = 331, + T_WITH = 332, + T_ASSERT = 333, + T_SQL = 334, + T_EXPECT = 335, + T_ERROR = 336, + T_PROMOTE = 337, + T_PERFORM = 338, + T_FAILOVER = 339, + T_NETWORK = 340, + T_DISCONNECT = 341, + T_CONNECT = 342, + T_SLEEP = 343, + T_COMPOSE = 344, + T_DOWN = 345, + T_START = 346, + T_STOP = 347, + T_STOPPED = 348, + T_KILL = 349, + T_INJECT = 350, + T_STATE = 351, + T_ASSIGNED_STATE = 352, + T_IN = 353, + T_GROUP = 354, + T_LBRACE = 355, + T_RBRACE = 356, + T_COMMA = 357, + T_POSTGRES = 358, + T_STAYS = 359, + T_WHILE = 360, + T_THROUGH = 361, + T_SET = 362, + T_GET = 363, + T_LOGS = 364, + T_NOT = 365, + T_CONTAINS = 366, + T_MATCHES = 367, + T_INTEGER = 368, + T_IDENT = 369, + T_STRING = 370, + T_BLOCK = 371, + T_SHELL_ARGS = 372 }; #endif /* Tokens. */ @@ -225,76 +227,78 @@ #define T_BIND_SOURCE 298 #define T_LEGACY_STARTUP 299 #define T_REGION 300 -#define T_FS_INIT 301 -#define T_FS_SINGLE 302 -#define T_FS_PRIMARY 303 -#define T_FS_WAIT_PRIMARY 304 -#define T_FS_WAIT_STANDBY 305 -#define T_FS_DEMOTED 306 -#define T_FS_DEMOTE_TIMEOUT 307 -#define T_FS_DRAINING 308 -#define T_FS_SECONDARY 309 -#define T_FS_CATCHINGUP 310 -#define T_FS_PREP_PROMOTION 311 -#define T_FS_STOP_REPLICATION 312 -#define T_FS_MAINTENANCE 313 -#define T_FS_JOIN_PRIMARY 314 -#define T_FS_APPLY_SETTINGS 315 -#define T_FS_PREPARE_MAINTENANCE 316 -#define T_FS_WAIT_MAINTENANCE 317 -#define T_FS_REPORT_LSN 318 -#define T_FS_FAST_FORWARD 319 -#define T_FS_JOIN_SECONDARY 320 -#define T_FS_DROPPED 321 -#define T_EXEC 322 -#define T_EXEC_FAILS 323 -#define T_RUN 324 -#define T_PG_AUTOCTL 325 -#define T_WAIT 326 -#define T_UNTIL 327 -#define T_TIMEOUT 328 -#define T_AND 329 -#define T_IS 330 -#define T_WITH 331 -#define T_ASSERT 332 -#define T_SQL 333 -#define T_EXPECT 334 -#define T_ERROR 335 -#define T_PROMOTE 336 -#define T_PERFORM 337 -#define T_FAILOVER 338 -#define T_NETWORK 339 -#define T_DISCONNECT 340 -#define T_CONNECT 341 -#define T_SLEEP 342 -#define T_COMPOSE 343 -#define T_DOWN 344 -#define T_START 345 -#define T_STOP 346 -#define T_STOPPED 347 -#define T_KILL 348 -#define T_INJECT 349 -#define T_STATE 350 -#define T_ASSIGNED_STATE 351 -#define T_IN 352 -#define T_GROUP 353 -#define T_LBRACE 354 -#define T_RBRACE 355 -#define T_COMMA 356 -#define T_POSTGRES 357 -#define T_STAYS 358 -#define T_WHILE 359 -#define T_THROUGH 360 -#define T_SET 361 -#define T_LOGS 362 -#define T_NOT 363 -#define T_CONTAINS 364 -#define T_MATCHES 365 -#define T_INTEGER 366 -#define T_IDENT 367 -#define T_STRING 368 -#define T_BLOCK 369 -#define T_SHELL_ARGS 370 +#define T_NODEINI 301 +#define T_FS_INIT 302 +#define T_FS_SINGLE 303 +#define T_FS_PRIMARY 304 +#define T_FS_WAIT_PRIMARY 305 +#define T_FS_WAIT_STANDBY 306 +#define T_FS_DEMOTED 307 +#define T_FS_DEMOTE_TIMEOUT 308 +#define T_FS_DRAINING 309 +#define T_FS_SECONDARY 310 +#define T_FS_CATCHINGUP 311 +#define T_FS_PREP_PROMOTION 312 +#define T_FS_STOP_REPLICATION 313 +#define T_FS_MAINTENANCE 314 +#define T_FS_JOIN_PRIMARY 315 +#define T_FS_APPLY_SETTINGS 316 +#define T_FS_PREPARE_MAINTENANCE 317 +#define T_FS_WAIT_MAINTENANCE 318 +#define T_FS_REPORT_LSN 319 +#define T_FS_FAST_FORWARD 320 +#define T_FS_JOIN_SECONDARY 321 +#define T_FS_DROPPED 322 +#define T_EXEC 323 +#define T_EXEC_FAILS 324 +#define T_RUN 325 +#define T_PG_AUTOCTL 326 +#define T_WAIT 327 +#define T_UNTIL 328 +#define T_TIMEOUT 329 +#define T_AND 330 +#define T_IS 331 +#define T_WITH 332 +#define T_ASSERT 333 +#define T_SQL 334 +#define T_EXPECT 335 +#define T_ERROR 336 +#define T_PROMOTE 337 +#define T_PERFORM 338 +#define T_FAILOVER 339 +#define T_NETWORK 340 +#define T_DISCONNECT 341 +#define T_CONNECT 342 +#define T_SLEEP 343 +#define T_COMPOSE 344 +#define T_DOWN 345 +#define T_START 346 +#define T_STOP 347 +#define T_STOPPED 348 +#define T_KILL 349 +#define T_INJECT 350 +#define T_STATE 351 +#define T_ASSIGNED_STATE 352 +#define T_IN 353 +#define T_GROUP 354 +#define T_LBRACE 355 +#define T_RBRACE 356 +#define T_COMMA 357 +#define T_POSTGRES 358 +#define T_STAYS 359 +#define T_WHILE 360 +#define T_THROUGH 361 +#define T_SET 362 +#define T_GET 363 +#define T_LOGS 364 +#define T_NOT 365 +#define T_CONTAINS 366 +#define T_MATCHES 367 +#define T_INTEGER 368 +#define T_IDENT 369 +#define T_STRING 370 +#define T_BLOCK 371 +#define T_SHELL_ARGS 372 @@ -473,7 +477,7 @@ typedef union YYSTYPE TestCmd *cmd; } /* Line 193 of yacc.c. */ -#line 477 "test_spec_parse.c" +#line 481 "test_spec_parse.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -486,7 +490,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 490 "test_spec_parse.c" +#line 494 "test_spec_parse.c" #ifdef short # undef short @@ -701,20 +705,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 21 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 594 +#define YYLAST 609 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 116 +#define YYNTOKENS 118 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 63 +#define YYNNTS 64 /* YYNRULES -- Number of rules. */ -#define YYNRULES 207 +#define YYNRULES 210 /* YYNRULES -- Number of states. */ -#define YYNSTATES 337 +#define YYNSTATES 347 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 370 +#define YYMAXUTOK 372 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -759,7 +763,7 @@ static const yytype_uint8 yytranslate[] = 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115 + 115, 116, 117 }; #if YYDEBUG @@ -777,113 +781,117 @@ static const yytype_uint16 yyprhs[] = 187, 189, 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 235, 239, 242, 245, 249, 253, 254, 257, 259, 261, 263, 265, 267, 269, - 271, 273, 275, 277, 279, 281, 283, 285, 289, 292, - 296, 299, 303, 306, 310, 313, 315, 317, 319, 324, - 329, 331, 335, 336, 339, 341, 343, 347, 351, 352, - 362, 363, 373, 381, 389, 395, 401, 408, 410, 412, - 416, 420, 421, 424, 427, 432, 433, 436, 440, 447, - 454, 461, 468, 472, 475, 478, 482, 486, 489, 491, - 495, 498, 503, 509, 517, 521, 525, 528, 531, 535, - 539, 543, 548, 552, 556, 557, 563, 569, 573, 578, - 584, 589, 595, 598, 599, 602, 604, 606, 608, 610, - 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, - 632, 634, 636, 638, 640, 642, 644, 646 + 271, 273, 275, 277, 279, 281, 283, 285, 287, 291, + 294, 298, 301, 305, 308, 312, 315, 317, 319, 321, + 326, 331, 333, 337, 338, 341, 343, 345, 349, 353, + 354, 364, 365, 375, 383, 391, 397, 403, 410, 412, + 414, 418, 422, 423, 426, 429, 434, 435, 438, 442, + 449, 456, 463, 470, 474, 477, 480, 484, 488, 491, + 493, 497, 500, 505, 511, 519, 523, 527, 533, 539, + 542, 545, 549, 553, 557, 562, 566, 570, 571, 577, + 583, 587, 592, 598, 603, 609, 612, 613, 616, 618, + 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, + 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, + 660 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 117, 0, -1, 118, -1, 117, 118, -1, 119, -1, - 141, -1, 142, -1, 143, -1, 175, -1, -1, 3, - 99, 120, 121, 100, -1, -1, 121, 122, -1, 123, - -1, 124, -1, 126, -1, 127, -1, 125, -1, 128, - -1, 43, -1, 44, -1, 4, -1, 4, 39, 112, - -1, 4, 14, 112, -1, 4, 35, 111, -1, 4, - 36, 113, -1, 4, 112, 24, 26, -1, 4, 112, - 30, 92, -1, 4, 112, 24, 26, 36, 113, -1, - 13, 113, -1, 13, 112, -1, 42, 112, -1, 42, - 113, -1, 15, 112, -1, 16, 112, -1, 17, 112, - -1, -1, 18, 129, 130, 99, 133, 100, -1, -1, - 130, 132, -1, 112, -1, 113, -1, 16, -1, 4, - -1, 5, -1, 131, -1, 19, 111, -1, 54, 28, - -1, -1, 133, 136, -1, 112, -1, 4, -1, -1, - -1, 134, 135, 137, 139, -1, -1, 5, 112, 135, - 138, 99, 139, 100, -1, -1, 139, 140, -1, 20, + 119, 0, -1, 120, -1, 119, 120, -1, 121, -1, + 143, -1, 144, -1, 145, -1, 178, -1, -1, 3, + 100, 122, 123, 101, -1, -1, 123, 124, -1, 125, + -1, 126, -1, 128, -1, 129, -1, 127, -1, 130, + -1, 43, -1, 44, -1, 4, -1, 4, 39, 114, + -1, 4, 14, 114, -1, 4, 35, 113, -1, 4, + 36, 115, -1, 4, 114, 24, 26, -1, 4, 114, + 30, 93, -1, 4, 114, 24, 26, 36, 115, -1, + 13, 115, -1, 13, 114, -1, 42, 114, -1, 42, + 115, -1, 15, 114, -1, 16, 114, -1, 17, 114, + -1, -1, 18, 131, 132, 100, 135, 101, -1, -1, + 132, 134, -1, 114, -1, 115, -1, 16, -1, 4, + -1, 5, -1, 133, -1, 19, 113, -1, 55, 28, + -1, -1, 135, 138, -1, 114, -1, 4, -1, -1, + -1, 136, 137, 139, 141, -1, -1, 5, 114, 137, + 140, 100, 141, 101, -1, -1, 141, 142, -1, 20, -1, 21, -1, 22, -1, 23, -1, 26, -1, 24, - 26, -1, 25, 26, -1, 25, 74, 24, 26, -1, + 26, -1, 25, 26, -1, 25, 75, 24, 26, -1, 24, 27, -1, 27, -1, 32, -1, 33, -1, 34, - 111, -1, 45, 112, -1, 45, 113, -1, 98, 111, - -1, 35, 111, -1, 38, 112, -1, 39, 112, -1, - 15, 112, -1, 16, 112, -1, 17, 112, -1, 40, - 29, -1, 40, 28, -1, 41, 113, -1, 37, 113, - -1, 31, 112, 112, -1, 31, 112, 113, -1, 8, - 144, -1, 9, 144, -1, 10, 178, 144, -1, 99, - 145, 100, -1, -1, 145, 146, -1, 147, -1, 153, - -1, 160, -1, 161, -1, 162, -1, 163, -1, 165, - -1, 166, -1, 167, -1, 168, -1, 169, -1, 172, - -1, 173, -1, 174, -1, 67, 112, 115, -1, 67, - 112, -1, 68, 112, 115, -1, 68, 112, -1, 69, - 112, 115, -1, 69, 112, -1, 70, 112, 115, -1, - 70, 112, -1, 70, -1, 12, -1, 75, -1, 112, - 95, 148, 177, -1, 112, 95, 148, 112, -1, 149, - -1, 150, 74, 149, -1, -1, 105, 152, -1, 177, - -1, 112, -1, 152, 101, 177, -1, 152, 101, 112, - -1, -1, 71, 72, 112, 95, 148, 177, 154, 151, - 159, -1, -1, 71, 72, 112, 95, 148, 112, 155, - 151, 159, -1, 71, 72, 112, 96, 148, 177, 159, - -1, 71, 72, 112, 96, 148, 112, 159, -1, 71, - 72, 112, 92, 159, -1, 71, 72, 156, 157, 159, - -1, 71, 72, 149, 74, 150, 159, -1, 177, -1, - 112, -1, 156, 101, 177, -1, 156, 101, 112, -1, - -1, 97, 158, -1, 98, 111, -1, 158, 101, 98, - 111, -1, -1, 73, 111, -1, 76, 73, 111, -1, - 77, 112, 95, 148, 177, 159, -1, 77, 112, 95, - 148, 112, 159, -1, 77, 112, 96, 148, 177, 159, - -1, 77, 112, 96, 148, 112, 159, -1, 78, 112, - 114, -1, 79, 114, -1, 79, 80, -1, 79, 80, - 112, -1, 79, 80, 111, -1, 81, 164, -1, 112, - -1, 164, 101, 112, -1, 82, 83, -1, 82, 83, - 98, 111, -1, 82, 83, 97, 18, 112, -1, 82, - 83, 97, 18, 112, 98, 111, -1, 84, 85, 112, - -1, 84, 86, 112, -1, 87, 111, -1, 88, 89, - -1, 88, 90, 112, -1, 88, 91, 112, -1, 88, - 93, 112, -1, 88, 94, 112, 115, -1, 91, 102, - 134, -1, 90, 102, 134, -1, -1, 104, 171, 99, - 145, 100, -1, 77, 134, 103, 177, 170, -1, 106, - 112, 112, -1, 107, 112, 109, 113, -1, 107, 112, - 108, 109, 113, -1, 107, 112, 110, 113, -1, 107, - 112, 108, 110, 113, -1, 11, 176, -1, -1, 176, - 178, -1, 46, -1, 47, -1, 48, -1, 49, -1, - 50, -1, 51, -1, 52, -1, 53, -1, 54, -1, - 55, -1, 56, -1, 57, -1, 58, -1, 59, -1, - 60, -1, 61, -1, 62, -1, 63, -1, 64, -1, - 65, -1, 66, -1, 112, -1, 113, -1 + 113, -1, 45, 114, -1, 45, 115, -1, 99, 113, + -1, 35, 113, -1, 38, 114, -1, 39, 114, -1, + 15, 114, -1, 16, 114, -1, 17, 114, -1, 40, + 29, -1, 40, 28, -1, 41, 115, -1, 37, 115, + -1, 31, 114, 114, -1, 31, 114, 115, -1, 8, + 146, -1, 9, 146, -1, 10, 181, 146, -1, 100, + 147, 101, -1, -1, 147, 148, -1, 149, -1, 155, + -1, 162, -1, 163, -1, 164, -1, 165, -1, 167, + -1, 168, -1, 170, -1, 171, -1, 172, -1, 175, + -1, 176, -1, 177, -1, 169, -1, 68, 114, 117, + -1, 68, 114, -1, 69, 114, 117, -1, 69, 114, + -1, 70, 114, 117, -1, 70, 114, -1, 71, 114, + 117, -1, 71, 114, -1, 71, -1, 12, -1, 76, + -1, 114, 96, 150, 180, -1, 114, 96, 150, 114, + -1, 151, -1, 152, 75, 151, -1, -1, 106, 154, + -1, 180, -1, 114, -1, 154, 102, 180, -1, 154, + 102, 114, -1, -1, 72, 73, 114, 96, 150, 180, + 156, 153, 161, -1, -1, 72, 73, 114, 96, 150, + 114, 157, 153, 161, -1, 72, 73, 114, 97, 150, + 180, 161, -1, 72, 73, 114, 97, 150, 114, 161, + -1, 72, 73, 114, 93, 161, -1, 72, 73, 158, + 159, 161, -1, 72, 73, 151, 75, 152, 161, -1, + 180, -1, 114, -1, 158, 102, 180, -1, 158, 102, + 114, -1, -1, 98, 160, -1, 99, 113, -1, 160, + 102, 99, 113, -1, -1, 74, 113, -1, 77, 74, + 113, -1, 78, 114, 96, 150, 180, 161, -1, 78, + 114, 96, 150, 114, 161, -1, 78, 114, 97, 150, + 180, 161, -1, 78, 114, 97, 150, 114, 161, -1, + 79, 114, 116, -1, 80, 116, -1, 80, 81, -1, + 80, 81, 114, -1, 80, 81, 113, -1, 82, 166, + -1, 114, -1, 166, 102, 114, -1, 83, 84, -1, + 83, 84, 99, 113, -1, 83, 84, 98, 18, 114, + -1, 83, 84, 98, 18, 114, 99, 113, -1, 85, + 86, 114, -1, 85, 87, 114, -1, 46, 107, 114, + 114, 114, -1, 46, 108, 114, 114, 114, -1, 88, + 113, -1, 89, 90, -1, 89, 91, 114, -1, 89, + 92, 114, -1, 89, 94, 114, -1, 89, 95, 114, + 117, -1, 92, 103, 136, -1, 91, 103, 136, -1, + -1, 105, 174, 100, 147, 101, -1, 78, 136, 104, + 180, 173, -1, 107, 114, 114, -1, 109, 114, 111, + 115, -1, 109, 114, 110, 111, 115, -1, 109, 114, + 112, 115, -1, 109, 114, 110, 112, 115, -1, 11, + 179, -1, -1, 179, 181, -1, 47, -1, 48, -1, + 49, -1, 50, -1, 51, -1, 52, -1, 53, -1, + 54, -1, 55, -1, 56, -1, 57, -1, 58, -1, + 59, -1, 60, -1, 61, -1, 62, -1, 63, -1, + 64, -1, 65, -1, 66, -1, 67, -1, 114, -1, + 115, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 212, 212, 213, 217, 218, 219, 220, 221, 234, - 233, 243, 245, 249, 250, 251, 252, 253, 254, 255, - 256, 269, 273, 280, 287, 293, 300, 307, 314, 327, - 333, 343, 349, 359, 369, 375, 386, 385, 402, 404, - 413, 414, 415, 416, 417, 421, 426, 430, 436, 438, - 457, 458, 467, 484, 483, 491, 490, 498, 500, 504, - 509, 514, 518, 522, 528, 533, 537, 542, 546, 550, - 554, 558, 562, 567, 572, 576, 580, 586, 592, 597, - 602, 607, 611, 615, 621, 627, 641, 662, 669, 680, - 698, 713, 716, 724, 725, 726, 727, 728, 729, 730, - 731, 732, 733, 734, 735, 736, 737, 751, 758, 764, - 771, 777, 784, 790, 798, 804, 831, 831, 842, 857, - 875, 876, 891, 893, 897, 905, 913, 920, 932, 931, - 943, 942, 953, 962, 971, 978, 992, 1007, 1013, 1020, - 1026, 1039, 1041, 1045, 1050, 1058, 1059, 1060, 1071, 1079, - 1087, 1095, 1113, 1128, 1135, 1139, 1145, 1158, 1166, 1174, - 1195, 1202, 1209, 1217, 1233, 1239, 1252, 1266, 1270, 1276, - 1282, 1308, 1342, 1348, 1365, 1365, 1370, 1389, 1414, 1423, - 1432, 1441, 1457, 1460, 1462, 1484, 1485, 1486, 1487, 1488, - 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, - 1499, 1500, 1501, 1502, 1503, 1504, 1512, 1513 + 0, 214, 214, 215, 219, 220, 221, 222, 223, 236, + 235, 245, 247, 251, 252, 253, 254, 255, 256, 257, + 258, 271, 275, 282, 289, 295, 302, 309, 316, 329, + 335, 345, 351, 361, 371, 377, 388, 387, 404, 406, + 415, 416, 417, 418, 419, 423, 428, 432, 438, 440, + 459, 460, 469, 486, 485, 493, 492, 500, 502, 506, + 511, 516, 520, 524, 530, 535, 539, 544, 548, 552, + 556, 560, 564, 569, 574, 578, 582, 588, 594, 599, + 604, 609, 613, 617, 623, 629, 643, 664, 671, 682, + 700, 715, 718, 726, 727, 728, 729, 730, 731, 732, + 733, 734, 735, 736, 737, 738, 739, 740, 754, 761, + 767, 774, 780, 787, 793, 801, 807, 834, 834, 845, + 860, 878, 879, 894, 896, 900, 908, 916, 923, 935, + 934, 946, 945, 956, 965, 974, 981, 995, 1010, 1016, + 1023, 1029, 1042, 1044, 1048, 1053, 1061, 1062, 1063, 1074, + 1082, 1090, 1098, 1116, 1131, 1138, 1142, 1148, 1161, 1169, + 1177, 1198, 1205, 1212, 1220, 1236, 1242, 1263, 1271, 1286, + 1300, 1304, 1310, 1316, 1342, 1376, 1382, 1399, 1399, 1404, + 1423, 1448, 1457, 1466, 1475, 1491, 1494, 1496, 1518, 1519, + 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, + 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1546, + 1547 }; #endif @@ -902,32 +910,33 @@ static const char *const yytname[] = "T_PORT", "T_PASSWORD", "T_MONITOR_PASSWORD", "T_CITUS_CLUSTER_NAME", "T_DEBIAN_CLUSTER", "T_REPLICATION_QUORUM", "T_REPLICATION_PASSWORD", "T_EXTENSION_VERSION", "T_BIND_SOURCE", "T_LEGACY_STARTUP", "T_REGION", - "T_FS_INIT", "T_FS_SINGLE", "T_FS_PRIMARY", "T_FS_WAIT_PRIMARY", - "T_FS_WAIT_STANDBY", "T_FS_DEMOTED", "T_FS_DEMOTE_TIMEOUT", - "T_FS_DRAINING", "T_FS_SECONDARY", "T_FS_CATCHINGUP", - "T_FS_PREP_PROMOTION", "T_FS_STOP_REPLICATION", "T_FS_MAINTENANCE", - "T_FS_JOIN_PRIMARY", "T_FS_APPLY_SETTINGS", "T_FS_PREPARE_MAINTENANCE", - "T_FS_WAIT_MAINTENANCE", "T_FS_REPORT_LSN", "T_FS_FAST_FORWARD", - "T_FS_JOIN_SECONDARY", "T_FS_DROPPED", "T_EXEC", "T_EXEC_FAILS", "T_RUN", - "T_PG_AUTOCTL", "T_WAIT", "T_UNTIL", "T_TIMEOUT", "T_AND", "T_IS", - "T_WITH", "T_ASSERT", "T_SQL", "T_EXPECT", "T_ERROR", "T_PROMOTE", - "T_PERFORM", "T_FAILOVER", "T_NETWORK", "T_DISCONNECT", "T_CONNECT", - "T_SLEEP", "T_COMPOSE", "T_DOWN", "T_START", "T_STOP", "T_STOPPED", - "T_KILL", "T_INJECT", "T_STATE", "T_ASSIGNED_STATE", "T_IN", "T_GROUP", - "T_LBRACE", "T_RBRACE", "T_COMMA", "T_POSTGRES", "T_STAYS", "T_WHILE", - "T_THROUGH", "T_SET", "T_LOGS", "T_NOT", "T_CONTAINS", "T_MATCHES", - "T_INTEGER", "T_IDENT", "T_STRING", "T_BLOCK", "T_SHELL_ARGS", "$accept", - "spec", "spec_item", "cluster_block", "@1", "cluster_item_list", - "cluster_item", "monitor_line", "image_line", "extension_version_line", - "ssl_line", "auth_line", "formation_block", "@2", "formation_opt_list", - "bare_name", "formation_opt", "node_list", "node_name", "init_node_slot", - "node_line", "@3", "@4", "node_opt_list", "node_opt", "setup_block", - "teardown_block", "named_step", "cmd_block", "cmd_list", "step_cmd", - "exec_cmd", "state_op", "wait_multi_condition", - "wait_multi_condition_list", "opt_passing_through", "pass_state_list", - "wait_cmd", "@5", "@6", "state_name_list", "opt_in_group", "group_items", - "opt_timeout", "assert_cmd", "sql_cmd", "expect_cmd", "promote_cmd", - "promote_list", "perform_cmd", "network_cmd", "sleep_cmd", "compose_cmd", + "T_NODEINI", "T_FS_INIT", "T_FS_SINGLE", "T_FS_PRIMARY", + "T_FS_WAIT_PRIMARY", "T_FS_WAIT_STANDBY", "T_FS_DEMOTED", + "T_FS_DEMOTE_TIMEOUT", "T_FS_DRAINING", "T_FS_SECONDARY", + "T_FS_CATCHINGUP", "T_FS_PREP_PROMOTION", "T_FS_STOP_REPLICATION", + "T_FS_MAINTENANCE", "T_FS_JOIN_PRIMARY", "T_FS_APPLY_SETTINGS", + "T_FS_PREPARE_MAINTENANCE", "T_FS_WAIT_MAINTENANCE", "T_FS_REPORT_LSN", + "T_FS_FAST_FORWARD", "T_FS_JOIN_SECONDARY", "T_FS_DROPPED", "T_EXEC", + "T_EXEC_FAILS", "T_RUN", "T_PG_AUTOCTL", "T_WAIT", "T_UNTIL", + "T_TIMEOUT", "T_AND", "T_IS", "T_WITH", "T_ASSERT", "T_SQL", "T_EXPECT", + "T_ERROR", "T_PROMOTE", "T_PERFORM", "T_FAILOVER", "T_NETWORK", + "T_DISCONNECT", "T_CONNECT", "T_SLEEP", "T_COMPOSE", "T_DOWN", "T_START", + "T_STOP", "T_STOPPED", "T_KILL", "T_INJECT", "T_STATE", + "T_ASSIGNED_STATE", "T_IN", "T_GROUP", "T_LBRACE", "T_RBRACE", "T_COMMA", + "T_POSTGRES", "T_STAYS", "T_WHILE", "T_THROUGH", "T_SET", "T_GET", + "T_LOGS", "T_NOT", "T_CONTAINS", "T_MATCHES", "T_INTEGER", "T_IDENT", + "T_STRING", "T_BLOCK", "T_SHELL_ARGS", "$accept", "spec", "spec_item", + "cluster_block", "@1", "cluster_item_list", "cluster_item", + "monitor_line", "image_line", "extension_version_line", "ssl_line", + "auth_line", "formation_block", "@2", "formation_opt_list", "bare_name", + "formation_opt", "node_list", "node_name", "init_node_slot", "node_line", + "@3", "@4", "node_opt_list", "node_opt", "setup_block", "teardown_block", + "named_step", "cmd_block", "cmd_list", "step_cmd", "exec_cmd", + "state_op", "wait_multi_condition", "wait_multi_condition_list", + "opt_passing_through", "pass_state_list", "wait_cmd", "@5", "@6", + "state_name_list", "opt_in_group", "group_items", "opt_timeout", + "assert_cmd", "sql_cmd", "expect_cmd", "promote_cmd", "promote_list", + "perform_cmd", "network_cmd", "nodeini_cmd", "sleep_cmd", "compose_cmd", "postgres_ctl_cmd", "while_body", "@7", "stays_while_cmd", "set_monitor_cmd", "logs_cmd", "sequence_block", "sequence_names", "fsm_state", "ident_or_string", 0 @@ -950,34 +959,35 @@ static const yytype_uint16 yytoknum[] = 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370 + 365, 366, 367, 368, 369, 370, 371, 372 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 116, 117, 117, 118, 118, 118, 118, 118, 120, - 119, 121, 121, 122, 122, 122, 122, 122, 122, 122, - 122, 123, 123, 123, 123, 123, 123, 123, 123, 124, - 124, 125, 125, 126, 127, 127, 129, 128, 130, 130, - 131, 131, 131, 131, 131, 132, 132, 132, 133, 133, - 134, 134, 135, 137, 136, 138, 136, 139, 139, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 141, 142, 143, - 144, 145, 145, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 147, 147, 147, - 147, 147, 147, 147, 147, 147, 148, 148, 149, 149, - 150, 150, 151, 151, 152, 152, 152, 152, 154, 153, - 155, 153, 153, 153, 153, 153, 153, 156, 156, 156, - 156, 157, 157, 158, 158, 159, 159, 159, 160, 160, - 160, 160, 161, 162, 162, 162, 162, 163, 164, 164, - 165, 165, 165, 165, 166, 166, 167, 168, 168, 168, - 168, 168, 169, 169, 171, 170, 172, 173, 174, 174, - 174, 174, 175, 176, 176, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 178, 178 + 0, 118, 119, 119, 120, 120, 120, 120, 120, 122, + 121, 123, 123, 124, 124, 124, 124, 124, 124, 124, + 124, 125, 125, 125, 125, 125, 125, 125, 125, 126, + 126, 127, 127, 128, 129, 129, 131, 130, 132, 132, + 133, 133, 133, 133, 133, 134, 134, 134, 135, 135, + 136, 136, 137, 139, 138, 140, 138, 141, 141, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 143, 144, 145, + 146, 147, 147, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 150, 150, 151, + 151, 152, 152, 153, 153, 154, 154, 154, 154, 156, + 155, 157, 155, 155, 155, 155, 155, 155, 158, 158, + 158, 158, 159, 159, 160, 160, 161, 161, 161, 162, + 162, 162, 162, 163, 164, 164, 164, 164, 165, 166, + 166, 167, 167, 167, 167, 168, 168, 169, 169, 170, + 171, 171, 171, 171, 171, 172, 172, 174, 173, 175, + 176, 177, 177, 177, 177, 178, 179, 179, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 181, + 181 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -993,17 +1003,18 @@ static const yytype_uint8 yyr2[] = 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3, 0, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, - 2, 3, 2, 3, 2, 1, 1, 1, 4, 4, - 1, 3, 0, 2, 1, 1, 3, 3, 0, 9, - 0, 9, 7, 7, 5, 5, 6, 1, 1, 3, - 3, 0, 2, 2, 4, 0, 2, 3, 6, 6, - 6, 6, 3, 2, 2, 3, 3, 2, 1, 3, - 2, 4, 5, 7, 3, 3, 2, 2, 3, 3, - 3, 4, 3, 3, 0, 5, 5, 3, 4, 5, - 4, 5, 2, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 3, 2, 3, 2, 3, 2, 1, 1, 1, 4, + 4, 1, 3, 0, 2, 1, 1, 3, 3, 0, + 9, 0, 9, 7, 7, 5, 5, 6, 1, 1, + 3, 3, 0, 2, 2, 4, 0, 2, 3, 6, + 6, 6, 6, 3, 2, 2, 3, 3, 2, 1, + 3, 2, 4, 5, 7, 3, 3, 5, 5, 2, + 2, 3, 3, 3, 4, 3, 3, 0, 5, 5, + 3, 4, 5, 4, 5, 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -1011,38 +1022,39 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 0, 0, 0, 183, 0, 2, 4, 5, - 6, 7, 8, 9, 91, 87, 88, 206, 207, 0, - 182, 1, 3, 11, 0, 89, 184, 0, 0, 0, - 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 90, 0, 0, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 21, 0, 0, 0, 0, 36, 0, 19, 20, - 10, 12, 13, 14, 17, 15, 16, 18, 108, 110, - 112, 114, 0, 51, 50, 0, 0, 154, 153, 158, - 157, 160, 0, 0, 166, 167, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, - 29, 33, 34, 35, 38, 31, 32, 107, 109, 111, - 113, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 138, 0, 141, 137, 0, 0, 0, 152, - 156, 155, 0, 0, 0, 164, 165, 168, 169, 170, - 0, 50, 173, 172, 177, 0, 0, 0, 23, 24, - 25, 22, 0, 0, 0, 145, 0, 0, 0, 0, - 0, 145, 116, 117, 0, 0, 0, 159, 0, 161, - 171, 0, 0, 178, 180, 26, 27, 43, 44, 42, - 0, 0, 48, 40, 41, 45, 39, 0, 0, 134, - 0, 0, 0, 120, 145, 0, 142, 140, 139, 135, - 145, 145, 145, 145, 174, 176, 162, 179, 181, 0, - 46, 47, 0, 146, 0, 130, 128, 145, 145, 0, - 0, 136, 143, 0, 149, 148, 151, 150, 0, 0, - 28, 0, 37, 52, 49, 147, 122, 122, 133, 132, - 0, 121, 0, 91, 163, 52, 53, 0, 145, 145, - 119, 118, 144, 0, 55, 57, 125, 123, 124, 131, - 129, 175, 0, 54, 0, 57, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 186, 0, 2, 4, 5, + 6, 7, 8, 9, 91, 87, 88, 209, 210, 0, + 185, 1, 3, 11, 0, 89, 187, 0, 0, 0, + 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 0, 0, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 107, 101, 102, 103, + 104, 105, 106, 21, 0, 0, 0, 0, 36, 0, + 19, 20, 10, 12, 13, 14, 17, 15, 16, 18, + 0, 0, 109, 111, 113, 115, 0, 51, 50, 0, + 0, 155, 154, 159, 158, 161, 0, 0, 169, 170, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 30, 29, 33, 34, 35, 38, 31, + 32, 0, 0, 108, 110, 112, 114, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 139, 0, + 142, 138, 0, 0, 0, 153, 157, 156, 0, 0, + 0, 165, 166, 171, 172, 173, 0, 50, 176, 175, + 180, 0, 0, 0, 23, 24, 25, 22, 0, 0, + 0, 0, 0, 146, 0, 0, 0, 0, 0, 146, + 117, 118, 0, 0, 0, 160, 0, 162, 174, 0, + 0, 181, 183, 26, 27, 43, 44, 42, 0, 0, + 48, 40, 41, 45, 39, 167, 168, 0, 0, 135, + 0, 0, 0, 121, 146, 0, 143, 141, 140, 136, + 146, 146, 146, 146, 177, 179, 163, 182, 184, 0, + 46, 47, 0, 147, 0, 131, 129, 146, 146, 0, + 0, 137, 144, 0, 150, 149, 152, 151, 0, 0, + 28, 0, 37, 52, 49, 148, 123, 123, 134, 133, + 0, 122, 0, 91, 164, 52, 53, 0, 146, 146, + 120, 119, 145, 0, 55, 57, 126, 124, 125, 132, + 130, 178, 0, 54, 0, 57, 0, 0, 0, 59, 60, 61, 62, 0, 0, 63, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, - 127, 126, 0, 78, 79, 80, 64, 67, 65, 0, + 128, 127, 0, 78, 79, 80, 64, 67, 65, 0, 0, 71, 75, 84, 76, 77, 82, 81, 83, 72, 73, 74, 56, 0, 85, 86, 66 }; @@ -1050,239 +1062,243 @@ static const yytype_uint8 yydefact[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 6, 7, 8, 23, 27, 71, 72, 73, 74, - 75, 76, 77, 114, 174, 205, 206, 232, 85, 266, - 254, 275, 282, 283, 309, 9, 10, 11, 15, 24, - 46, 47, 184, 143, 214, 268, 277, 48, 257, 256, - 144, 181, 216, 209, 49, 50, 51, 52, 90, 53, - 54, 55, 56, 57, 225, 248, 58, 59, 60, 12, - 20, 145, 19 + -1, 6, 7, 8, 23, 27, 73, 74, 75, 76, + 77, 78, 79, 118, 180, 213, 214, 242, 89, 276, + 264, 285, 292, 293, 319, 9, 10, 11, 15, 24, + 47, 48, 192, 149, 224, 278, 287, 49, 267, 266, + 150, 189, 226, 219, 50, 51, 52, 53, 94, 54, + 55, 56, 57, 58, 59, 235, 258, 60, 61, 62, + 12, 20, 151, 19 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -163 +#define YYPACT_NINF -174 static const yytype_int16 yypact[] = { - 56, -84, -61, -61, -68, -163, 43, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -61, - -68, -163, -163, -163, 425, -163, -163, 6, -30, -25, - -17, -2, 54, 3, 15, -67, 16, 46, -29, 19, - -10, 29, 30, -163, 22, 28, -163, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -5, -42, 38, 39, 40, -163, -27, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, 26, 53, - 62, 63, 150, -163, -6, 32, 44, -7, -163, -163, - 78, 0, 73, 79, -163, -163, 80, 81, 83, 105, - 4, 4, 106, -81, 107, 110, 131, 133, 9, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -23, 172, -83, -163, 13, 13, 528, -163, - -163, -163, 136, 231, 139, -163, -163, -163, -163, -163, - 137, -163, -163, -163, -163, -8, 138, 140, -163, -163, - -163, -163, 228, 163, 1, -15, 13, 13, 144, 159, - 177, -15, -163, -163, 217, 244, 154, -163, 147, -163, - -163, 148, 171, -163, -163, 224, -163, -163, -163, -163, - 174, 258, -163, -163, -163, -163, -163, 176, 215, -163, - 284, 311, 216, -163, 20, 201, 212, -163, -163, -163, - -15, -15, -15, -15, -163, -163, 218, -163, -163, 202, - -163, -163, -1, -163, 203, 243, 245, -15, -15, 13, - 144, -163, -163, 220, -163, -163, -163, -163, 221, 210, - -163, 211, -163, -163, -163, -163, 219, 219, -163, -163, - 351, -163, 214, -163, -163, -163, -163, 378, -15, -15, - -163, -163, -163, 466, -163, -163, -163, 225, -163, -163, - -163, -163, 223, 149, 418, -163, 239, 240, 241, -163, - -163, -163, -163, 82, -14, -163, -163, 242, -163, -163, - 267, 268, 269, 271, 272, 89, 273, 8, 270, -163, - -163, -163, 122, -163, -163, -163, -163, -163, -163, 303, - 12, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, 302, -163, -163, -163 + 80, -81, -72, -72, -52, -174, 71, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -72, + -52, -174, -174, -174, 432, -174, -174, 7, -15, -71, + -59, -57, -50, -40, 3, -27, -69, -16, 25, 8, + 11, -22, 16, 19, -174, 24, 32, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -4, -18, 42, 53, 59, -174, -14, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + 67, 94, 93, 116, 117, 118, 136, -174, 15, 133, + 122, 52, -174, -174, 138, 5, 125, 127, -174, -174, + 128, 129, 130, 131, 4, 4, 132, -26, 134, 159, + 158, 135, 6, -174, -174, -174, -174, -174, -174, -174, + -174, 160, 161, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -51, 172, + -54, -174, 2, 2, 542, -174, -174, -174, 162, 259, + 188, -174, -174, -174, -174, -174, 185, -174, -174, -174, + -174, 9, 163, 189, -174, -174, -174, -174, 277, 212, + -1, 192, 193, -21, 2, 2, 194, 210, 165, -21, + -174, -174, 204, 233, 205, -174, 197, -174, -174, 198, + 199, -174, -174, 276, -174, -174, -174, -174, 202, 288, + -174, -174, -174, -174, -174, -174, -174, 227, 243, -174, + 272, 301, 245, -174, -48, 229, 241, -174, -174, -174, + -21, -21, -21, -21, -174, -174, 246, -174, -174, 231, + -174, -174, 1, -174, 256, 269, 295, -21, -21, 2, + 194, -174, -174, 273, -174, -174, -174, -174, 271, 260, + -174, 261, -174, -174, -174, -174, 268, 268, -174, -174, + 340, -174, 263, -174, -174, -174, -174, 369, -21, -21, + -174, -174, -174, 479, -174, -174, -174, 275, -174, -174, + -174, -174, 278, 137, 408, -174, 265, 266, 267, -174, + -174, -174, -174, 102, -10, -174, -174, 270, -174, -174, + 296, 297, 293, 298, 299, 151, 322, 90, 325, -174, + -174, -174, 110, -174, -174, -174, -174, -174, -174, 358, + 92, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, 357, -174, -174, -174 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -163, -163, 349, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -99, 115, - -163, -163, -163, 100, -163, -163, -163, -163, 23, 124, - -163, -163, -136, -162, -163, 132, -163, -163, -163, -163, - -163, -163, -163, -146, -163, -163, -163, -163, -163, -163, - -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -148, 368 + -174, -174, 379, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -103, 139, + -174, -174, -174, 144, -174, -174, -174, -174, 18, 167, + -174, -174, -144, -173, -174, 174, -174, -174, -174, -174, + -174, -174, -174, -172, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -154, 391 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -120 +#define YYTABLE_NINF -121 static const yytype_int16 yytable[] = { - 186, 162, 163, 83, 251, 197, 198, 83, 83, 104, - 61, 185, 318, 87, 179, 13, 213, 199, 180, 62, - 200, 63, 64, 65, 66, 182, 16, 165, 166, 167, - 105, 106, 218, 172, 107, 219, 221, 223, 14, 173, - 210, 211, 25, 21, 17, 18, 1, 88, 67, 68, - 69, 2, 3, 4, 5, 201, 92, 93, 207, 1, - 319, 208, 236, 238, 2, 3, 4, 5, 241, 175, - 109, 110, 176, 177, 244, 245, 246, 247, 261, 95, - 96, 97, 78, 98, 99, 115, 116, 79, 183, 146, - 147, 258, 259, 207, 240, 80, 208, 153, 154, 252, - 202, 191, 192, 260, 150, 151, 70, 108, 316, 317, - 81, 161, 271, 203, 204, 84, 161, 326, 327, 278, - 329, 330, 279, 280, 334, 335, 82, 86, 89, 91, - 94, 100, 101, 253, 102, 148, 311, 286, 287, 288, - 103, 117, 289, 290, 291, 292, 293, 294, 295, 296, - 111, 112, 113, 297, 298, 299, 300, 301, 149, 302, - 303, 304, 305, 306, 286, 287, 288, 307, 118, 289, - 290, 291, 292, 293, 294, 295, 296, 119, 120, 152, - 297, 298, 299, 300, 301, 155, 302, 303, 304, 305, - 306, 156, 157, 158, 307, 159, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 160, 164, 168, - 308, 169, 332, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 170, 171, 178, 308, 187, 188, - 189, 193, 190, 194, 195, 196, 212, 215, 224, 226, - 229, 227, 142, 121, 122, 123, 124, 125, 126, 127, + 194, 168, 169, 205, 206, 87, 261, 87, 87, 193, + 108, 63, 91, 223, 190, 207, 328, 229, 208, 13, + 64, 16, 65, 66, 67, 68, 217, 250, 14, 218, + 178, 109, 110, 86, 228, 111, 179, 25, 231, 233, + 220, 221, 183, 82, 187, 184, 185, 92, 188, 69, + 70, 71, 251, 217, 209, 83, 218, 84, 254, 255, + 256, 257, 17, 18, 85, 329, 246, 248, 99, 100, + 101, 21, 102, 103, 1, 268, 269, 271, 191, 2, + 3, 4, 5, 1, 171, 172, 173, 90, 2, 3, + 4, 5, 80, 81, 96, 97, 113, 114, 93, 210, + 119, 120, 262, 159, 160, 270, 289, 290, 72, 95, + 112, 152, 153, 211, 212, 167, 281, 88, 167, 104, + 199, 200, 105, 288, 98, 296, 297, 298, 326, 327, + 299, 300, 301, 302, 303, 304, 305, 306, 106, 263, + 321, 307, 308, 309, 310, 311, 107, 312, 313, 314, + 315, 316, 296, 297, 298, 317, 115, 299, 300, 301, + 302, 303, 304, 305, 306, 156, 157, 116, 307, 308, + 309, 310, 311, 117, 312, 313, 314, 315, 316, 336, + 337, 121, 317, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 339, 340, 344, 345, 122, 318, + 123, 342, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 124, 125, 126, 318, 154, 155, 161, + 158, 162, 163, 164, 165, 166, 170, 186, 174, 177, + 148, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 175, 176, 181, 182, 195, 196, 201, 227, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 197, 198, 203, 202, 204, 215, 216, 222, 225, + 234, 236, 239, 237, 238, 240, 241, 244, 230, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 228, 230, 231, 233, 234, 217, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 243, 249, 252, 253, -120, 259, 260, 232, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 265, + -119, 273, 272, 274, 277, 275, 282, 294, 295, 323, + 324, 325, 343, 346, 330, 22, 245, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 333, 331, + 332, 26, 334, 335, 284, 247, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 239, 242, 243, 255, 250, 249, -119, 262, -118, - 263, 264, 285, 265, 267, 272, 284, 333, 336, 220, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 313, 314, 315, 320, 22, 222, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 321, 322, - 274, 331, 323, 324, 325, 312, 328, 273, 26, 269, - 0, 0, 0, 0, 0, 0, 235, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 0, 0, - 0, 0, 0, 237, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 0, 0, 0, 0, 0, + 141, 142, 143, 144, 145, 146, 147, 338, 341, 322, + 283, 279, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 280, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 0, 0, 28, 0, + 0, 0, 0, 286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 270, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 0, 0, 0, 0, 0, - 276, 0, 28, 29, 30, 31, 32, 0, 0, 0, - 0, 0, 33, 34, 35, 0, 36, 37, 0, 38, - 0, 0, 39, 40, 0, 41, 42, 0, 0, 0, - 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, - 310, 44, 45, 28, 29, 30, 31, 32, 0, 0, - 0, 0, 0, 33, 34, 35, 0, 36, 37, 0, - 38, 0, 0, 39, 40, 0, 41, 42, 0, 0, - 0, 0, 0, 0, 0, 0, 281, 0, 0, 0, - 0, 0, 44, 45, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141 + 29, 30, 31, 32, 33, 0, 0, 0, 0, 0, + 34, 35, 36, 0, 37, 38, 0, 39, 0, 0, + 40, 41, 320, 42, 43, 28, 0, 0, 0, 0, + 0, 0, 0, 44, 0, 0, 0, 0, 0, 45, + 0, 46, 0, 0, 0, 0, 0, 29, 30, 31, + 32, 33, 0, 0, 0, 0, 0, 34, 35, 36, + 0, 37, 38, 0, 39, 0, 0, 40, 41, 0, + 42, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 291, 0, 0, 0, 0, 0, 45, 0, 46, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147 }; static const yytype_int16 yycheck[] = { - 148, 100, 101, 4, 5, 4, 5, 4, 4, 14, - 4, 147, 26, 80, 97, 99, 178, 16, 101, 13, - 19, 15, 16, 17, 18, 12, 3, 108, 109, 110, - 35, 36, 180, 24, 39, 181, 184, 185, 99, 30, - 176, 177, 19, 0, 112, 113, 3, 114, 42, 43, - 44, 8, 9, 10, 11, 54, 85, 86, 73, 3, - 74, 76, 210, 211, 8, 9, 10, 11, 214, 92, - 112, 113, 95, 96, 220, 221, 222, 223, 240, 89, - 90, 91, 112, 93, 94, 112, 113, 112, 75, 95, - 96, 237, 238, 73, 74, 112, 76, 97, 98, 100, - 99, 109, 110, 239, 111, 112, 100, 112, 26, 27, - 112, 112, 260, 112, 113, 112, 112, 28, 29, 267, - 112, 113, 268, 269, 112, 113, 72, 112, 112, 83, - 111, 102, 102, 232, 112, 103, 284, 15, 16, 17, - 112, 115, 20, 21, 22, 23, 24, 25, 26, 27, - 112, 112, 112, 31, 32, 33, 34, 35, 114, 37, - 38, 39, 40, 41, 15, 16, 17, 45, 115, 20, - 21, 22, 23, 24, 25, 26, 27, 115, 115, 101, - 31, 32, 33, 34, 35, 112, 37, 38, 39, 40, - 41, 112, 112, 112, 45, 112, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 112, 112, 112, - 98, 111, 100, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 113, 112, 74, 98, 112, 18, - 111, 113, 115, 113, 26, 92, 112, 98, 104, 112, - 36, 113, 112, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 113, 111, 28, 111, 73, 112, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 95, 111, 101, 111, 113, 98, 74, 98, 74, - 99, 111, 99, 112, 105, 111, 101, 24, 26, 112, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 154, 104, 105, 4, 5, 4, 5, 4, 4, 153, + 14, 4, 81, 186, 12, 16, 26, 189, 19, 100, + 13, 3, 15, 16, 17, 18, 74, 75, 100, 77, + 24, 35, 36, 73, 188, 39, 30, 19, 192, 193, + 184, 185, 93, 114, 98, 96, 97, 116, 102, 42, + 43, 44, 224, 74, 55, 114, 77, 114, 230, 231, + 232, 233, 114, 115, 114, 75, 220, 221, 90, 91, + 92, 0, 94, 95, 3, 247, 248, 250, 76, 8, + 9, 10, 11, 3, 110, 111, 112, 114, 8, 9, + 10, 11, 107, 108, 86, 87, 114, 115, 114, 100, + 114, 115, 101, 98, 99, 249, 278, 279, 101, 84, + 114, 96, 97, 114, 115, 114, 270, 114, 114, 103, + 111, 112, 103, 277, 113, 15, 16, 17, 26, 27, + 20, 21, 22, 23, 24, 25, 26, 27, 114, 242, + 294, 31, 32, 33, 34, 35, 114, 37, 38, 39, + 40, 41, 15, 16, 17, 45, 114, 20, 21, 22, + 23, 24, 25, 26, 27, 113, 114, 114, 31, 32, + 33, 34, 35, 114, 37, 38, 39, 40, 41, 28, + 29, 114, 45, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 114, 115, 114, 115, 114, 99, + 117, 101, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 117, 117, 117, 99, 104, 116, 114, + 102, 114, 114, 114, 114, 114, 114, 75, 114, 114, + 114, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 112, 112, 112, 112, 6, 112, 46, 47, 48, + 66, 67, 113, 115, 114, 114, 114, 18, 115, 114, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 113, 117, 26, 115, 93, 114, 114, 114, 99, + 105, 114, 36, 115, 115, 113, 28, 74, 114, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 113, 96, 113, 102, 75, 99, 115, 114, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 111, 111, - 265, 111, 113, 112, 112, 285, 113, 263, 20, 257, - -1, -1, -1, -1, -1, -1, 112, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, -1, -1, - -1, -1, -1, 112, 46, 47, 48, 49, 50, 51, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 113, + 75, 100, 99, 113, 106, 114, 113, 102, 100, 114, + 114, 114, 24, 26, 114, 6, 114, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 115, 113, + 113, 20, 114, 114, 275, 114, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 115, 113, 295, + 273, 267, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 114, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, -1, -1, -1, -1, -1, + 62, 63, 64, 65, 66, 67, -1, -1, 46, -1, + -1, -1, -1, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 112, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, -1, -1, -1, -1, -1, - 112, -1, 67, 68, 69, 70, 71, -1, -1, -1, - -1, -1, 77, 78, 79, -1, 81, 82, -1, 84, - -1, -1, 87, 88, -1, 90, 91, -1, -1, -1, - -1, -1, -1, -1, -1, 100, -1, -1, -1, -1, - 112, 106, 107, 67, 68, 69, 70, 71, -1, -1, - -1, -1, -1, 77, 78, 79, -1, 81, 82, -1, - 84, -1, -1, 87, 88, -1, 90, 91, -1, -1, - -1, -1, -1, -1, -1, -1, 100, -1, -1, -1, - -1, -1, 106, 107, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66 + 68, 69, 70, 71, 72, -1, -1, -1, -1, -1, + 78, 79, 80, -1, 82, 83, -1, 85, -1, -1, + 88, 89, 114, 91, 92, 46, -1, -1, -1, -1, + -1, -1, -1, 101, -1, -1, -1, -1, -1, 107, + -1, 109, -1, -1, -1, -1, -1, 68, 69, 70, + 71, 72, -1, -1, -1, -1, -1, 78, 79, 80, + -1, 82, 83, -1, 85, -1, -1, 88, 89, -1, + 91, 92, -1, -1, -1, -1, -1, -1, -1, -1, + 101, -1, -1, -1, -1, -1, 107, -1, 109, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 8, 9, 10, 11, 117, 118, 119, 141, - 142, 143, 175, 99, 99, 144, 144, 112, 113, 178, - 176, 0, 118, 120, 145, 144, 178, 121, 67, 68, - 69, 70, 71, 77, 78, 79, 81, 82, 84, 87, - 88, 90, 91, 100, 106, 107, 146, 147, 153, 160, - 161, 162, 163, 165, 166, 167, 168, 169, 172, 173, - 174, 4, 13, 15, 16, 17, 18, 42, 43, 44, - 100, 122, 123, 124, 125, 126, 127, 128, 112, 112, - 112, 112, 72, 4, 112, 134, 112, 80, 114, 112, - 164, 83, 85, 86, 111, 89, 90, 91, 93, 94, - 102, 102, 112, 112, 14, 35, 36, 39, 112, 112, - 113, 112, 112, 112, 129, 112, 113, 115, 115, 115, - 115, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 112, 149, 156, 177, 95, 96, 103, 114, - 111, 112, 101, 97, 98, 112, 112, 112, 112, 112, - 112, 112, 134, 134, 112, 108, 109, 110, 112, 111, - 113, 112, 24, 30, 130, 92, 95, 96, 74, 97, - 101, 157, 12, 75, 148, 148, 177, 112, 18, 111, - 115, 109, 110, 113, 113, 26, 92, 4, 5, 16, - 19, 54, 99, 112, 113, 131, 132, 73, 76, 159, - 148, 148, 112, 149, 150, 98, 158, 112, 177, 159, - 112, 177, 112, 177, 104, 170, 112, 113, 113, 36, - 111, 28, 133, 111, 73, 112, 177, 112, 177, 95, - 74, 159, 111, 101, 159, 159, 159, 159, 171, 98, - 113, 5, 100, 134, 136, 111, 155, 154, 159, 159, - 148, 149, 98, 99, 111, 112, 135, 105, 151, 151, - 112, 177, 111, 145, 135, 137, 112, 152, 177, 159, - 159, 100, 138, 139, 101, 99, 15, 16, 17, 20, + 0, 3, 8, 9, 10, 11, 119, 120, 121, 143, + 144, 145, 178, 100, 100, 146, 146, 114, 115, 181, + 179, 0, 120, 122, 147, 146, 181, 123, 46, 68, + 69, 70, 71, 72, 78, 79, 80, 82, 83, 85, + 88, 89, 91, 92, 101, 107, 109, 148, 149, 155, + 162, 163, 164, 165, 167, 168, 169, 170, 171, 172, + 175, 176, 177, 4, 13, 15, 16, 17, 18, 42, + 43, 44, 101, 124, 125, 126, 127, 128, 129, 130, + 107, 108, 114, 114, 114, 114, 73, 4, 114, 136, + 114, 81, 116, 114, 166, 84, 86, 87, 113, 90, + 91, 92, 94, 95, 103, 103, 114, 114, 14, 35, + 36, 39, 114, 114, 115, 114, 114, 114, 131, 114, + 115, 114, 114, 117, 117, 117, 117, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 114, 151, + 158, 180, 96, 97, 104, 116, 113, 114, 102, 98, + 99, 114, 114, 114, 114, 114, 114, 114, 136, 136, + 114, 110, 111, 112, 114, 113, 115, 114, 24, 30, + 132, 114, 114, 93, 96, 97, 75, 98, 102, 159, + 12, 76, 150, 150, 180, 114, 18, 113, 117, 111, + 112, 115, 115, 26, 93, 4, 5, 16, 19, 55, + 100, 114, 115, 133, 134, 114, 114, 74, 77, 161, + 150, 150, 114, 151, 152, 99, 160, 114, 180, 161, + 114, 180, 114, 180, 105, 173, 114, 115, 115, 36, + 113, 28, 135, 113, 74, 114, 180, 114, 180, 96, + 75, 161, 113, 102, 161, 161, 161, 161, 174, 99, + 115, 5, 101, 136, 138, 113, 157, 156, 161, 161, + 150, 151, 99, 100, 113, 114, 137, 106, 153, 153, + 114, 180, 113, 147, 137, 139, 114, 154, 180, 161, + 161, 101, 140, 141, 102, 100, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33, - 34, 35, 37, 38, 39, 40, 41, 45, 98, 140, - 112, 177, 139, 112, 112, 112, 26, 27, 26, 74, - 112, 111, 111, 113, 112, 112, 28, 29, 113, 112, - 113, 111, 100, 24, 112, 113, 26 + 34, 35, 37, 38, 39, 40, 41, 45, 99, 142, + 114, 180, 141, 114, 114, 114, 26, 27, 26, 75, + 114, 113, 113, 115, 114, 114, 28, 29, 115, 114, + 115, 113, 101, 24, 114, 115, 26 }; #define yyerrok (yyerrstatus = 0) @@ -2097,7 +2113,7 @@ yyparse () switch (yyn) { case 9: -#line 234 "test_spec_parse.y" +#line 236 "test_spec_parse.y" { strlcpy(current_spec->cluster.ssl, "self-signed", sizeof(current_spec->cluster.ssl)); @@ -2107,24 +2123,24 @@ yyparse () break; case 19: -#line 255 "test_spec_parse.y" +#line 257 "test_spec_parse.y" { current_spec->cluster.bindSource = true; ;} break; case 20: -#line 256 "test_spec_parse.y" +#line 258 "test_spec_parse.y" { current_spec->cluster.legacyStartup = true; ;} break; case 21: -#line 270 "test_spec_parse.y" +#line 272 "test_spec_parse.y" { current_spec->cluster.withMonitor = true; ;} break; case 22: -#line 274 "test_spec_parse.y" +#line 276 "test_spec_parse.y" { current_spec->cluster.withMonitor = true; strlcpy(current_spec->cluster.monitorDebianCluster, (yyvsp[(3) - (3)].str), @@ -2134,7 +2150,7 @@ yyparse () break; case 23: -#line 281 "test_spec_parse.y" +#line 283 "test_spec_parse.y" { current_spec->cluster.withMonitor = true; strlcpy(current_spec->cluster.monitorImageTarget, (yyvsp[(3) - (3)].str), @@ -2144,7 +2160,7 @@ yyparse () break; case 24: -#line 288 "test_spec_parse.y" +#line 290 "test_spec_parse.y" { current_spec->cluster.withMonitor = true; /* monitor port not stored in TestCluster yet; ignore */ @@ -2153,7 +2169,7 @@ yyparse () break; case 25: -#line 294 "test_spec_parse.y" +#line 296 "test_spec_parse.y" { current_spec->cluster.withMonitor = true; strlcpy(current_spec->cluster.monitorPassword, (yyvsp[(3) - (3)].str), @@ -2163,7 +2179,7 @@ yyparse () break; case 26: -#line 301 "test_spec_parse.y" +#line 303 "test_spec_parse.y" { strlcpy(current_spec->cluster.secondMonitorName, (yyvsp[(2) - (4)].str), sizeof(current_spec->cluster.secondMonitorName)); @@ -2173,7 +2189,7 @@ yyparse () break; case 27: -#line 308 "test_spec_parse.y" +#line 310 "test_spec_parse.y" { strlcpy(current_spec->cluster.secondMonitorName, (yyvsp[(2) - (4)].str), sizeof(current_spec->cluster.secondMonitorName)); @@ -2183,7 +2199,7 @@ yyparse () break; case 28: -#line 315 "test_spec_parse.y" +#line 317 "test_spec_parse.y" { strlcpy(current_spec->cluster.secondMonitorName, (yyvsp[(2) - (6)].str), sizeof(current_spec->cluster.secondMonitorName)); @@ -2195,7 +2211,7 @@ yyparse () break; case 29: -#line 328 "test_spec_parse.y" +#line 330 "test_spec_parse.y" { strlcpy(current_spec->cluster.image, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.image)); @@ -2204,7 +2220,7 @@ yyparse () break; case 30: -#line 334 "test_spec_parse.y" +#line 336 "test_spec_parse.y" { strlcpy(current_spec->cluster.image, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.image)); @@ -2213,7 +2229,7 @@ yyparse () break; case 31: -#line 344 "test_spec_parse.y" +#line 346 "test_spec_parse.y" { strlcpy(current_spec->cluster.extensionVersion, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.extensionVersion)); @@ -2222,7 +2238,7 @@ yyparse () break; case 32: -#line 350 "test_spec_parse.y" +#line 352 "test_spec_parse.y" { strlcpy(current_spec->cluster.extensionVersion, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.extensionVersion)); @@ -2231,7 +2247,7 @@ yyparse () break; case 33: -#line 360 "test_spec_parse.y" +#line 362 "test_spec_parse.y" { strlcpy(current_spec->cluster.ssl, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.ssl)); @@ -2240,7 +2256,7 @@ yyparse () break; case 34: -#line 370 "test_spec_parse.y" +#line 372 "test_spec_parse.y" { strlcpy(current_spec->cluster.auth, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.auth)); @@ -2249,7 +2265,7 @@ yyparse () break; case 35: -#line 376 "test_spec_parse.y" +#line 378 "test_spec_parse.y" { strlcpy(current_spec->cluster.auth, (yyvsp[(2) - (2)].str), sizeof(current_spec->cluster.auth)); @@ -2258,7 +2274,7 @@ yyparse () break; case 36: -#line 386 "test_spec_parse.y" +#line 388 "test_spec_parse.y" { TestCluster *cl = ¤t_spec->cluster; if (cl->formationCount >= PGAF_MAX_FORMATIONS) @@ -2275,32 +2291,32 @@ yyparse () break; case 40: -#line 413 "test_spec_parse.y" +#line 415 "test_spec_parse.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; case 41: -#line 414 "test_spec_parse.y" +#line 416 "test_spec_parse.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; case 42: -#line 415 "test_spec_parse.y" +#line 417 "test_spec_parse.y" { (yyval.str) = strdup("auth"); ;} break; case 43: -#line 416 "test_spec_parse.y" +#line 418 "test_spec_parse.y" { (yyval.str) = strdup("monitor"); ;} break; case 44: -#line 417 "test_spec_parse.y" +#line 419 "test_spec_parse.y" { (yyval.str) = strdup("node"); ;} break; case 45: -#line 422 "test_spec_parse.y" +#line 424 "test_spec_parse.y" { strlcpy(current_formation->name, (yyvsp[(1) - (1)].str), sizeof(current_formation->name)); free((yyvsp[(1) - (1)].str)); @@ -2308,31 +2324,31 @@ yyparse () break; case 46: -#line 427 "test_spec_parse.y" +#line 429 "test_spec_parse.y" { current_formation->numSync = (yyvsp[(2) - (2)].ival); ;} break; case 47: -#line 431 "test_spec_parse.y" +#line 433 "test_spec_parse.y" { current_formation->disableSecondary = true; ;} break; case 50: -#line 457 "test_spec_parse.y" +#line 459 "test_spec_parse.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; case 51: -#line 458 "test_spec_parse.y" +#line 460 "test_spec_parse.y" { (yyval.str) = strdup("monitor"); ;} break; case 52: -#line 467 "test_spec_parse.y" +#line 469 "test_spec_parse.y" { if (current_formation->nodeCount >= PGAF_MAX_NODES) { @@ -2348,7 +2364,7 @@ yyparse () break; case 53: -#line 484 "test_spec_parse.y" +#line 486 "test_spec_parse.y" { strlcpy(current_node->name, (yyvsp[(1) - (2)].str), sizeof(current_node->name)); free((yyvsp[(1) - (2)].str)); @@ -2356,7 +2372,7 @@ yyparse () break; case 55: -#line 491 "test_spec_parse.y" +#line 493 "test_spec_parse.y" { strlcpy(current_node->name, (yyvsp[(2) - (3)].str), sizeof(current_node->name)); free((yyvsp[(2) - (3)].str)); @@ -2364,7 +2380,7 @@ yyparse () break; case 59: -#line 505 "test_spec_parse.y" +#line 507 "test_spec_parse.y" { current_node->kind = NODE_KIND_CITUS_COORDINATOR; current_spec->cluster.withCitus = true; @@ -2372,7 +2388,7 @@ yyparse () break; case 60: -#line 510 "test_spec_parse.y" +#line 512 "test_spec_parse.y" { current_node->kind = NODE_KIND_CITUS_WORKER; current_spec->cluster.withCitus = true; @@ -2380,21 +2396,21 @@ yyparse () break; case 61: -#line 515 "test_spec_parse.y" +#line 517 "test_spec_parse.y" { current_node->replicationQuorum = false; ;} break; case 62: -#line 519 "test_spec_parse.y" +#line 521 "test_spec_parse.y" { current_node->noMonitor = true; ;} break; case 63: -#line 523 "test_spec_parse.y" +#line 525 "test_spec_parse.y" { /* bare "deferred" = create and launch deferred (both gates) */ current_node->createDeferred = true; @@ -2403,7 +2419,7 @@ yyparse () break; case 64: -#line 529 "test_spec_parse.y" +#line 531 "test_spec_parse.y" { /* "launch deferred" alone = run-deferred only, create immediate */ current_node->launchDeferred = true; @@ -2411,14 +2427,14 @@ yyparse () break; case 65: -#line 534 "test_spec_parse.y" +#line 536 "test_spec_parse.y" { current_node->createDeferred = true; ;} break; case 66: -#line 538 "test_spec_parse.y" +#line 540 "test_spec_parse.y" { current_node->createDeferred = true; current_node->launchDeferred = true; @@ -2426,42 +2442,42 @@ yyparse () break; case 67: -#line 543 "test_spec_parse.y" +#line 545 "test_spec_parse.y" { current_node->launchDeferred = false; ;} break; case 68: -#line 547 "test_spec_parse.y" +#line 549 "test_spec_parse.y" { current_node->launchDeferred = false; ;} break; case 69: -#line 551 "test_spec_parse.y" +#line 553 "test_spec_parse.y" { current_node->listen = true; ;} break; case 70: -#line 555 "test_spec_parse.y" +#line 557 "test_spec_parse.y" { current_node->citusSecondary = true; ;} break; case 71: -#line 559 "test_spec_parse.y" +#line 561 "test_spec_parse.y" { current_node->candidatePriority = (yyvsp[(2) - (2)].ival); ;} break; case 72: -#line 563 "test_spec_parse.y" +#line 565 "test_spec_parse.y" { strlcpy(current_node->region, (yyvsp[(2) - (2)].str), sizeof(current_node->region)); free((yyvsp[(2) - (2)].str)); @@ -2469,7 +2485,7 @@ yyparse () break; case 73: -#line 568 "test_spec_parse.y" +#line 570 "test_spec_parse.y" { strlcpy(current_node->region, (yyvsp[(2) - (2)].str), sizeof(current_node->region)); free((yyvsp[(2) - (2)].str)); @@ -2477,21 +2493,21 @@ yyparse () break; case 74: -#line 573 "test_spec_parse.y" +#line 575 "test_spec_parse.y" { current_node->group = (yyvsp[(2) - (2)].ival); ;} break; case 75: -#line 577 "test_spec_parse.y" +#line 579 "test_spec_parse.y" { current_node->pgPort = (yyvsp[(2) - (2)].ival); ;} break; case 76: -#line 581 "test_spec_parse.y" +#line 583 "test_spec_parse.y" { strlcpy(current_node->citusClusterName, (yyvsp[(2) - (2)].str), sizeof(current_node->citusClusterName)); @@ -2500,7 +2516,7 @@ yyparse () break; case 77: -#line 587 "test_spec_parse.y" +#line 589 "test_spec_parse.y" { strlcpy(current_node->debianCluster, (yyvsp[(2) - (2)].str), sizeof(current_node->debianCluster)); @@ -2509,7 +2525,7 @@ yyparse () break; case 78: -#line 593 "test_spec_parse.y" +#line 595 "test_spec_parse.y" { strlcpy(current_node->ssl, (yyvsp[(2) - (2)].str), sizeof(current_node->ssl)); free((yyvsp[(2) - (2)].str)); @@ -2517,7 +2533,7 @@ yyparse () break; case 79: -#line 598 "test_spec_parse.y" +#line 600 "test_spec_parse.y" { strlcpy(current_node->auth, (yyvsp[(2) - (2)].str), sizeof(current_node->auth)); free((yyvsp[(2) - (2)].str)); @@ -2525,7 +2541,7 @@ yyparse () break; case 80: -#line 603 "test_spec_parse.y" +#line 605 "test_spec_parse.y" { strlcpy(current_node->auth, (yyvsp[(2) - (2)].str), sizeof(current_node->auth)); free((yyvsp[(2) - (2)].str)); @@ -2533,21 +2549,21 @@ yyparse () break; case 81: -#line 608 "test_spec_parse.y" +#line 610 "test_spec_parse.y" { current_node->replicationQuorum = true; ;} break; case 82: -#line 612 "test_spec_parse.y" +#line 614 "test_spec_parse.y" { current_node->replicationQuorum = false; ;} break; case 83: -#line 616 "test_spec_parse.y" +#line 618 "test_spec_parse.y" { strlcpy(current_node->replicationPassword, (yyvsp[(2) - (2)].str), sizeof(current_node->replicationPassword)); @@ -2556,7 +2572,7 @@ yyparse () break; case 84: -#line 622 "test_spec_parse.y" +#line 624 "test_spec_parse.y" { strlcpy(current_node->monitorPassword, (yyvsp[(2) - (2)].str), sizeof(current_node->monitorPassword)); @@ -2565,7 +2581,7 @@ yyparse () break; case 85: -#line 628 "test_spec_parse.y" +#line 630 "test_spec_parse.y" { /* volume — adds a named Docker volume */ int vi = current_node->volumeCount; @@ -2582,7 +2598,7 @@ yyparse () break; case 86: -#line 642 "test_spec_parse.y" +#line 644 "test_spec_parse.y" { /* volume "/path/with spaces" */ int vi = current_node->volumeCount; @@ -2599,21 +2615,21 @@ yyparse () break; case 87: -#line 663 "test_spec_parse.y" +#line 665 "test_spec_parse.y" { current_spec->setup = (yyvsp[(2) - (2)].step); ;} break; case 88: -#line 670 "test_spec_parse.y" +#line 672 "test_spec_parse.y" { current_spec->teardown = (yyvsp[(2) - (2)].step); ;} break; case 89: -#line 681 "test_spec_parse.y" +#line 683 "test_spec_parse.y" { TestStep *s = (yyvsp[(3) - (3)].step); strncpy(s->name, (yyvsp[(2) - (3)].str), sizeof(s->name) - 1); @@ -2623,7 +2639,7 @@ yyparse () break; case 90: -#line 699 "test_spec_parse.y" +#line 701 "test_spec_parse.y" { /* post-process: CMD_SQL immediately before CMD_EXPECT_ERROR */ for (TestCmd *c = (yyvsp[(2) - (3)].step)->commands; c; c = c->next) @@ -2637,14 +2653,14 @@ yyparse () break; case 91: -#line 713 "test_spec_parse.y" +#line 715 "test_spec_parse.y" { (yyval.step) = make_step(""); ;} break; case 92: -#line 717 "test_spec_parse.y" +#line 719 "test_spec_parse.y" { if ((yyvsp[(2) - (2)].cmd)) append_cmd((yyvsp[(1) - (2)].step), (yyvsp[(2) - (2)].cmd)); (yyval.step) = (yyvsp[(1) - (2)].step); @@ -2652,77 +2668,82 @@ yyparse () break; case 93: -#line 724 "test_spec_parse.y" +#line 726 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 94: -#line 725 "test_spec_parse.y" +#line 727 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 95: -#line 726 "test_spec_parse.y" +#line 728 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 96: -#line 727 "test_spec_parse.y" +#line 729 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 97: -#line 728 "test_spec_parse.y" +#line 730 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 98: -#line 729 "test_spec_parse.y" +#line 731 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 99: -#line 730 "test_spec_parse.y" +#line 732 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 100: -#line 731 "test_spec_parse.y" +#line 733 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 101: -#line 732 "test_spec_parse.y" +#line 734 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 102: -#line 733 "test_spec_parse.y" +#line 735 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 103: -#line 734 "test_spec_parse.y" +#line 736 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 104: -#line 735 "test_spec_parse.y" +#line 737 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 105: -#line 736 "test_spec_parse.y" +#line 738 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 106: -#line 737 "test_spec_parse.y" +#line 739 "test_spec_parse.y" { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} break; case 107: -#line 752 "test_spec_parse.y" +#line 740 "test_spec_parse.y" + { (yyval.cmd) = (yyvsp[(1) - (1)].cmd); ;} + break; + + case 108: +#line 755 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXEC); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (3)].str), sizeof((yyval.cmd)->service)); @@ -2731,8 +2752,8 @@ yyparse () ;} break; - case 108: -#line 759 "test_spec_parse.y" + case 109: +#line 762 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXEC); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (2)].str), sizeof((yyval.cmd)->service)); @@ -2740,8 +2761,8 @@ yyparse () ;} break; - case 109: -#line 765 "test_spec_parse.y" + case 110: +#line 768 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXEC_FAILS); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (3)].str), sizeof((yyval.cmd)->service)); @@ -2750,8 +2771,8 @@ yyparse () ;} break; - case 110: -#line 772 "test_spec_parse.y" + case 111: +#line 775 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXEC_FAILS); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (2)].str), sizeof((yyval.cmd)->service)); @@ -2759,8 +2780,8 @@ yyparse () ;} break; - case 111: -#line 778 "test_spec_parse.y" + case 112: +#line 781 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_RUN); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (3)].str), sizeof((yyval.cmd)->service)); @@ -2769,8 +2790,8 @@ yyparse () ;} break; - case 112: -#line 785 "test_spec_parse.y" + case 113: +#line 788 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_RUN); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (2)].str), sizeof((yyval.cmd)->service)); @@ -2778,8 +2799,8 @@ yyparse () ;} break; - case 113: -#line 791 "test_spec_parse.y" + case 114: +#line 794 "test_spec_parse.y" { /* "pg_autoctl perform failover --formation auth" * EXEC_ARGS returns T_IDENT for first word, T_SHELL_ARGS for rest */ @@ -2789,8 +2810,8 @@ yyparse () ;} break; - case 114: -#line 799 "test_spec_parse.y" + case 115: +#line 802 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_PG_AUTOCTL); strlcpy((yyval.cmd)->args, (yyvsp[(2) - (2)].str), sizeof((yyval.cmd)->args)); @@ -2798,15 +2819,15 @@ yyparse () ;} break; - case 115: -#line 805 "test_spec_parse.y" + case 116: +#line 808 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_PG_AUTOCTL); ;} break; - case 118: -#line 843 "test_spec_parse.y" + case 119: +#line 846 "test_spec_parse.y" { if (!current_wait_cmd) current_wait_cmd = make_cmd(CMD_WAIT_MULTI); @@ -2823,8 +2844,8 @@ yyparse () ;} break; - case 119: -#line 858 "test_spec_parse.y" + case 120: +#line 861 "test_spec_parse.y" { if (!current_wait_cmd) current_wait_cmd = make_cmd(CMD_WAIT_MULTI); @@ -2841,8 +2862,8 @@ yyparse () ;} break; - case 124: -#line 898 "test_spec_parse.y" + case 125: +#line 901 "test_spec_parse.y" { /* current_pass_cmd set by the enclosing wait_cmd rule */ if (current_pass_cmd && @@ -2852,8 +2873,8 @@ yyparse () ;} break; - case 125: -#line 906 "test_spec_parse.y" + case 126: +#line 909 "test_spec_parse.y" { if (current_pass_cmd && current_pass_cmd->passThroughCount < PGAF_MAX_WAIT_STATES) @@ -2863,8 +2884,8 @@ yyparse () ;} break; - case 126: -#line 914 "test_spec_parse.y" + case 127: +#line 917 "test_spec_parse.y" { if (current_pass_cmd && current_pass_cmd->passThroughCount < PGAF_MAX_WAIT_STATES) @@ -2873,8 +2894,8 @@ yyparse () ;} break; - case 127: -#line 921 "test_spec_parse.y" + case 128: +#line 924 "test_spec_parse.y" { if (current_pass_cmd && current_pass_cmd->passThroughCount < PGAF_MAX_WAIT_STATES) @@ -2884,16 +2905,16 @@ yyparse () ;} break; - case 128: -#line 932 "test_spec_parse.y" + case 129: +#line 935 "test_spec_parse.y" { current_pass_cmd = make_cmd(CMD_WAIT_STATE); strlcpy(current_pass_cmd->service, (yyvsp[(3) - (6)].str), sizeof(current_pass_cmd->service)); strlcpy(current_pass_cmd->state, (yyvsp[(6) - (6)].str), sizeof(current_pass_cmd->state)); free((yyvsp[(3) - (6)].str)); ;} break; - case 129: -#line 937 "test_spec_parse.y" + case 130: +#line 940 "test_spec_parse.y" { current_pass_cmd->timeoutSeconds = (yyvsp[(9) - (9)].ival); (yyval.cmd) = current_pass_cmd; @@ -2901,16 +2922,16 @@ yyparse () ;} break; - case 130: -#line 943 "test_spec_parse.y" + case 131: +#line 946 "test_spec_parse.y" { current_pass_cmd = make_cmd(CMD_WAIT_STATE); strlcpy(current_pass_cmd->service, (yyvsp[(3) - (6)].str), sizeof(current_pass_cmd->service)); strlcpy(current_pass_cmd->state, (yyvsp[(6) - (6)].str), sizeof(current_pass_cmd->state)); free((yyvsp[(3) - (6)].str)); free((yyvsp[(6) - (6)].str)); ;} break; - case 131: -#line 948 "test_spec_parse.y" + case 132: +#line 951 "test_spec_parse.y" { current_pass_cmd->timeoutSeconds = (yyvsp[(9) - (9)].ival); (yyval.cmd) = current_pass_cmd; @@ -2918,8 +2939,8 @@ yyparse () ;} break; - case 132: -#line 954 "test_spec_parse.y" + case 133: +#line 957 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_WAIT_STATE); (yyval.cmd)->kind = CMD_ASSERT_ASSIGNED; @@ -2930,8 +2951,8 @@ yyparse () ;} break; - case 133: -#line 963 "test_spec_parse.y" + case 134: +#line 966 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_WAIT_STATE); (yyval.cmd)->kind = CMD_ASSERT_ASSIGNED; @@ -2942,8 +2963,8 @@ yyparse () ;} break; - case 134: -#line 972 "test_spec_parse.y" + case 135: +#line 975 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_WAIT_STOPPED); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (5)].str), sizeof((yyval.cmd)->service)); @@ -2952,8 +2973,8 @@ yyparse () ;} break; - case 135: -#line 979 "test_spec_parse.y" + case 136: +#line 982 "test_spec_parse.y" { (yyval.cmd) = current_wait_cmd; (yyval.cmd)->timeoutSeconds = (yyvsp[(5) - (5)].ival); @@ -2961,8 +2982,8 @@ yyparse () ;} break; - case 136: -#line 993 "test_spec_parse.y" + case 137: +#line 996 "test_spec_parse.y" { (yyval.cmd) = current_wait_cmd; (yyval.cmd)->timeoutSeconds = (yyvsp[(6) - (6)].ival); @@ -2970,8 +2991,8 @@ yyparse () ;} break; - case 137: -#line 1008 "test_spec_parse.y" + case 138: +#line 1011 "test_spec_parse.y" { current_wait_cmd = make_cmd(CMD_WAIT_STATES); strlcpy(current_wait_cmd->waitStates[current_wait_cmd->waitStateCount++], @@ -2979,8 +3000,8 @@ yyparse () ;} break; - case 138: -#line 1014 "test_spec_parse.y" + case 139: +#line 1017 "test_spec_parse.y" { current_wait_cmd = make_cmd(CMD_WAIT_STATES); strlcpy(current_wait_cmd->waitStates[current_wait_cmd->waitStateCount++], @@ -2989,8 +3010,8 @@ yyparse () ;} break; - case 139: -#line 1021 "test_spec_parse.y" + case 140: +#line 1024 "test_spec_parse.y" { if (current_wait_cmd->waitStateCount < PGAF_MAX_WAIT_STATES) strlcpy(current_wait_cmd->waitStates[current_wait_cmd->waitStateCount++], @@ -2998,8 +3019,8 @@ yyparse () ;} break; - case 140: -#line 1027 "test_spec_parse.y" + case 141: +#line 1030 "test_spec_parse.y" { if (current_wait_cmd->waitStateCount < PGAF_MAX_WAIT_STATES) strlcpy(current_wait_cmd->waitStates[current_wait_cmd->waitStateCount++], @@ -3008,39 +3029,39 @@ yyparse () ;} break; - case 143: -#line 1046 "test_spec_parse.y" + case 144: +#line 1049 "test_spec_parse.y" { if (current_wait_cmd->waitGroupCount < PGAF_MAX_WAIT_GROUPS) current_wait_cmd->waitGroups[current_wait_cmd->waitGroupCount++] = (yyvsp[(2) - (2)].ival); ;} break; - case 144: -#line 1051 "test_spec_parse.y" + case 145: +#line 1054 "test_spec_parse.y" { if (current_wait_cmd->waitGroupCount < PGAF_MAX_WAIT_GROUPS) current_wait_cmd->waitGroups[current_wait_cmd->waitGroupCount++] = (yyvsp[(4) - (4)].ival); ;} break; - case 145: -#line 1058 "test_spec_parse.y" + case 146: +#line 1061 "test_spec_parse.y" { (yyval.ival) = PGAF_TIMEOUT_DEFAULT; ;} break; - case 146: -#line 1059 "test_spec_parse.y" + case 147: +#line 1062 "test_spec_parse.y" { (yyval.ival) = (yyvsp[(2) - (2)].ival); ;} break; - case 147: -#line 1060 "test_spec_parse.y" + case 148: +#line 1063 "test_spec_parse.y" { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} break; - case 148: -#line 1072 "test_spec_parse.y" + case 149: +#line 1075 "test_spec_parse.y" { (yyval.cmd) = make_cmd((yyvsp[(6) - (6)].ival) > 0 ? CMD_WAIT_STATE : CMD_ASSERT_STATE); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (6)].str), sizeof((yyval.cmd)->service)); @@ -3050,8 +3071,8 @@ yyparse () ;} break; - case 149: -#line 1080 "test_spec_parse.y" + case 150: +#line 1083 "test_spec_parse.y" { (yyval.cmd) = make_cmd((yyvsp[(6) - (6)].ival) > 0 ? CMD_WAIT_STATE : CMD_ASSERT_STATE); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (6)].str), sizeof((yyval.cmd)->service)); @@ -3061,8 +3082,8 @@ yyparse () ;} break; - case 150: -#line 1088 "test_spec_parse.y" + case 151: +#line 1091 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_ASSERT_ASSIGNED); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (6)].str), sizeof((yyval.cmd)->service)); @@ -3072,8 +3093,8 @@ yyparse () ;} break; - case 151: -#line 1096 "test_spec_parse.y" + case 152: +#line 1099 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_ASSERT_ASSIGNED); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (6)].str), sizeof((yyval.cmd)->service)); @@ -3083,8 +3104,8 @@ yyparse () ;} break; - case 152: -#line 1114 "test_spec_parse.y" + case 153: +#line 1117 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_SQL); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3093,8 +3114,8 @@ yyparse () ;} break; - case 153: -#line 1129 "test_spec_parse.y" + case 154: +#line 1132 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXPECT); strlcpy((yyval.cmd)->expected, (yyvsp[(2) - (2)].str), sizeof((yyval.cmd)->expected)); @@ -3103,15 +3124,15 @@ yyparse () ;} break; - case 154: -#line 1136 "test_spec_parse.y" + case 155: +#line 1139 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXPECT_ERROR); ;} break; - case 155: -#line 1140 "test_spec_parse.y" + case 156: +#line 1143 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_EXPECT_ERROR); strlcpy((yyval.cmd)->state, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->state)); @@ -3119,8 +3140,8 @@ yyparse () ;} break; - case 156: -#line 1146 "test_spec_parse.y" + case 157: +#line 1149 "test_spec_parse.y" { /* SQLSTATE codes like 25006 are all digits, lexed as T_INTEGER */ (yyval.cmd) = make_cmd(CMD_EXPECT_ERROR); @@ -3128,16 +3149,16 @@ yyparse () ;} break; - case 157: -#line 1159 "test_spec_parse.y" + case 158: +#line 1162 "test_spec_parse.y" { (yyval.cmd) = current_promote_cmd; current_promote_cmd = NULL; ;} break; - case 158: -#line 1167 "test_spec_parse.y" + case 159: +#line 1170 "test_spec_parse.y" { current_promote_cmd = make_cmd(CMD_PROMOTE); current_promote_cmd->timeoutSeconds = PGAF_TIMEOUT_DEFAULT; @@ -3147,8 +3168,8 @@ yyparse () ;} break; - case 159: -#line 1175 "test_spec_parse.y" + case 160: +#line 1178 "test_spec_parse.y" { if (current_promote_cmd->promoteCount < PGAF_MAX_PROMOTE_NODES) strlcpy(current_promote_cmd->promoteNodes[current_promote_cmd->promoteCount++], @@ -3157,8 +3178,8 @@ yyparse () ;} break; - case 160: -#line 1196 "test_spec_parse.y" + case 161: +#line 1199 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_FAILOVER); strlcpy((yyval.cmd)->service, "default", sizeof((yyval.cmd)->service)); @@ -3167,8 +3188,8 @@ yyparse () ;} break; - case 161: -#line 1203 "test_spec_parse.y" + case 162: +#line 1206 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_FAILOVER); strlcpy((yyval.cmd)->service, "default", sizeof((yyval.cmd)->service)); @@ -3177,8 +3198,8 @@ yyparse () ;} break; - case 162: -#line 1210 "test_spec_parse.y" + case 163: +#line 1213 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_FAILOVER); strlcpy((yyval.cmd)->service, (yyvsp[(5) - (5)].str), sizeof((yyval.cmd)->service)); @@ -3188,8 +3209,8 @@ yyparse () ;} break; - case 163: -#line 1218 "test_spec_parse.y" + case 164: +#line 1221 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_FAILOVER); strlcpy((yyval.cmd)->service, (yyvsp[(5) - (7)].str), sizeof((yyval.cmd)->service)); @@ -3199,8 +3220,8 @@ yyparse () ;} break; - case 164: -#line 1234 "test_spec_parse.y" + case 165: +#line 1237 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_NETWORK_OFF); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3208,8 +3229,8 @@ yyparse () ;} break; - case 165: -#line 1240 "test_spec_parse.y" + case 166: +#line 1243 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_NETWORK_ON); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3217,23 +3238,45 @@ yyparse () ;} break; - case 166: -#line 1253 "test_spec_parse.y" + case 167: +#line 1264 "test_spec_parse.y" + { + (yyval.cmd) = make_cmd(CMD_NODEINI_SET); + strlcpy((yyval.cmd)->service, (yyvsp[(3) - (5)].str), sizeof((yyval.cmd)->service)); + strlcpy((yyval.cmd)->state, (yyvsp[(4) - (5)].str), sizeof((yyval.cmd)->state)); + strlcpy((yyval.cmd)->args, (yyvsp[(5) - (5)].str), sizeof((yyval.cmd)->args)); + free((yyvsp[(3) - (5)].str)); free((yyvsp[(4) - (5)].str)); free((yyvsp[(5) - (5)].str)); + ;} + break; + + case 168: +#line 1272 "test_spec_parse.y" + { + (yyval.cmd) = make_cmd(CMD_NODEINI_GET); + strlcpy((yyval.cmd)->service, (yyvsp[(3) - (5)].str), sizeof((yyval.cmd)->service)); + strlcpy((yyval.cmd)->state, (yyvsp[(4) - (5)].str), sizeof((yyval.cmd)->state)); + strlcpy((yyval.cmd)->args, (yyvsp[(5) - (5)].str), sizeof((yyval.cmd)->args)); + free((yyvsp[(3) - (5)].str)); free((yyvsp[(4) - (5)].str)); free((yyvsp[(5) - (5)].str)); + ;} + break; + + case 169: +#line 1287 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_SLEEP); (yyval.cmd)->timeoutSeconds = (yyvsp[(2) - (2)].ival); ;} break; - case 167: -#line 1267 "test_spec_parse.y" + case 170: +#line 1301 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_COMPOSE_DOWN); ;} break; - case 168: -#line 1271 "test_spec_parse.y" + case 171: +#line 1305 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_COMPOSE_START); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3241,8 +3284,8 @@ yyparse () ;} break; - case 169: -#line 1277 "test_spec_parse.y" + case 172: +#line 1311 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_COMPOSE_STOP); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3250,8 +3293,8 @@ yyparse () ;} break; - case 170: -#line 1283 "test_spec_parse.y" + case 173: +#line 1317 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_COMPOSE_KILL); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3259,8 +3302,8 @@ yyparse () ;} break; - case 171: -#line 1309 "test_spec_parse.y" + case 174: +#line 1343 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_COMPOSE_INJECT); strlcpy((yyval.cmd)->expected, (yyvsp[(3) - (4)].str), sizeof((yyval.cmd)->expected)); /* image */ @@ -3285,8 +3328,8 @@ yyparse () ;} break; - case 172: -#line 1343 "test_spec_parse.y" + case 175: +#line 1377 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_STOP_POSTGRES); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3294,8 +3337,8 @@ yyparse () ;} break; - case 173: -#line 1349 "test_spec_parse.y" + case 176: +#line 1383 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_START_POSTGRES); strlcpy((yyval.cmd)->service, (yyvsp[(3) - (3)].str), sizeof((yyval.cmd)->service)); @@ -3303,18 +3346,18 @@ yyparse () ;} break; - case 174: -#line 1365 "test_spec_parse.y" + case 177: +#line 1399 "test_spec_parse.y" { pgaf_next_brace_is_while = 1; ;} break; - case 175: -#line 1366 "test_spec_parse.y" + case 178: +#line 1400 "test_spec_parse.y" { (yyval.step) = (yyvsp[(4) - (5)].step); ;} break; - case 176: -#line 1371 "test_spec_parse.y" + case 179: +#line 1405 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_STAYS_WHILE); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (5)].str), sizeof((yyval.cmd)->service)); @@ -3324,8 +3367,8 @@ yyparse () ;} break; - case 177: -#line 1390 "test_spec_parse.y" + case 180: +#line 1424 "test_spec_parse.y" { /* only "set monitor " is supported; $2 must be "monitor" */ if (strcmp((yyvsp[(2) - (3)].str), "monitor") != 0) @@ -3340,8 +3383,8 @@ yyparse () ;} break; - case 178: -#line 1415 "test_spec_parse.y" + case 181: +#line 1449 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_LOGS_CHECK); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (4)].str), sizeof((yyval.cmd)->service)); @@ -3352,8 +3395,8 @@ yyparse () ;} break; - case 179: -#line 1424 "test_spec_parse.y" + case 182: +#line 1458 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_LOGS_CHECK); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (5)].str), sizeof((yyval.cmd)->service)); @@ -3364,8 +3407,8 @@ yyparse () ;} break; - case 180: -#line 1433 "test_spec_parse.y" + case 183: +#line 1467 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_LOGS_CHECK); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (4)].str), sizeof((yyval.cmd)->service)); @@ -3376,8 +3419,8 @@ yyparse () ;} break; - case 181: -#line 1442 "test_spec_parse.y" + case 184: +#line 1476 "test_spec_parse.y" { (yyval.cmd) = make_cmd(CMD_LOGS_CHECK); strlcpy((yyval.cmd)->service, (yyvsp[(2) - (5)].str), sizeof((yyval.cmd)->service)); @@ -3388,8 +3431,8 @@ yyparse () ;} break; - case 184: -#line 1463 "test_spec_parse.y" + case 187: +#line 1497 "test_spec_parse.y" { int i = current_spec->sequenceLength; if (i < PGAF_MAX_SEQ) @@ -3403,124 +3446,124 @@ yyparse () ;} break; - case 185: -#line 1484 "test_spec_parse.y" + case 188: +#line 1518 "test_spec_parse.y" { (yyval.str) = "init"; ;} break; - case 186: -#line 1485 "test_spec_parse.y" + case 189: +#line 1519 "test_spec_parse.y" { (yyval.str) = "single"; ;} break; - case 187: -#line 1486 "test_spec_parse.y" + case 190: +#line 1520 "test_spec_parse.y" { (yyval.str) = "primary"; ;} break; - case 188: -#line 1487 "test_spec_parse.y" + case 191: +#line 1521 "test_spec_parse.y" { (yyval.str) = "wait_primary"; ;} break; - case 189: -#line 1488 "test_spec_parse.y" + case 192: +#line 1522 "test_spec_parse.y" { (yyval.str) = "wait_standby"; ;} break; - case 190: -#line 1489 "test_spec_parse.y" + case 193: +#line 1523 "test_spec_parse.y" { (yyval.str) = "demoted"; ;} break; - case 191: -#line 1490 "test_spec_parse.y" + case 194: +#line 1524 "test_spec_parse.y" { (yyval.str) = "demote_timeout"; ;} break; - case 192: -#line 1491 "test_spec_parse.y" + case 195: +#line 1525 "test_spec_parse.y" { (yyval.str) = "draining"; ;} break; - case 193: -#line 1492 "test_spec_parse.y" + case 196: +#line 1526 "test_spec_parse.y" { (yyval.str) = "secondary"; ;} break; - case 194: -#line 1493 "test_spec_parse.y" + case 197: +#line 1527 "test_spec_parse.y" { (yyval.str) = "catchingup"; ;} break; - case 195: -#line 1494 "test_spec_parse.y" + case 198: +#line 1528 "test_spec_parse.y" { (yyval.str) = "prepare_promotion"; ;} break; - case 196: -#line 1495 "test_spec_parse.y" + case 199: +#line 1529 "test_spec_parse.y" { (yyval.str) = "stop_replication"; ;} break; - case 197: -#line 1496 "test_spec_parse.y" + case 200: +#line 1530 "test_spec_parse.y" { (yyval.str) = "maintenance"; ;} break; - case 198: -#line 1497 "test_spec_parse.y" + case 201: +#line 1531 "test_spec_parse.y" { (yyval.str) = "join_primary"; ;} break; - case 199: -#line 1498 "test_spec_parse.y" + case 202: +#line 1532 "test_spec_parse.y" { (yyval.str) = "apply_settings"; ;} break; - case 200: -#line 1499 "test_spec_parse.y" + case 203: +#line 1533 "test_spec_parse.y" { (yyval.str) = "prepare_maintenance"; ;} break; - case 201: -#line 1500 "test_spec_parse.y" + case 204: +#line 1534 "test_spec_parse.y" { (yyval.str) = "wait_maintenance"; ;} break; - case 202: -#line 1501 "test_spec_parse.y" + case 205: +#line 1535 "test_spec_parse.y" { (yyval.str) = "report_lsn"; ;} break; - case 203: -#line 1502 "test_spec_parse.y" + case 206: +#line 1536 "test_spec_parse.y" { (yyval.str) = "fast_forward"; ;} break; - case 204: -#line 1503 "test_spec_parse.y" + case 207: +#line 1537 "test_spec_parse.y" { (yyval.str) = "join_secondary"; ;} break; - case 205: -#line 1504 "test_spec_parse.y" + case 208: +#line 1538 "test_spec_parse.y" { (yyval.str) = "dropped"; ;} break; - case 206: -#line 1512 "test_spec_parse.y" + case 209: +#line 1546 "test_spec_parse.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; - case 207: -#line 1513 "test_spec_parse.y" + case 210: +#line 1547 "test_spec_parse.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; /* Line 1267 of yacc.c. */ -#line 3524 "test_spec_parse.c" +#line 3567 "test_spec_parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3734,7 +3777,7 @@ yyparse () } -#line 1516 "test_spec_parse.y" +#line 1550 "test_spec_parse.y" /* ----------------------------------------------------------------------- diff --git a/src/bin/pgaftest/test_spec_parse.h b/src/bin/pgaftest/test_spec_parse.h index 606b58134..9a5acacc7 100644 --- a/src/bin/pgaftest/test_spec_parse.h +++ b/src/bin/pgaftest/test_spec_parse.h @@ -82,76 +82,78 @@ T_BIND_SOURCE = 298, T_LEGACY_STARTUP = 299, T_REGION = 300, - T_FS_INIT = 301, - T_FS_SINGLE = 302, - T_FS_PRIMARY = 303, - T_FS_WAIT_PRIMARY = 304, - T_FS_WAIT_STANDBY = 305, - T_FS_DEMOTED = 306, - T_FS_DEMOTE_TIMEOUT = 307, - T_FS_DRAINING = 308, - T_FS_SECONDARY = 309, - T_FS_CATCHINGUP = 310, - T_FS_PREP_PROMOTION = 311, - T_FS_STOP_REPLICATION = 312, - T_FS_MAINTENANCE = 313, - T_FS_JOIN_PRIMARY = 314, - T_FS_APPLY_SETTINGS = 315, - T_FS_PREPARE_MAINTENANCE = 316, - T_FS_WAIT_MAINTENANCE = 317, - T_FS_REPORT_LSN = 318, - T_FS_FAST_FORWARD = 319, - T_FS_JOIN_SECONDARY = 320, - T_FS_DROPPED = 321, - T_EXEC = 322, - T_EXEC_FAILS = 323, - T_RUN = 324, - T_PG_AUTOCTL = 325, - T_WAIT = 326, - T_UNTIL = 327, - T_TIMEOUT = 328, - T_AND = 329, - T_IS = 330, - T_WITH = 331, - T_ASSERT = 332, - T_SQL = 333, - T_EXPECT = 334, - T_ERROR = 335, - T_PROMOTE = 336, - T_PERFORM = 337, - T_FAILOVER = 338, - T_NETWORK = 339, - T_DISCONNECT = 340, - T_CONNECT = 341, - T_SLEEP = 342, - T_COMPOSE = 343, - T_DOWN = 344, - T_START = 345, - T_STOP = 346, - T_STOPPED = 347, - T_KILL = 348, - T_INJECT = 349, - T_STATE = 350, - T_ASSIGNED_STATE = 351, - T_IN = 352, - T_GROUP = 353, - T_LBRACE = 354, - T_RBRACE = 355, - T_COMMA = 356, - T_POSTGRES = 357, - T_STAYS = 358, - T_WHILE = 359, - T_THROUGH = 360, - T_SET = 361, - T_LOGS = 362, - T_NOT = 363, - T_CONTAINS = 364, - T_MATCHES = 365, - T_INTEGER = 366, - T_IDENT = 367, - T_STRING = 368, - T_BLOCK = 369, - T_SHELL_ARGS = 370 + T_NODEINI = 301, + T_FS_INIT = 302, + T_FS_SINGLE = 303, + T_FS_PRIMARY = 304, + T_FS_WAIT_PRIMARY = 305, + T_FS_WAIT_STANDBY = 306, + T_FS_DEMOTED = 307, + T_FS_DEMOTE_TIMEOUT = 308, + T_FS_DRAINING = 309, + T_FS_SECONDARY = 310, + T_FS_CATCHINGUP = 311, + T_FS_PREP_PROMOTION = 312, + T_FS_STOP_REPLICATION = 313, + T_FS_MAINTENANCE = 314, + T_FS_JOIN_PRIMARY = 315, + T_FS_APPLY_SETTINGS = 316, + T_FS_PREPARE_MAINTENANCE = 317, + T_FS_WAIT_MAINTENANCE = 318, + T_FS_REPORT_LSN = 319, + T_FS_FAST_FORWARD = 320, + T_FS_JOIN_SECONDARY = 321, + T_FS_DROPPED = 322, + T_EXEC = 323, + T_EXEC_FAILS = 324, + T_RUN = 325, + T_PG_AUTOCTL = 326, + T_WAIT = 327, + T_UNTIL = 328, + T_TIMEOUT = 329, + T_AND = 330, + T_IS = 331, + T_WITH = 332, + T_ASSERT = 333, + T_SQL = 334, + T_EXPECT = 335, + T_ERROR = 336, + T_PROMOTE = 337, + T_PERFORM = 338, + T_FAILOVER = 339, + T_NETWORK = 340, + T_DISCONNECT = 341, + T_CONNECT = 342, + T_SLEEP = 343, + T_COMPOSE = 344, + T_DOWN = 345, + T_START = 346, + T_STOP = 347, + T_STOPPED = 348, + T_KILL = 349, + T_INJECT = 350, + T_STATE = 351, + T_ASSIGNED_STATE = 352, + T_IN = 353, + T_GROUP = 354, + T_LBRACE = 355, + T_RBRACE = 356, + T_COMMA = 357, + T_POSTGRES = 358, + T_STAYS = 359, + T_WHILE = 360, + T_THROUGH = 361, + T_SET = 362, + T_GET = 363, + T_LOGS = 364, + T_NOT = 365, + T_CONTAINS = 366, + T_MATCHES = 367, + T_INTEGER = 368, + T_IDENT = 369, + T_STRING = 370, + T_BLOCK = 371, + T_SHELL_ARGS = 372 }; #endif /* Tokens. */ @@ -198,76 +200,78 @@ #define T_BIND_SOURCE 298 #define T_LEGACY_STARTUP 299 #define T_REGION 300 -#define T_FS_INIT 301 -#define T_FS_SINGLE 302 -#define T_FS_PRIMARY 303 -#define T_FS_WAIT_PRIMARY 304 -#define T_FS_WAIT_STANDBY 305 -#define T_FS_DEMOTED 306 -#define T_FS_DEMOTE_TIMEOUT 307 -#define T_FS_DRAINING 308 -#define T_FS_SECONDARY 309 -#define T_FS_CATCHINGUP 310 -#define T_FS_PREP_PROMOTION 311 -#define T_FS_STOP_REPLICATION 312 -#define T_FS_MAINTENANCE 313 -#define T_FS_JOIN_PRIMARY 314 -#define T_FS_APPLY_SETTINGS 315 -#define T_FS_PREPARE_MAINTENANCE 316 -#define T_FS_WAIT_MAINTENANCE 317 -#define T_FS_REPORT_LSN 318 -#define T_FS_FAST_FORWARD 319 -#define T_FS_JOIN_SECONDARY 320 -#define T_FS_DROPPED 321 -#define T_EXEC 322 -#define T_EXEC_FAILS 323 -#define T_RUN 324 -#define T_PG_AUTOCTL 325 -#define T_WAIT 326 -#define T_UNTIL 327 -#define T_TIMEOUT 328 -#define T_AND 329 -#define T_IS 330 -#define T_WITH 331 -#define T_ASSERT 332 -#define T_SQL 333 -#define T_EXPECT 334 -#define T_ERROR 335 -#define T_PROMOTE 336 -#define T_PERFORM 337 -#define T_FAILOVER 338 -#define T_NETWORK 339 -#define T_DISCONNECT 340 -#define T_CONNECT 341 -#define T_SLEEP 342 -#define T_COMPOSE 343 -#define T_DOWN 344 -#define T_START 345 -#define T_STOP 346 -#define T_STOPPED 347 -#define T_KILL 348 -#define T_INJECT 349 -#define T_STATE 350 -#define T_ASSIGNED_STATE 351 -#define T_IN 352 -#define T_GROUP 353 -#define T_LBRACE 354 -#define T_RBRACE 355 -#define T_COMMA 356 -#define T_POSTGRES 357 -#define T_STAYS 358 -#define T_WHILE 359 -#define T_THROUGH 360 -#define T_SET 361 -#define T_LOGS 362 -#define T_NOT 363 -#define T_CONTAINS 364 -#define T_MATCHES 365 -#define T_INTEGER 366 -#define T_IDENT 367 -#define T_STRING 368 -#define T_BLOCK 369 -#define T_SHELL_ARGS 370 +#define T_NODEINI 301 +#define T_FS_INIT 302 +#define T_FS_SINGLE 303 +#define T_FS_PRIMARY 304 +#define T_FS_WAIT_PRIMARY 305 +#define T_FS_WAIT_STANDBY 306 +#define T_FS_DEMOTED 307 +#define T_FS_DEMOTE_TIMEOUT 308 +#define T_FS_DRAINING 309 +#define T_FS_SECONDARY 310 +#define T_FS_CATCHINGUP 311 +#define T_FS_PREP_PROMOTION 312 +#define T_FS_STOP_REPLICATION 313 +#define T_FS_MAINTENANCE 314 +#define T_FS_JOIN_PRIMARY 315 +#define T_FS_APPLY_SETTINGS 316 +#define T_FS_PREPARE_MAINTENANCE 317 +#define T_FS_WAIT_MAINTENANCE 318 +#define T_FS_REPORT_LSN 319 +#define T_FS_FAST_FORWARD 320 +#define T_FS_JOIN_SECONDARY 321 +#define T_FS_DROPPED 322 +#define T_EXEC 323 +#define T_EXEC_FAILS 324 +#define T_RUN 325 +#define T_PG_AUTOCTL 326 +#define T_WAIT 327 +#define T_UNTIL 328 +#define T_TIMEOUT 329 +#define T_AND 330 +#define T_IS 331 +#define T_WITH 332 +#define T_ASSERT 333 +#define T_SQL 334 +#define T_EXPECT 335 +#define T_ERROR 336 +#define T_PROMOTE 337 +#define T_PERFORM 338 +#define T_FAILOVER 339 +#define T_NETWORK 340 +#define T_DISCONNECT 341 +#define T_CONNECT 342 +#define T_SLEEP 343 +#define T_COMPOSE 344 +#define T_DOWN 345 +#define T_START 346 +#define T_STOP 347 +#define T_STOPPED 348 +#define T_KILL 349 +#define T_INJECT 350 +#define T_STATE 351 +#define T_ASSIGNED_STATE 352 +#define T_IN 353 +#define T_GROUP 354 +#define T_LBRACE 355 +#define T_RBRACE 356 +#define T_COMMA 357 +#define T_POSTGRES 358 +#define T_STAYS 359 +#define T_WHILE 360 +#define T_THROUGH 361 +#define T_SET 362 +#define T_GET 363 +#define T_LOGS 364 +#define T_NOT 365 +#define T_CONTAINS 366 +#define T_MATCHES 367 +#define T_INTEGER 368 +#define T_IDENT 369 +#define T_STRING 370 +#define T_BLOCK 371 +#define T_SHELL_ARGS 372 @@ -282,7 +286,7 @@ typedef union YYSTYPE TestCmd *cmd; } /* Line 1529 of yacc.c. */ -#line 286 "test_spec_parse.h" +#line 290 "test_spec_parse.h" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/src/bin/pgaftest/test_spec_parse.y b/src/bin/pgaftest/test_spec_parse.y index 325b8fe88..5956f4813 100644 --- a/src/bin/pgaftest/test_spec_parse.y +++ b/src/bin/pgaftest/test_spec_parse.y @@ -161,6 +161,7 @@ static TestNode *current_node = NULL; %token T_LISTEN T_CITUS_SECONDARY T_CANDIDATE_PRIORITY T_PORT T_PASSWORD T_MONITOR_PASSWORD %token T_CITUS_CLUSTER_NAME T_DEBIAN_CLUSTER T_REPLICATION_QUORUM T_REPLICATION_PASSWORD %token T_EXTENSION_VERSION T_BIND_SOURCE T_LEGACY_STARTUP T_REGION +%token T_NODEINI /* ---- FSM state tokens (used in CLUSTER_BODY and STEP_BODY) ---- */ %token T_FS_INIT T_FS_SINGLE T_FS_PRIMARY @@ -186,7 +187,7 @@ static TestNode *current_node = NULL; %token T_STATE T_ASSIGNED_STATE %token T_IN T_GROUP %token T_LBRACE T_RBRACE T_COMMA -%token T_POSTGRES T_STAYS T_WHILE T_THROUGH T_SET +%token T_POSTGRES T_STAYS T_WHILE T_THROUGH T_SET T_GET %token T_LOGS T_NOT T_CONTAINS T_MATCHES /* ---- Tokens with values ---- */ @@ -203,6 +204,7 @@ static TestNode *current_node = NULL; %type exec_cmd wait_cmd assert_cmd sql_cmd expect_cmd %type promote_cmd network_cmd sleep_cmd compose_cmd %type postgres_ctl_cmd stays_while_cmd set_monitor_cmd logs_cmd perform_cmd +%type nodeini_cmd %type opt_timeout %type while_body @@ -735,6 +737,7 @@ step_cmd: | stays_while_cmd { $$ = $1; } | set_monitor_cmd { $$ = $1; } | logs_cmd { $$ = $1; } + | nodeini_cmd { $$ = $1; } ; /* ----------------------------------------------------------------------- @@ -1244,6 +1247,37 @@ network_cmd: } ; +/* ----------------------------------------------------------------------- + * nodeini set + * nodeini get + * + * Edits or reads 's pg_autoctl_node.ini [settings] entry directly on + * the host side (the file is bind-mounted read-only inside the node's own + * container, so this can't go through exec/compose). "set" exercises the + * supervisor's automatic file-watch apply path, distinct from calling + * `pg_autoctl set node ...` directly; "get" asserts the on-disk value, + * distinct from `pg_autoctl get node ...` which queries the running node. + * ----------------------------------------------------------------------- */ + +nodeini_cmd: + T_NODEINI T_SET T_IDENT T_IDENT T_IDENT + { + $$ = make_cmd(CMD_NODEINI_SET); + strlcpy($$->service, $3, sizeof($$->service)); + strlcpy($$->state, $4, sizeof($$->state)); + strlcpy($$->args, $5, sizeof($$->args)); + free($3); free($4); free($5); + } + | T_NODEINI T_GET T_IDENT T_IDENT T_IDENT + { + $$ = make_cmd(CMD_NODEINI_GET); + strlcpy($$->service, $3, sizeof($$->service)); + strlcpy($$->state, $4, sizeof($$->state)); + strlcpy($$->args, $5, sizeof($$->args)); + free($3); free($4); free($5); + } + ; + /* ----------------------------------------------------------------------- * sleep Ns * ----------------------------------------------------------------------- */ diff --git a/src/bin/pgaftest/test_spec_scan.c b/src/bin/pgaftest/test_spec_scan.c index 4b30ba1f4..ab48f71a2 100644 --- a/src/bin/pgaftest/test_spec_scan.c +++ b/src/bin/pgaftest/test_spec_scan.c @@ -356,8 +356,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 157 -#define YY_END_OF_BUFFER 158 +#define YY_NUM_RULES 159 +#define YY_END_OF_BUFFER 160 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -365,143 +365,144 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[1229] = +static const flex_int16_t yy_accept[1236] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 158, 18, 17, 16, 18, 1, 12, 11, 13, 13, - 13, 13, 13, 13, 15, 157, 21, 20, 157, 19, + 160, 18, 17, 16, 18, 1, 12, 11, 13, 13, + 13, 13, 13, 13, 15, 159, 21, 20, 159, 19, 61, 60, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 63, 64, 101, 100, 157, 99, 135, 147, 134, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 149, - 150, 153, 152, 154, 155, 156, 17, 0, 14, 1, + 98, 63, 64, 101, 100, 159, 99, 136, 149, 135, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 151, + 152, 155, 154, 156, 157, 158, 17, 0, 14, 1, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 21, 0, 62, 19, 61, 61, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 101, 0, 148, 99, 147, 147, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 126, 132, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 153, 152, 155, 13, 13, 13, 13, 13, 13, - - 13, 13, 43, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 101, 0, 150, 99, 149, 149, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 127, 133, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 155, 154, 157, 13, 13, 13, 13, 13, + + 13, 13, 13, 43, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 25, 98, 98, 98, 98, 98, 131, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 144, 151, 151, 151, 151, - 151, 151, 151, 151, 104, 151, 141, 151, 151, 110, - 151, 151, 151, 151, 151, 151, 151, 151, 13, 13, - - 13, 4, 13, 13, 9, 13, 98, 98, 27, 98, + 98, 98, 98, 25, 98, 98, 98, 98, 98, 132, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 143, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 146, 153, + 153, 153, 153, 153, 153, 153, 153, 104, 153, 142, + 153, 153, 110, 153, 153, 153, 153, 153, 153, 153, + + 153, 13, 13, 13, 4, 13, 13, 9, 13, 98, + 98, 27, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 65, 98, 98, - 98, 98, 98, 98, 98, 30, 98, 98, 52, 98, - 98, 98, 98, 98, 98, 98, 98, 42, 98, 98, - 98, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 121, 151, 151, 151, 103, 151, 151, 151, 151, - 151, 65, 151, 151, 125, 143, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 123, 151, 151, 151, 106, 151, 133, - - 13, 13, 13, 13, 7, 13, 98, 33, 98, 98, + 65, 98, 98, 98, 98, 98, 98, 98, 30, 98, + 98, 52, 98, 98, 98, 98, 98, 98, 98, 98, + 42, 98, 98, 98, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 122, 153, 153, 153, 103, 153, + 153, 153, 153, 153, 65, 153, 153, 126, 145, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 124, 153, 153, + + 153, 106, 153, 134, 13, 13, 13, 13, 7, 13, + 98, 33, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 41, 98, 98, 98, 51, + 24, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 41, 98, 98, 98, 51, 24, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 112, 151, 151, 151, 151, - 151, 151, 130, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 119, - 122, 127, 137, 151, 151, 151, 151, 151, 107, 151, - - 151, 138, 13, 13, 13, 13, 13, 98, 98, 98, - 98, 98, 98, 98, 98, 38, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 37, 98, 47, 98, 98, 98, 98, 98, - 98, 98, 50, 98, 98, 98, 66, 98, 98, 98, - 46, 98, 98, 98, 98, 98, 98, 32, 151, 151, - 109, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 111, 151, 151, 151, 151, 142, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 66, 151, 151, 151, 151, 151, - - 151, 151, 151, 151, 151, 151, 13, 13, 2, 3, + 98, 98, 98, 98, 98, 98, 98, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 112, + 153, 153, 153, 153, 153, 153, 131, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 119, 123, 128, 138, 153, 153, + + 153, 153, 153, 107, 153, 153, 139, 13, 13, 13, 13, 13, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 72, 98, 97, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 22, 98, 98, 98, 98, 67, 98, 98, 98, - 98, 98, 98, 45, 98, 98, 98, 98, 98, 98, - 151, 151, 151, 151, 151, 120, 118, 151, 151, 151, - 72, 151, 151, 97, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 146, 116, 151, 114, 151, 151, - 151, 67, 113, 151, 151, 151, 151, 151, 124, 140, - - 108, 151, 151, 151, 151, 151, 151, 13, 13, 10, - 8, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 39, 98, 98, 75, 98, 98, 98, 98, 98, + 38, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 37, 98, 47, + 98, 98, 98, 98, 98, 98, 98, 50, 98, 98, + 98, 66, 98, 98, 98, 46, 98, 98, 98, 98, + 98, 98, 32, 153, 153, 109, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 111, 153, 153, + 153, 153, 144, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + + 66, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 13, 13, 2, 3, 13, 13, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 29, 35, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 151, 151, 151, 151, - 151, 145, 151, 151, 151, 75, 151, 115, 151, 151, - 151, 151, 151, 151, 151, 151, 0, 151, 136, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 13, 13, 98, 98, 98, 98, 98, 98, - - 98, 98, 98, 98, 98, 98, 98, 98, 98, 28, - 98, 40, 44, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 76, 98, - 98, 98, 98, 98, 98, 98, 98, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 28, 151, - 151, 151, 151, 151, 0, 151, 151, 151, 151, 151, - 151, 151, 76, 151, 151, 151, 151, 151, 151, 151, - 151, 13, 13, 98, 98, 98, 98, 98, 77, 98, + 98, 72, 98, 97, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 22, 98, 98, + 98, 98, 67, 98, 98, 98, 98, 98, 98, 45, + 98, 98, 98, 98, 98, 98, 153, 153, 153, 153, + 153, 120, 118, 153, 153, 153, 72, 153, 153, 97, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 148, 116, 121, 153, 114, 153, 153, 153, 67, 113, + + 153, 153, 153, 153, 153, 125, 141, 108, 153, 153, + 153, 153, 153, 153, 13, 13, 10, 8, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 39, 98, + 98, 75, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 29, 35, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 34, 98, 98, 98, - - 98, 98, 92, 91, 98, 98, 98, 98, 98, 98, - 98, 98, 151, 151, 151, 151, 77, 151, 151, 117, - 102, 151, 151, 151, 151, 151, 151, 151, 0, 105, - 151, 151, 151, 151, 92, 91, 151, 151, 151, 151, - 151, 151, 151, 151, 13, 13, 98, 98, 26, 58, - 98, 98, 98, 31, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 82, 98, 98, 98, + 98, 98, 98, 153, 153, 153, 153, 153, 147, 153, + 153, 153, 75, 153, 115, 153, 153, 153, 153, 153, + 153, 153, 153, 0, 153, 137, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 13, + + 13, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 28, 98, 40, 44, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 82, 0, 151, 151, 151, 151, 151, - - 151, 151, 151, 151, 151, 151, 151, 13, 6, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 94, 93, - 23, 84, 98, 83, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 69, 71, 98, 68, 70, - 151, 151, 151, 151, 151, 151, 94, 93, 84, 151, - 83, 151, 0, 151, 151, 151, 151, 151, 151, 151, - 69, 71, 151, 68, 70, 13, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 76, 98, 98, 98, 98, + 98, 98, 98, 98, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 28, 153, 153, 153, 153, + 153, 0, 153, 153, 153, 153, 153, 153, 153, 76, + 153, 153, 153, 153, 153, 153, 153, 153, 13, 13, + 98, 98, 98, 98, 98, 77, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 151, - 151, 151, 151, 151, 151, 151, 151, 0, 151, 151, - 151, 151, 151, 151, 151, 151, 13, 86, 85, 98, - 98, 98, 54, 74, 73, 98, 96, 95, 59, 98, + 98, 98, 98, 34, 98, 98, 98, 98, 98, 92, + 91, 98, 98, 98, 98, 98, 98, 98, 98, 153, + 153, 153, 153, 77, 153, 153, 117, 102, 153, 153, + 153, 153, 153, 153, 153, 0, 105, 153, 153, 153, + 153, 92, 91, 153, 153, 153, 153, 153, 153, 153, + 153, 13, 13, 98, 98, 26, 58, 98, 98, 98, + 31, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 82, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + + 82, 0, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 13, 6, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 94, 93, 23, 84, 98, + 83, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 69, 71, 98, 68, 70, 153, 153, 153, + 153, 153, 153, 94, 93, 84, 153, 83, 153, 0, + 153, 153, 153, 153, 153, 153, 153, 69, 71, 153, + 68, 70, 13, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 86, 85, 128, 151, 74, 73, 96, 95, 0, 151, - 151, 151, 151, 151, 151, 151, 151, 13, 98, 98, - 48, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 151, 139, 151, 151, 151, 151, 151, - 151, 151, 151, 13, 98, 98, 98, 36, 98, 98, - 98, 98, 98, 98, 81, 80, 90, 89, 151, 151, - 151, 151, 151, 81, 80, 90, 89, 5, 98, 98, - - 57, 98, 79, 98, 78, 98, 98, 151, 151, 79, - 151, 78, 49, 53, 98, 98, 98, 55, 129, 151, - 151, 88, 87, 98, 88, 87, 56, 0 + 98, 98, 98, 98, 98, 98, 153, 153, 153, 153, + + 153, 153, 153, 153, 0, 153, 153, 153, 153, 153, + 153, 153, 153, 13, 86, 85, 98, 98, 98, 54, + 74, 73, 98, 96, 95, 59, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 86, 85, 129, + 153, 74, 73, 96, 95, 0, 153, 153, 153, 153, + 153, 153, 153, 153, 13, 98, 98, 48, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 153, 140, 153, 153, 153, 153, 153, 153, 153, 153, + 13, 98, 98, 98, 36, 98, 98, 98, 98, 98, + 98, 81, 80, 90, 89, 153, 153, 153, 153, 153, + + 81, 80, 90, 89, 5, 98, 98, 57, 98, 79, + 98, 78, 98, 98, 153, 153, 79, 153, 78, 49, + 53, 98, 98, 98, 55, 130, 153, 153, 88, 87, + 98, 88, 87, 56, 0 } ; static const YY_CHAR yy_ec[256] = @@ -544,289 +545,289 @@ static const YY_CHAR yy_meta[41] = 4, 4, 4, 4, 4, 4, 4, 4, 1, 1 } ; -static const flex_int16_t yy_base[1242] = +static const flex_int16_t yy_base[1249] = { 0, - 0, 0, 40, 0, 80, 0, 119, 121, 1321, 1320, - 1322, 1325, 123, 1325, 1316, 0, 117, 1325, 0, 106, - 1292, 1291, 112, 1300, 1325, 1325, 130, 1325, 1312, 0, - 124, 1325, 0, 108, 1294, 124, 123, 1278, 125, 1283, - 117, 1285, 143, 134, 130, 145, 1294, 145, 1280, 1282, - 146, 1325, 1325, 164, 1325, 1304, 0, 1325, 138, 1325, - 0, 152, 155, 164, 154, 161, 1277, 161, 1279, 1284, - 1277, 1290, 162, 180, 153, 179, 181, 1276, 185, 1325, - 1325, 0, 1300, 1325, 0, 1325, 211, 1296, 1325, 0, - 205, 1325, 0, 1267, 1265, 1271, 1280, 186, 1278, 1281, - - 216, 1289, 1325, 0, 212, 1325, 0, 1276, 1263, 1253, - 1257, 1262, 195, 1255, 1259, 1268, 208, 182, 1252, 200, - 1253, 1255, 212, 1260, 1259, 1246, 1259, 1246, 1255, 1249, - 222, 1249, 1242, 1242, 211, 211, 1256, 1244, 1245, 1241, - 1234, 1242, 1244, 1234, 239, 1259, 1325, 0, 233, 1325, - 0, 1246, 1233, 1229, 219, 209, 1234, 1227, 1222, 233, - 1226, 230, 228, 1225, 1227, 231, 0, 1232, 1228, 1232, - 229, 1218, 1217, 1217, 1217, 1234, 1214, 245, 1216, 1217, - 233, 1216, 1224, 1216, 241, 1209, 1213, 1205, 1215, 1214, - 1202, 0, 1232, 0, 1199, 1200, 1209, 1212, 1195, 1194, - - 1198, 1195, 0, 1200, 1197, 1202, 1205, 1204, 1204, 1185, - 1187, 1203, 1194, 1197, 1186, 1191, 1183, 1193, 1178, 1176, - 1182, 1173, 1186, 1187, 1171, 1176, 1175, 1187, 1167, 1172, - 1176, 1171, 1178, 1187, 1162, 1160, 1163, 1165, 1168, 243, - 1161, 1168, 0, 1158, 1168, 1151, 1151, 1159, 0, 1157, - 252, 1164, 1164, 1150, 231, 1150, 1161, 1149, 1153, 1145, - 1145, 1156, 1153, 1145, 1136, 1142, 1133, 1133, 1147, 1137, - 1138, 1130, 1134, 1144, 1123, 0, 1126, 1138, 1142, 1122, - 1125, 1127, 1126, 1123, 0, 1122, 0, 1129, 1130, 0, - 244, 1118, 1118, 1127, 1122, 1110, 1117, 1120, 1108, 1106, - - 1105, 0, 1119, 1107, 0, 1118, 1096, 1117, 1124, 1123, - 1108, 1108, 1096, 1110, 1093, 1111, 1093, 1090, 1095, 1092, - 1093, 1101, 268, 1104, 1088, 1098, 1098, 1092, 270, 1097, - 1096, 1093, 1077, 1076, 1080, 0, 1075, 1070, 0, 1091, - 1090, 1075, 1080, 1070, 1073, 1074, 271, 0, 1072, 272, - 1079, 1058, 1064, 1074, 1071, 1071, 1063, 1072, 1075, 1055, - 1059, 0, 1059, 1056, 1053, 1075, 1066, 1053, 278, 1066, - 1050, 0, 1062, 279, 0, 0, 1044, 1055, 1047, 1052, - 1045, 1038, 1051, 1056, 1055, 1040, 1036, 1039, 1040, 1035, - 1030, 1044, 1029, 280, 1026, 1031, 1033, 281, 1039, 0, - - 1048, 1037, 1026, 1026, 0, 1024, 282, 0, 1025, 1018, - 1032, 1026, 1039, 1024, 1027, 1017, 1012, 1024, 1019, 1022, - 1007, 0, 1019, 1018, 1003, 0, 1027, 1012, 1019, 267, - 269, 1011, 993, 1003, 1011, 1000, 1000, 988, 997, 993, - 992, 995, 1005, 987, 1002, 1000, 986, 985, 997, 996, - 276, 278, 982, 298, 979, 984, 993, 987, 976, 991, - 984, 987, 977, 981, 984, 0, 982, 967, 964, 979, - 978, 963, 0, 962, 283, 284, 976, 975, 961, 964, - 959, 956, 957, 956, 955, 952, 951, 966, 964, 0, - 0, 0, 0, 950, 949, 961, 958, 943, 0, 288, - - 292, 0, 287, 945, 944, 958, 937, 940, 939, 952, - 941, 954, 940, 240, 939, 0, 957, 946, 314, 936, - 945, 939, 932, 931, 936, 924, 942, 930, 923, 935, - 921, 933, 0, 942, 0, 922, 917, 925, 919, 914, - 926, 905, 0, 928, 317, 927, 0, 922, 921, 921, - 0, 923, 905, 902, 920, 902, 899, 0, 899, 898, - 0, 911, 914, 900, 908, 892, 897, 320, 896, 895, - 904, 906, 0, 901, 890, 889, 894, 0, 884, 896, - 882, 894, 884, 878, 885, 888, 881, 878, 887, 886, - 865, 884, 321, 887, 0, 882, 881, 881, 876, 863, - - 881, 863, 860, 878, 860, 857, 861, 860, 0, 0, - 869, 859, 867, 866, 850, 848, 848, 860, 854, 860, - 863, 860, 858, 841, 840, 0, 852, 0, 843, 839, - 838, 840, 853, 833, 840, 842, 847, 840, 845, 828, - 845, 850, 824, 840, 838, 327, 0, 821, 828, 827, - 820, 821, 820, 0, 826, 825, 832, 823, 822, 829, - 824, 823, 823, 806, 818, 0, 0, 805, 803, 802, - 0, 816, 813, 0, 810, 800, 799, 798, 799, 801, - 806, 129, 156, 191, 0, 0, 339, 0, 241, 265, - 331, 0, 0, 294, 301, 301, 307, 309, 0, 0, - - 0, 323, 324, 333, 326, 327, 336, 323, 321, 0, - 0, 320, 321, 334, 325, 339, 324, 325, 344, 328, - 337, 0, 341, 342, 0, 338, 330, 331, 341, 338, - 352, 333, 346, 345, 348, 347, 343, 350, 349, 351, - 0, 0, 354, 355, 360, 353, 354, 349, 363, 364, - 363, 365, 365, 366, 368, 368, 363, 364, 390, 381, - 366, 0, 379, 380, 387, 0, 379, 0, 369, 370, - 380, 382, 381, 384, 383, 385, 411, 383, 0, 391, - 392, 387, 390, 385, 399, 400, 399, 401, 401, 402, - 404, 404, 401, 409, 401, 402, 408, 421, 430, 410, - - 408, 413, 414, 409, 419, 420, 439, 434, 435, 0, - 430, 0, 0, 437, 425, 439, 427, 441, 440, 443, - 427, 445, 429, 447, 431, 435, 437, 438, 0, 444, - 445, 435, 455, 453, 438, 458, 456, 441, 442, 444, - 469, 449, 453, 454, 448, 450, 469, 470, 0, 471, - 459, 473, 461, 473, 469, 466, 478, 462, 480, 464, - 469, 470, 0, 476, 477, 467, 487, 485, 470, 490, - 488, 489, 489, 486, 487, 493, 493, 483, 0, 480, - 487, 484, 484, 499, 500, 484, 489, 490, 504, 492, - 507, 494, 509, 496, 510, 497, 0, 508, 503, 510, - - 505, 507, 0, 0, 519, 520, 519, 507, 524, 522, - 510, 527, 521, 522, 512, 517, 0, 529, 530, 0, - 0, 518, 519, 520, 535, 522, 537, 537, 525, 0, - 535, 530, 537, 532, 0, 0, 545, 546, 545, 533, - 550, 548, 536, 553, 547, 539, 544, 545, 0, 0, - 542, 556, 558, 0, 543, 549, 550, 561, 563, 564, - 549, 545, 570, 547, 572, 554, 0, 556, 562, 564, - 564, 566, 585, 580, 581, 569, 559, 560, 572, 562, - 563, 575, 576, 590, 574, 578, 579, 591, 592, 572, - 597, 574, 599, 0, 586, 588, 590, 590, 592, 605, - - 606, 594, 584, 585, 597, 587, 588, 600, 0, 608, - 609, 608, 600, 618, 615, 600, 601, 605, 0, 0, - 0, 0, 606, 0, 607, 605, 604, 608, 614, 610, - 616, 616, 614, 615, 635, 0, 0, 636, 0, 0, - 631, 632, 620, 632, 621, 622, 0, 0, 0, 626, - 0, 627, 625, 627, 633, 629, 635, 631, 632, 652, - 0, 0, 653, 0, 0, 654, 637, 638, 643, 664, - 642, 643, 642, 643, 645, 640, 641, 651, 653, 664, - 650, 666, 652, 672, 653, 666, 667, 663, 664, 660, - 661, 676, 667, 663, 664, 660, 661, 680, 683, 669, - - 685, 671, 683, 684, 680, 681, 676, 0, 0, 679, - 684, 674, 0, 0, 0, 691, 0, 0, 0, 683, - 688, 694, 690, 696, 687, 692, 693, 694, 707, 708, - 0, 0, 0, 694, 0, 0, 0, 0, 705, 700, - 706, 702, 708, 703, 704, 717, 718, 707, 714, 723, - 0, 710, 722, 726, 713, 728, 715, 712, 714, 719, - 720, 730, 731, 728, 1325, 737, 724, 739, 726, 728, - 729, 739, 740, 728, 727, 735, 735, 0, 736, 737, - 738, 739, 731, 734, 0, 0, 0, 0, 736, 743, - 744, 745, 746, 0, 0, 0, 0, 0, 736, 757, - - 0, 760, 0, 761, 0, 750, 753, 742, 765, 0, - 766, 0, 0, 0, 765, 766, 754, 0, 0, 768, - 769, 0, 0, 771, 0, 0, 0, 1325, 788, 792, - 796, 800, 799, 804, 808, 807, 812, 816, 815, 820, - 824 + 0, 0, 40, 0, 80, 0, 119, 121, 1328, 1327, + 1329, 1332, 123, 1332, 1323, 0, 117, 1332, 0, 106, + 1299, 1298, 112, 1307, 1332, 1332, 130, 1332, 1319, 0, + 124, 1332, 0, 108, 1301, 124, 123, 1285, 125, 1290, + 117, 1292, 143, 134, 130, 145, 1301, 145, 1287, 1289, + 146, 1332, 1332, 164, 1332, 1311, 0, 1332, 138, 1332, + 0, 152, 155, 164, 154, 161, 162, 167, 1287, 1292, + 1285, 1298, 169, 182, 154, 186, 184, 1284, 193, 1332, + 1332, 0, 1308, 1332, 0, 1332, 199, 1304, 1332, 0, + 200, 1332, 0, 1275, 1273, 1279, 1288, 187, 1286, 1289, + + 219, 1297, 1332, 0, 213, 1332, 0, 1284, 1271, 1261, + 1265, 1270, 191, 1263, 1267, 1276, 211, 213, 1260, 203, + 1261, 1263, 217, 1268, 1267, 1254, 1267, 1254, 1263, 1257, + 221, 1257, 1250, 1250, 218, 213, 1264, 1252, 1253, 1249, + 1242, 1250, 1252, 1242, 242, 1267, 1332, 0, 238, 1332, + 0, 1254, 1241, 1237, 221, 225, 1242, 1235, 1230, 225, + 1234, 231, 233, 1233, 1230, 1234, 234, 0, 1239, 1235, + 1239, 236, 1225, 242, 1225, 1225, 1242, 1222, 244, 1224, + 1225, 245, 1224, 1232, 1224, 249, 1217, 1221, 1213, 1223, + 1222, 1210, 0, 1240, 0, 1207, 1208, 1217, 1220, 1203, + + 1202, 1206, 1203, 0, 1208, 1205, 1210, 1213, 1212, 1212, + 1193, 1195, 1211, 1202, 1205, 1194, 1199, 1191, 1201, 1186, + 1184, 1190, 1181, 1194, 1195, 1179, 1184, 1183, 1195, 1175, + 1180, 1184, 1179, 1186, 1195, 1170, 1168, 1171, 1173, 1176, + 239, 1169, 1176, 0, 1166, 1176, 1159, 1159, 1167, 0, + 1165, 258, 1172, 1172, 1158, 241, 1158, 1169, 1157, 1161, + 1153, 1153, 1164, 1161, 1153, 1144, 1150, 0, 1141, 1141, + 1155, 1145, 1146, 1138, 1142, 1152, 1131, 1148, 0, 1133, + 1145, 1149, 1129, 1132, 1134, 1133, 1130, 0, 1129, 0, + 1136, 1137, 0, 248, 1125, 1125, 1134, 1129, 1117, 1124, + + 1127, 1115, 1113, 1112, 0, 1126, 1114, 0, 1125, 1103, + 1124, 1131, 1130, 1115, 1115, 1103, 1117, 1100, 1118, 1100, + 1097, 1102, 1099, 1100, 1108, 274, 1111, 1095, 1105, 1105, + 1099, 275, 1104, 1103, 1100, 1084, 1083, 1087, 0, 1082, + 1077, 0, 1098, 1097, 1082, 1087, 1077, 1080, 1081, 276, + 0, 1079, 277, 1086, 1065, 1071, 1081, 1078, 1078, 1070, + 1079, 1082, 1062, 1066, 0, 1066, 1063, 1060, 1082, 1073, + 1060, 283, 1073, 1057, 0, 1069, 284, 0, 0, 1051, + 1062, 1054, 1059, 1058, 1051, 1044, 1057, 1062, 1061, 1046, + 1042, 1045, 1046, 1041, 1036, 1050, 1035, 285, 1032, 1037, + + 1039, 286, 1045, 0, 1054, 1043, 1032, 1032, 0, 1030, + 287, 0, 1031, 1024, 1038, 1032, 1045, 1030, 1033, 1023, + 1018, 1030, 1025, 1028, 1013, 0, 1025, 1024, 1009, 0, + 1033, 1018, 1025, 272, 274, 1017, 999, 1009, 1017, 1006, + 1006, 994, 1003, 999, 998, 1001, 1011, 993, 1008, 1006, + 992, 991, 1003, 1002, 281, 283, 988, 303, 985, 990, + 999, 993, 982, 997, 990, 993, 983, 987, 990, 0, + 988, 973, 970, 985, 984, 969, 0, 968, 288, 289, + 982, 981, 967, 970, 969, 964, 961, 962, 961, 960, + 957, 956, 971, 969, 0, 0, 0, 0, 955, 954, + + 966, 963, 948, 0, 293, 297, 0, 135, 950, 949, + 963, 942, 945, 944, 957, 946, 959, 945, 292, 944, + 0, 962, 951, 319, 941, 950, 944, 937, 936, 941, + 929, 947, 935, 928, 940, 926, 938, 0, 947, 0, + 927, 922, 930, 924, 919, 931, 910, 0, 933, 320, + 932, 0, 927, 926, 926, 0, 928, 910, 907, 925, + 907, 904, 0, 904, 903, 0, 916, 919, 905, 913, + 897, 902, 322, 901, 900, 909, 911, 0, 906, 895, + 894, 899, 0, 889, 901, 887, 899, 889, 883, 890, + 891, 892, 885, 882, 891, 890, 869, 888, 329, 891, + + 0, 886, 885, 885, 880, 867, 885, 867, 864, 882, + 864, 861, 865, 864, 0, 0, 873, 863, 871, 870, + 854, 852, 852, 864, 858, 864, 867, 864, 862, 845, + 844, 0, 856, 0, 847, 843, 842, 844, 857, 837, + 844, 846, 851, 844, 849, 832, 849, 854, 828, 844, + 842, 330, 0, 825, 832, 831, 824, 825, 824, 0, + 830, 829, 836, 827, 826, 833, 828, 827, 827, 810, + 822, 0, 0, 809, 807, 806, 0, 820, 817, 0, + 814, 803, 799, 798, 162, 176, 218, 249, 257, 288, + 0, 0, 0, 342, 0, 315, 302, 339, 0, 0, + + 315, 316, 317, 320, 321, 0, 0, 0, 329, 331, + 340, 333, 334, 343, 330, 328, 0, 0, 327, 328, + 341, 332, 346, 331, 332, 351, 335, 344, 0, 348, + 349, 0, 345, 337, 338, 348, 345, 359, 340, 353, + 352, 355, 354, 350, 357, 356, 358, 0, 0, 361, + 362, 367, 360, 361, 356, 370, 371, 370, 372, 372, + 373, 375, 375, 370, 371, 397, 388, 373, 0, 386, + 387, 394, 0, 386, 0, 376, 377, 387, 389, 388, + 391, 390, 392, 418, 390, 0, 398, 399, 394, 397, + 392, 406, 407, 406, 408, 408, 409, 411, 411, 408, + + 416, 408, 409, 415, 428, 437, 417, 415, 420, 421, + 416, 426, 427, 446, 441, 442, 0, 437, 0, 0, + 444, 432, 446, 434, 448, 447, 450, 434, 452, 436, + 454, 438, 442, 444, 445, 0, 451, 452, 442, 462, + 460, 445, 465, 463, 448, 449, 451, 476, 456, 460, + 461, 455, 457, 476, 477, 0, 478, 466, 480, 468, + 480, 476, 473, 485, 469, 487, 471, 476, 477, 0, + 483, 484, 474, 494, 492, 477, 497, 495, 496, 496, + 493, 494, 500, 500, 490, 0, 487, 494, 491, 491, + 506, 507, 491, 496, 497, 511, 499, 514, 501, 516, + + 503, 517, 504, 0, 515, 510, 517, 512, 514, 0, + 0, 526, 527, 526, 514, 531, 529, 517, 534, 528, + 529, 519, 524, 0, 536, 537, 0, 0, 525, 526, + 527, 542, 529, 544, 544, 532, 0, 542, 537, 544, + 539, 0, 0, 552, 553, 552, 540, 557, 555, 543, + 560, 554, 546, 551, 552, 0, 0, 549, 563, 565, + 0, 550, 556, 557, 568, 570, 571, 556, 552, 577, + 554, 579, 561, 0, 563, 569, 571, 571, 573, 592, + 587, 588, 576, 566, 567, 579, 569, 570, 582, 583, + 597, 581, 585, 586, 598, 599, 579, 604, 581, 606, + + 0, 593, 595, 597, 597, 599, 612, 613, 601, 591, + 592, 604, 594, 595, 607, 0, 615, 616, 615, 607, + 625, 622, 607, 608, 612, 0, 0, 0, 0, 613, + 0, 614, 612, 611, 615, 621, 617, 623, 623, 621, + 622, 642, 0, 0, 643, 0, 0, 638, 639, 627, + 639, 628, 629, 0, 0, 0, 633, 0, 634, 632, + 634, 640, 636, 642, 638, 639, 659, 0, 0, 660, + 0, 0, 661, 644, 645, 650, 671, 649, 650, 649, + 650, 652, 647, 648, 658, 660, 671, 657, 673, 659, + 679, 660, 673, 674, 670, 671, 667, 668, 683, 674, + + 670, 671, 667, 668, 687, 690, 676, 692, 678, 690, + 691, 687, 688, 683, 0, 0, 686, 691, 681, 0, + 0, 0, 698, 0, 0, 0, 690, 695, 701, 697, + 703, 694, 699, 700, 701, 714, 715, 0, 0, 0, + 701, 0, 0, 0, 0, 712, 707, 713, 709, 715, + 710, 711, 724, 725, 714, 721, 730, 0, 717, 729, + 733, 720, 735, 722, 719, 721, 726, 727, 737, 738, + 735, 1332, 744, 731, 746, 733, 735, 736, 746, 747, + 735, 734, 742, 742, 0, 743, 744, 745, 746, 738, + 741, 0, 0, 0, 0, 743, 750, 751, 752, 753, + + 0, 0, 0, 0, 0, 743, 764, 0, 767, 0, + 768, 0, 757, 760, 749, 772, 0, 773, 0, 0, + 0, 772, 773, 761, 0, 0, 775, 776, 0, 0, + 778, 0, 0, 0, 1332, 795, 799, 803, 807, 806, + 811, 815, 814, 819, 823, 822, 827, 831 } ; -static const flex_int16_t yy_def[1242] = +static const flex_int16_t yy_def[1249] = { 0, - 1228, 1, 1228, 3, 1228, 5, 1229, 1229, 1230, 1230, - 1228, 1228, 1228, 1228, 1231, 1232, 1228, 1228, 1233, 1233, - 1233, 1233, 1233, 1233, 1228, 1228, 1228, 1228, 1234, 1235, - 1228, 1228, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1228, 1228, 1228, 1228, 1237, 1238, 1228, 1228, 1228, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1228, - 1228, 1240, 1228, 1228, 1241, 1228, 1228, 1231, 1228, 1232, - 1228, 1228, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, - - 1228, 1234, 1228, 1235, 1228, 1228, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1228, 1237, 1228, 1238, 1228, 1228, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1240, 1228, 1241, 1233, 1233, 1233, 1233, 1233, 1233, - - 1233, 1233, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1233, - - 1233, 1233, 1233, 1233, 1233, 1233, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - - 1233, 1233, 1233, 1233, 1233, 1233, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - - 1239, 1239, 1233, 1233, 1233, 1233, 1233, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - - 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1233, 1233, 1233, - 1233, 1233, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1233, 1233, - 1233, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1228, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1233, 1233, 1236, 1236, 1236, 1236, 1236, 1236, - - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1228, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1233, 1233, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1228, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1233, 1233, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1228, 1239, 1239, 1239, 1239, 1239, - - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1233, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1228, 1239, 1239, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1233, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1228, 1239, 1239, - - 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1228, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1239, 1228, 1239, 1239, 1239, 1239, 1239, - 1239, 1239, 1239, 1233, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, - 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1233, 1236, 1236, - - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, 1239, - 1239, 1239, 1236, 1236, 1236, 1236, 1236, 1236, 1239, 1239, - 1239, 1236, 1236, 1236, 1239, 1239, 1236, 0, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228 + 1235, 1, 1235, 3, 1235, 5, 1236, 1236, 1237, 1237, + 1235, 1235, 1235, 1235, 1238, 1239, 1235, 1235, 1240, 1240, + 1240, 1240, 1240, 1240, 1235, 1235, 1235, 1235, 1241, 1242, + 1235, 1235, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1235, 1235, 1235, 1235, 1244, 1245, 1235, 1235, 1235, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1235, + 1235, 1247, 1235, 1235, 1248, 1235, 1235, 1238, 1235, 1239, + 1235, 1235, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + + 1235, 1241, 1235, 1242, 1235, 1235, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1235, 1244, 1235, 1245, 1235, 1235, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1247, 1235, 1248, 1240, 1240, 1240, 1240, 1240, + + 1240, 1240, 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1240, 1240, 1240, 1240, 1240, 1240, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1240, 1240, 1240, + 1240, 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1240, 1240, 1240, 1240, 1240, 1240, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1240, 1240, 1240, 1240, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1235, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1240, + + 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1235, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1240, 1240, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1235, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1240, 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1235, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1240, 1240, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1235, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1235, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1240, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1235, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1240, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1246, 1235, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1240, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1240, 1243, 1243, 1243, 1243, 1243, + 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1246, 1246, 1243, + 1243, 1243, 1243, 1243, 1243, 1246, 1246, 1246, 1243, 1243, + 1243, 1246, 1246, 1243, 0, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235 } ; -static const flex_int16_t yy_nxt[1366] = +static const flex_int16_t yy_nxt[1373] = { 0, 12, 13, 14, 13, 15, 16, 12, 12, 17, 18, 19, 19, 19, 19, 19, 20, 19, 19, 19, 19, @@ -844,40 +845,40 @@ static const flex_int16_t yy_nxt[1366] = 83, 84, 83, 84, 87, 91, 87, 94, 92, 98, 95, 101, 105, 101, 108, 106, 109, 113, 120, 110, 117, 111, 123, 124, 99, 114, 149, 129, 92, 150, - 774, 115, 121, 118, 116, 106, 126, 131, 133, 143, + 613, 115, 121, 118, 116, 106, 126, 131, 133, 143, 127, 130, 137, 132, 128, 145, 138, 145, 155, 150, - 179, 775, 134, 144, 163, 135, 139, 140, 152, 172, - 153, 157, 156, 154, 161, 158, 180, 166, 164, 173, - 162, 159, 167, 174, 160, 216, 181, 175, 189, 176, - - 182, 186, 187, 183, 776, 190, 191, 177, 184, 217, - 178, 185, 87, 91, 87, 199, 92, 101, 200, 101, - 105, 208, 213, 106, 219, 223, 214, 209, 237, 232, - 239, 220, 238, 215, 254, 255, 92, 224, 233, 240, - 145, 149, 145, 106, 150, 252, 259, 262, 286, 264, - 273, 253, 268, 269, 291, 619, 778, 358, 263, 265, - 260, 274, 281, 359, 150, 287, 282, 343, 292, 353, - 344, 620, 283, 354, 391, 423, 392, 430, 447, 451, - 424, 393, 431, 448, 452, 470, 475, 494, 500, 508, - 471, 476, 495, 501, 509, 529, 779, 531, 530, 449, - - 532, 552, 607, 555, 553, 559, 556, 554, 496, 557, - 560, 579, 581, 601, 580, 582, 602, 604, 782, 603, - 605, 624, 608, 606, 649, 783, 625, 669, 694, 650, - 626, 784, 670, 695, 743, 785, 671, 786, 780, 744, - 777, 777, 777, 781, 787, 788, 789, 790, 791, 792, - 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, + 614, 180, 134, 144, 163, 135, 139, 140, 152, 165, + 153, 157, 156, 154, 161, 158, 173, 181, 164, 778, + 162, 159, 166, 167, 160, 175, 174, 779, 168, 176, + + 87, 177, 87, 182, 187, 188, 190, 183, 91, 178, + 184, 92, 179, 191, 192, 185, 200, 209, 186, 201, + 101, 105, 101, 210, 106, 214, 217, 220, 233, 215, + 224, 92, 240, 780, 221, 238, 216, 234, 260, 239, + 218, 241, 225, 145, 106, 145, 149, 253, 263, 150, + 255, 256, 261, 254, 265, 270, 271, 275, 278, 264, + 289, 284, 294, 346, 266, 285, 347, 361, 276, 150, + 781, 286, 782, 362, 279, 356, 295, 290, 395, 357, + 396, 427, 434, 451, 455, 397, 428, 435, 452, 456, + 474, 479, 499, 505, 513, 475, 480, 500, 506, 514, + + 534, 783, 536, 535, 453, 537, 557, 625, 560, 558, + 564, 561, 559, 501, 562, 565, 584, 586, 607, 585, + 587, 608, 610, 626, 609, 611, 630, 655, 612, 675, + 785, 631, 656, 786, 676, 632, 701, 750, 677, 789, + 790, 702, 751, 784, 784, 784, 787, 791, 792, 793, + 794, 788, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, - 824, 826, 823, 825, 827, 828, 829, 830, 831, 832, - 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, + 823, 824, 825, 826, 827, 828, 829, 831, 833, 830, + 832, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, - 853, 854, 777, 777, 777, 856, 857, 859, 861, 858, - 860, 862, 863, 864, 865, 866, 867, 868, 869, 870, + 853, 854, 855, 856, 857, 858, 859, 860, 861, 784, + 784, 784, 863, 864, 866, 868, 865, 867, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, - 881, 882, 883, 855, 884, 885, 886, 887, 888, 889, - 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, + 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, + 862, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, @@ -913,74 +914,75 @@ static const flex_int16_t yy_nxt[1366] = 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, - 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 82, 82, - 82, 82, 85, 85, 85, 85, 88, 88, 88, 88, - - 90, 90, 93, 90, 102, 102, 102, 102, 104, 104, - 107, 104, 146, 146, 146, 146, 148, 148, 151, 148, - 192, 773, 772, 192, 194, 194, 771, 194, 770, 769, - 768, 767, 766, 765, 764, 763, 762, 761, 760, 759, - 758, 757, 756, 755, 754, 753, 752, 751, 750, 749, - 748, 747, 746, 745, 742, 741, 740, 739, 738, 737, - 736, 735, 734, 733, 732, 731, 730, 729, 728, 727, - 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, - 716, 715, 714, 713, 712, 711, 710, 709, 708, 707, - 706, 705, 704, 703, 702, 701, 700, 699, 698, 697, - - 696, 693, 692, 691, 690, 689, 688, 687, 686, 685, - 684, 683, 682, 681, 680, 679, 678, 677, 676, 675, - 674, 673, 672, 668, 667, 666, 665, 664, 663, 662, - 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, - 651, 648, 647, 646, 645, 644, 643, 642, 641, 640, - 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, - 629, 628, 627, 623, 622, 621, 618, 617, 616, 615, - 614, 613, 612, 611, 610, 609, 600, 599, 598, 597, - 596, 595, 594, 593, 592, 591, 590, 589, 588, 587, - 586, 585, 584, 583, 578, 577, 576, 575, 574, 573, - - 572, 571, 570, 569, 568, 567, 566, 565, 564, 563, - 562, 561, 558, 551, 550, 549, 548, 547, 546, 545, - 544, 543, 542, 541, 540, 539, 538, 537, 536, 535, - 534, 533, 528, 527, 526, 525, 524, 523, 522, 521, - 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, - 510, 507, 506, 505, 504, 503, 502, 499, 498, 497, - 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, - 483, 482, 481, 480, 479, 478, 477, 474, 473, 472, - 469, 468, 467, 466, 465, 464, 463, 462, 461, 460, - 459, 458, 457, 456, 455, 454, 453, 450, 446, 445, - - 444, 443, 442, 441, 440, 439, 438, 437, 436, 435, - 434, 433, 432, 429, 428, 427, 426, 425, 422, 421, - 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, - 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, - 400, 399, 398, 397, 396, 395, 394, 390, 389, 388, - 387, 386, 385, 384, 383, 382, 381, 380, 379, 378, - 377, 376, 375, 374, 373, 372, 371, 370, 369, 368, - 367, 366, 365, 364, 363, 362, 361, 360, 357, 356, - 355, 352, 351, 350, 349, 348, 347, 346, 345, 342, - 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, - - 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, - 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, - 311, 310, 309, 308, 307, 306, 305, 304, 303, 302, - 301, 300, 299, 193, 298, 297, 296, 295, 294, 293, - 290, 289, 288, 285, 284, 280, 279, 278, 277, 276, - 275, 272, 271, 270, 267, 266, 261, 258, 257, 256, - 251, 250, 249, 147, 248, 247, 246, 245, 244, 243, - 242, 241, 236, 235, 234, 231, 230, 229, 228, 227, - 226, 225, 222, 221, 218, 212, 211, 210, 207, 206, - 205, 204, 203, 103, 202, 201, 198, 197, 196, 195, - - 89, 193, 188, 171, 170, 169, 168, 165, 147, 142, - 141, 136, 125, 122, 119, 112, 103, 100, 97, 96, - 89, 1228, 86, 86, 11, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228 + 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, + 1230, 1231, 1232, 1233, 1234, 82, 82, 82, 82, 85, + + 85, 85, 85, 88, 88, 88, 88, 90, 90, 93, + 90, 102, 102, 102, 102, 104, 104, 107, 104, 146, + 146, 146, 146, 148, 148, 151, 148, 193, 777, 776, + 193, 195, 195, 775, 195, 774, 773, 772, 771, 770, + 769, 768, 767, 766, 765, 764, 763, 762, 761, 760, + 759, 758, 757, 756, 755, 754, 753, 752, 749, 748, + 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, + 737, 736, 735, 734, 733, 732, 731, 730, 729, 728, + 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, + 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, + + 707, 706, 705, 704, 703, 700, 699, 698, 697, 696, + 695, 694, 693, 692, 691, 690, 689, 688, 687, 686, + 685, 684, 683, 682, 681, 680, 679, 678, 674, 673, + 672, 671, 670, 669, 668, 667, 666, 665, 664, 663, + 662, 661, 660, 659, 658, 657, 654, 653, 652, 651, + 650, 649, 648, 647, 646, 645, 644, 643, 642, 641, + 640, 639, 638, 637, 636, 635, 634, 633, 629, 628, + 627, 624, 623, 622, 621, 620, 619, 618, 617, 616, + 615, 606, 605, 604, 603, 602, 601, 600, 599, 598, + 597, 596, 595, 594, 593, 592, 591, 590, 589, 588, + + 583, 582, 581, 580, 579, 578, 577, 576, 575, 574, + 573, 572, 571, 570, 569, 568, 567, 566, 563, 556, + 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, + 545, 544, 543, 542, 541, 540, 539, 538, 533, 532, + 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, + 521, 520, 519, 518, 517, 516, 515, 512, 511, 510, + 509, 508, 507, 504, 503, 502, 498, 497, 496, 495, + 494, 493, 492, 491, 490, 489, 488, 487, 486, 485, + 484, 483, 482, 481, 478, 477, 476, 473, 472, 471, + 470, 469, 468, 467, 466, 465, 464, 463, 462, 461, + + 460, 459, 458, 457, 454, 450, 449, 448, 447, 446, + 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, + 433, 432, 431, 430, 429, 426, 425, 424, 423, 422, + 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, + 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, + 401, 400, 399, 398, 394, 393, 392, 391, 390, 389, + 388, 387, 386, 385, 384, 383, 382, 381, 380, 379, + 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, + 368, 367, 366, 365, 364, 363, 360, 359, 358, 355, + 354, 353, 352, 351, 350, 349, 348, 345, 344, 343, + + 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, + 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, + 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, + 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, + 302, 194, 301, 300, 299, 298, 297, 296, 293, 292, + 291, 288, 287, 283, 282, 281, 280, 277, 274, 273, + 272, 269, 268, 267, 262, 259, 258, 257, 252, 251, + 250, 147, 249, 248, 247, 246, 245, 244, 243, 242, + 237, 236, 235, 232, 231, 230, 229, 228, 227, 226, + 223, 222, 219, 213, 212, 211, 208, 207, 206, 205, + + 204, 103, 203, 202, 199, 198, 197, 196, 89, 194, + 189, 172, 171, 170, 169, 147, 142, 141, 136, 125, + 122, 119, 112, 103, 100, 97, 96, 89, 1235, 86, + 86, 11, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235 } ; -static const flex_int16_t yy_chk[1366] = +static const flex_int16_t yy_chk[1373] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -998,140 +1000,141 @@ static const flex_int16_t yy_chk[1366] = 7, 7, 8, 8, 13, 17, 13, 20, 17, 23, 20, 27, 31, 27, 34, 31, 34, 36, 39, 34, 37, 34, 41, 41, 23, 36, 59, 44, 17, 59, - 682, 36, 39, 37, 36, 31, 43, 45, 46, 51, + 508, 36, 39, 37, 36, 31, 43, 45, 46, 51, 43, 44, 48, 45, 43, 54, 48, 54, 63, 59, - 75, 683, 46, 51, 66, 46, 48, 48, 62, 73, - 62, 64, 63, 62, 65, 64, 75, 68, 66, 73, - 65, 64, 68, 74, 64, 118, 76, 74, 79, 74, - - 76, 77, 77, 76, 684, 79, 79, 74, 76, 118, - 74, 76, 87, 91, 87, 98, 91, 101, 98, 101, - 105, 113, 117, 105, 120, 123, 117, 113, 135, 131, - 136, 120, 135, 117, 156, 156, 91, 123, 131, 136, - 145, 149, 145, 105, 149, 155, 160, 162, 181, 163, - 171, 155, 166, 166, 185, 514, 689, 255, 162, 163, - 160, 171, 178, 255, 149, 181, 178, 240, 185, 251, - 240, 514, 178, 251, 291, 323, 291, 329, 347, 350, - 323, 291, 329, 347, 350, 369, 374, 394, 398, 407, - 369, 374, 394, 398, 407, 430, 690, 431, 430, 347, - - 431, 451, 503, 452, 451, 454, 452, 451, 394, 452, - 454, 475, 476, 500, 475, 476, 500, 501, 694, 500, - 501, 519, 503, 501, 545, 695, 519, 568, 593, 545, - 519, 696, 568, 593, 646, 697, 568, 698, 691, 646, - 687, 687, 687, 691, 702, 703, 704, 705, 706, 707, - 708, 709, 712, 713, 714, 715, 716, 717, 718, 719, - 720, 721, 723, 724, 726, 727, 728, 729, 730, 731, - 732, 733, 734, 735, 736, 737, 738, 739, 740, 743, - 744, 745, 743, 744, 746, 747, 748, 749, 750, 751, - 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, - - 763, 764, 765, 767, 769, 770, 771, 772, 773, 774, - 775, 776, 777, 777, 777, 778, 780, 781, 782, 780, - 781, 783, 784, 785, 786, 787, 788, 789, 790, 791, + 508, 75, 46, 51, 66, 46, 48, 48, 62, 67, + 62, 64, 63, 62, 65, 64, 73, 75, 66, 685, + 65, 64, 67, 68, 64, 74, 73, 686, 68, 74, + + 87, 74, 87, 76, 77, 77, 79, 76, 91, 74, + 76, 91, 74, 79, 79, 76, 98, 113, 76, 98, + 101, 105, 101, 113, 105, 117, 118, 120, 131, 117, + 123, 91, 136, 687, 120, 135, 117, 131, 160, 135, + 118, 136, 123, 145, 105, 145, 149, 155, 162, 149, + 156, 156, 160, 155, 163, 167, 167, 172, 174, 162, + 182, 179, 186, 241, 163, 179, 241, 256, 172, 149, + 688, 179, 689, 256, 174, 252, 186, 182, 294, 252, + 294, 326, 332, 350, 353, 294, 326, 332, 350, 353, + 372, 377, 398, 402, 411, 372, 377, 398, 402, 411, + + 434, 690, 435, 434, 350, 435, 455, 519, 456, 455, + 458, 456, 455, 398, 456, 458, 479, 480, 505, 479, + 480, 505, 506, 519, 505, 506, 524, 550, 506, 573, + 696, 524, 550, 697, 573, 524, 599, 652, 573, 701, + 702, 599, 652, 694, 694, 694, 698, 703, 704, 705, + 709, 698, 710, 711, 712, 713, 714, 715, 716, 719, + 720, 721, 722, 723, 724, 725, 726, 727, 728, 730, + 731, 733, 734, 735, 736, 737, 738, 739, 740, 741, + 742, 743, 744, 745, 746, 747, 750, 751, 752, 750, + 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, + + 762, 763, 764, 765, 766, 767, 768, 770, 771, 772, + 774, 776, 777, 778, 779, 780, 781, 782, 783, 784, + 784, 784, 785, 787, 788, 789, 787, 788, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, - 802, 803, 804, 777, 805, 806, 807, 808, 809, 811, - 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, - 824, 825, 826, 827, 828, 830, 831, 832, 833, 834, - 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, - 845, 846, 847, 848, 850, 851, 852, 853, 854, 855, - 856, 857, 858, 859, 860, 861, 862, 864, 865, 866, - - 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, - 877, 878, 880, 881, 882, 883, 884, 885, 886, 887, - 888, 889, 890, 891, 892, 893, 894, 895, 896, 898, - 899, 900, 901, 902, 905, 906, 907, 908, 909, 910, - 911, 912, 913, 914, 915, 916, 918, 919, 922, 923, - 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, - 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, - 947, 948, 951, 952, 953, 955, 956, 957, 958, 959, - 960, 961, 962, 963, 964, 965, 966, 968, 969, 970, - 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, + 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, + 784, 812, 813, 814, 815, 816, 818, 821, 822, 823, + 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, + 834, 835, 837, 838, 839, 840, 841, 842, 843, 844, + 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, + 855, 857, 858, 859, 860, 861, 862, 863, 864, 865, + + 866, 867, 868, 869, 871, 872, 873, 874, 875, 876, + 877, 878, 879, 880, 881, 882, 883, 884, 885, 887, + 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, + 898, 899, 900, 901, 902, 903, 905, 906, 907, 908, + 909, 912, 913, 914, 915, 916, 917, 918, 919, 920, + 921, 922, 923, 925, 926, 929, 930, 931, 932, 933, + 934, 935, 936, 938, 939, 940, 941, 944, 945, 946, + 947, 948, 949, 950, 951, 952, 953, 954, 955, 958, + 959, 960, 962, 963, 964, 965, 966, 967, 968, 969, + 970, 971, 972, 973, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, - 991, 992, 993, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1010, 1011, 1012, - 1013, 1014, 1015, 1016, 1017, 1018, 1023, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1032, 1033, 1034, 1035, 1038, - 1041, 1042, 1043, 1044, 1045, 1046, 1050, 1052, 1053, 1054, - 1055, 1056, 1057, 1058, 1059, 1060, 1063, 1066, 1067, 1068, - 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, + 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, + 1012, 1013, 1014, 1015, 1017, 1018, 1019, 1020, 1021, 1022, + 1023, 1024, 1025, 1030, 1032, 1033, 1034, 1035, 1036, 1037, + 1038, 1039, 1039, 1040, 1041, 1042, 1045, 1048, 1049, 1050, + 1051, 1052, 1053, 1057, 1059, 1060, 1061, 1062, 1063, 1064, + 1065, 1066, 1067, 1070, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, - 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1110, - 1111, 1112, 1116, 1120, 1121, 1122, 1123, 1124, 1125, 1126, - 1127, 1128, 1129, 1130, 1134, 1139, 1140, 1141, 1142, 1143, - 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1152, 1153, 1154, - 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, - 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, - 1176, 1177, 1179, 1180, 1181, 1182, 1183, 1184, 1189, 1190, - 1191, 1192, 1193, 1199, 1200, 1202, 1204, 1206, 1207, 1208, - 1209, 1211, 1215, 1216, 1217, 1220, 1221, 1224, 1229, 1229, - 1229, 1229, 1230, 1230, 1230, 1230, 1231, 1231, 1231, 1231, - - 1232, 1232, 1233, 1232, 1234, 1234, 1234, 1234, 1235, 1235, - 1236, 1235, 1237, 1237, 1237, 1237, 1238, 1238, 1239, 1238, - 1240, 681, 680, 1240, 1241, 1241, 679, 1241, 678, 677, - 676, 675, 673, 672, 670, 669, 668, 665, 664, 663, - 662, 661, 660, 659, 658, 657, 656, 655, 653, 652, - 651, 650, 649, 648, 645, 644, 643, 642, 641, 640, - 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, - 629, 627, 625, 624, 623, 622, 621, 620, 619, 618, - 617, 616, 615, 614, 613, 612, 611, 608, 607, 606, - 605, 604, 603, 602, 601, 600, 599, 598, 597, 596, - - 594, 592, 591, 590, 589, 588, 587, 586, 585, 584, - 583, 582, 581, 580, 579, 577, 576, 575, 574, 572, - 571, 570, 569, 567, 566, 565, 564, 563, 562, 560, - 559, 557, 556, 555, 554, 553, 552, 550, 549, 548, - 546, 544, 542, 541, 540, 539, 538, 537, 536, 534, - 532, 531, 530, 529, 528, 527, 526, 525, 524, 523, - 522, 521, 520, 518, 517, 515, 513, 512, 511, 510, - 509, 508, 507, 506, 505, 504, 498, 497, 496, 495, - 494, 489, 488, 487, 486, 485, 484, 483, 482, 481, - 480, 479, 478, 477, 474, 472, 471, 470, 469, 468, - - 467, 465, 464, 463, 462, 461, 460, 459, 458, 457, - 456, 455, 453, 450, 449, 448, 447, 446, 445, 444, - 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, - 433, 432, 429, 428, 427, 425, 424, 423, 421, 420, - 419, 418, 417, 416, 415, 414, 413, 412, 411, 410, - 409, 406, 404, 403, 402, 401, 399, 397, 396, 395, + 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, + 1109, 1110, 1111, 1112, 1113, 1114, 1117, 1118, 1119, 1123, + 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, + 1137, 1141, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, + 1154, 1155, 1156, 1157, 1159, 1160, 1161, 1162, 1163, 1164, + 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1173, 1174, 1175, + 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1186, + 1187, 1188, 1189, 1190, 1191, 1196, 1197, 1198, 1199, 1200, + 1206, 1207, 1209, 1211, 1213, 1214, 1215, 1216, 1218, 1222, + 1223, 1224, 1227, 1228, 1231, 1236, 1236, 1236, 1236, 1237, + + 1237, 1237, 1237, 1238, 1238, 1238, 1238, 1239, 1239, 1240, + 1239, 1241, 1241, 1241, 1241, 1242, 1242, 1243, 1242, 1244, + 1244, 1244, 1244, 1245, 1245, 1246, 1245, 1247, 684, 683, + 1247, 1248, 1248, 682, 1248, 681, 679, 678, 676, 675, + 674, 671, 670, 669, 668, 667, 666, 665, 664, 663, + 662, 661, 659, 658, 657, 656, 655, 654, 651, 650, + 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, + 639, 638, 637, 636, 635, 633, 631, 630, 629, 628, + 627, 626, 625, 624, 623, 622, 621, 620, 619, 618, + 617, 614, 613, 612, 611, 610, 609, 608, 607, 606, + + 605, 604, 603, 602, 600, 598, 597, 596, 595, 594, + 593, 592, 591, 590, 589, 588, 587, 586, 585, 584, + 582, 581, 580, 579, 577, 576, 575, 574, 572, 571, + 570, 569, 568, 567, 565, 564, 562, 561, 560, 559, + 558, 557, 555, 554, 553, 551, 549, 547, 546, 545, + 544, 543, 542, 541, 539, 537, 536, 535, 534, 533, + 532, 531, 530, 529, 528, 527, 526, 525, 523, 522, + 520, 518, 517, 516, 515, 514, 513, 512, 511, 510, + 509, 503, 502, 501, 500, 499, 494, 493, 492, 491, + 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, + + 478, 476, 475, 474, 473, 472, 471, 469, 468, 467, + 466, 465, 464, 463, 462, 461, 460, 459, 457, 454, + 453, 452, 451, 450, 449, 448, 447, 446, 445, 444, + 443, 442, 441, 440, 439, 438, 437, 436, 433, 432, + 431, 429, 428, 427, 425, 424, 423, 422, 421, 420, + 419, 418, 417, 416, 415, 414, 413, 410, 408, 407, + 406, 405, 403, 401, 400, 399, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, - 383, 382, 381, 380, 379, 378, 377, 373, 371, 370, - 368, 367, 366, 365, 364, 363, 361, 360, 359, 358, - 357, 356, 355, 354, 353, 352, 351, 349, 346, 345, + 383, 382, 381, 380, 376, 374, 373, 371, 370, 369, + 368, 367, 366, 364, 363, 362, 361, 360, 359, 358, - 344, 343, 342, 341, 340, 338, 337, 335, 334, 333, - 332, 331, 330, 328, 327, 326, 325, 324, 322, 321, + 357, 356, 355, 354, 352, 349, 348, 347, 346, 345, + 344, 343, 341, 340, 338, 337, 336, 335, 334, 333, + 331, 330, 329, 328, 327, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, - 310, 309, 308, 307, 306, 304, 303, 301, 300, 299, - 298, 297, 296, 295, 294, 293, 292, 289, 288, 286, - 284, 283, 282, 281, 280, 279, 278, 277, 275, 274, - 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, - 263, 262, 261, 260, 259, 258, 257, 256, 254, 253, - 252, 250, 248, 247, 246, 245, 244, 242, 241, 239, - 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, - - 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, - 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, - 208, 207, 206, 205, 204, 202, 201, 200, 199, 198, - 197, 196, 195, 193, 191, 190, 189, 188, 187, 186, - 184, 183, 182, 180, 179, 177, 176, 175, 174, 173, - 172, 170, 169, 168, 165, 164, 161, 159, 158, 157, - 154, 153, 152, 146, 144, 143, 142, 141, 140, 139, - 138, 137, 134, 133, 132, 130, 129, 128, 127, 126, - 125, 124, 122, 121, 119, 116, 115, 114, 112, 111, - 110, 109, 108, 102, 100, 99, 97, 96, 95, 94, - - 88, 83, 78, 72, 71, 70, 69, 67, 56, 50, - 49, 47, 42, 40, 38, 35, 29, 24, 22, 21, - 15, 11, 10, 9, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, - 1228, 1228, 1228, 1228, 1228 + 310, 309, 307, 306, 304, 303, 302, 301, 300, 299, + 298, 297, 296, 295, 292, 291, 289, 287, 286, 285, + 284, 283, 282, 281, 280, 278, 277, 276, 275, 274, + 273, 272, 271, 270, 269, 267, 266, 265, 264, 263, + 262, 261, 260, 259, 258, 257, 255, 254, 253, 251, + 249, 248, 247, 246, 245, 243, 242, 240, 239, 238, + + 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, + 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, + 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, + 207, 206, 205, 203, 202, 201, 200, 199, 198, 197, + 196, 194, 192, 191, 190, 189, 188, 187, 185, 184, + 183, 181, 180, 178, 177, 176, 175, 173, 171, 170, + 169, 166, 165, 164, 161, 159, 158, 157, 154, 153, + 152, 146, 144, 143, 142, 141, 140, 139, 138, 137, + 134, 133, 132, 130, 129, 128, 127, 126, 125, 124, + 122, 121, 119, 116, 115, 114, 112, 111, 110, 109, + + 108, 102, 100, 99, 97, 96, 95, 94, 88, 83, + 78, 72, 71, 70, 69, 56, 50, 49, 47, 42, + 40, 38, 35, 29, 24, 22, 21, 15, 11, 10, + 9, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235 } ; static yy_state_type yy_last_accepting_state; @@ -1226,9 +1229,9 @@ static char *pgaf_strdup(const char *s) * call flex's static input() function. */ static void pgaf_read_raw_block(void); -#line 1229 "test_spec_scan.c" +#line 1232 "test_spec_scan.c" -#line 1231 "test_spec_scan.c" +#line 1234 "test_spec_scan.c" #define INITIAL 0 #define CLUSTER_BODY 1 @@ -1450,7 +1453,7 @@ YY_DECL #line 89 "test_spec_scan.l" -#line 1453 "test_spec_scan.c" +#line 1456 "test_spec_scan.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1477,13 +1480,13 @@ YY_DECL while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1229 ) + if ( yy_current_state >= 1236 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_current_state != 1228 ); + while ( yy_current_state != 1235 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -2158,100 +2161,100 @@ YY_RULE_SETUP case 121: YY_RULE_SETUP #line 280 "test_spec_scan.l" -{ return T_DOWN; } +{ return T_NODEINI; } YY_BREAK case 122: YY_RULE_SETUP #line 281 "test_spec_scan.l" -{ return T_START; } +{ return T_DOWN; } YY_BREAK case 123: YY_RULE_SETUP #line 282 "test_spec_scan.l" -{ return T_STOP; } +{ return T_START; } YY_BREAK case 124: YY_RULE_SETUP #line 283 "test_spec_scan.l" -{ return T_STOPPED; } +{ return T_STOP; } YY_BREAK case 125: YY_RULE_SETUP #line 284 "test_spec_scan.l" -{ return T_KILL; } +{ return T_STOPPED; } YY_BREAK case 126: YY_RULE_SETUP #line 285 "test_spec_scan.l" -{ return T_IN; } +{ return T_KILL; } YY_BREAK case 127: YY_RULE_SETUP #line 286 "test_spec_scan.l" -{ return T_STATE; } +{ return T_IN; } YY_BREAK case 128: YY_RULE_SETUP #line 287 "test_spec_scan.l" -{ return T_ASSIGNED_STATE; } +{ return T_STATE; } YY_BREAK case 129: YY_RULE_SETUP #line 288 "test_spec_scan.l" -{ return T_CANDIDATE_PRIORITY; } +{ return T_ASSIGNED_STATE; } YY_BREAK case 130: YY_RULE_SETUP #line 289 "test_spec_scan.l" -{ return T_GROUP; } +{ return T_CANDIDATE_PRIORITY; } YY_BREAK case 131: YY_RULE_SETUP #line 290 "test_spec_scan.l" -{ return T_AND; } +{ return T_GROUP; } YY_BREAK case 132: YY_RULE_SETUP #line 291 "test_spec_scan.l" -{ return T_IS; } +{ return T_AND; } YY_BREAK case 133: YY_RULE_SETUP #line 292 "test_spec_scan.l" -{ return T_WITH; } +{ return T_IS; } YY_BREAK case 134: YY_RULE_SETUP #line 293 "test_spec_scan.l" -{ return T_EQUALS; } +{ return T_WITH; } YY_BREAK case 135: YY_RULE_SETUP #line 294 "test_spec_scan.l" -{ return T_COMMA; } +{ return T_EQUALS; } YY_BREAK case 136: YY_RULE_SETUP #line 295 "test_spec_scan.l" -{ return T_POSTGRES; } +{ return T_COMMA; } YY_BREAK case 137: YY_RULE_SETUP #line 296 "test_spec_scan.l" -{ return T_STAYS; } +{ return T_POSTGRES; } YY_BREAK case 138: YY_RULE_SETUP #line 297 "test_spec_scan.l" -{ return T_WHILE; } +{ return T_STAYS; } YY_BREAK case 139: -/* rule 139 can match eol */ YY_RULE_SETUP #line 298 "test_spec_scan.l" -{ return T_THROUGH; } +{ return T_WHILE; } YY_BREAK case 140: +/* rule 140 can match eol */ YY_RULE_SETUP #line 299 "test_spec_scan.l" { return T_THROUGH; } @@ -2259,54 +2262,64 @@ YY_RULE_SETUP case 141: YY_RULE_SETUP #line 300 "test_spec_scan.l" -{ return T_SET; } +{ return T_THROUGH; } YY_BREAK case 142: YY_RULE_SETUP #line 301 "test_spec_scan.l" -{ BEGIN(EXEC_ARGS); return T_INJECT; } +{ return T_SET; } YY_BREAK case 143: YY_RULE_SETUP #line 302 "test_spec_scan.l" -{ return T_LOGS; } +{ return T_GET; } YY_BREAK case 144: YY_RULE_SETUP #line 303 "test_spec_scan.l" -{ return T_NOT; } +{ BEGIN(EXEC_ARGS); return T_INJECT; } YY_BREAK case 145: YY_RULE_SETUP #line 304 "test_spec_scan.l" -{ return T_CONTAINS; } +{ return T_LOGS; } YY_BREAK case 146: YY_RULE_SETUP #line 305 "test_spec_scan.l" -{ return T_MATCHES; } +{ return T_NOT; } YY_BREAK case 147: YY_RULE_SETUP +#line 306 "test_spec_scan.l" +{ return T_CONTAINS; } + YY_BREAK +case 148: +YY_RULE_SETUP #line 307 "test_spec_scan.l" +{ return T_MATCHES; } + YY_BREAK +case 149: +YY_RULE_SETUP +#line 309 "test_spec_scan.l" { yylval.ival = atoi(yytext); return T_INTEGER; } YY_BREAK -case 148: -/* rule 148 can match eol */ +case 150: +/* rule 150 can match eol */ YY_RULE_SETUP -#line 312 "test_spec_scan.l" +#line 314 "test_spec_scan.l" { yytext[yyleng - 1] = '\0'; yylval.str = pgaf_strdup(yytext + 1); return T_STRING; } YY_BREAK -case 149: +case 151: YY_RULE_SETUP -#line 318 "test_spec_scan.l" +#line 320 "test_spec_scan.l" { if (pgaf_next_brace_is_while) { pgaf_next_brace_is_while = 0; @@ -2317,9 +2330,9 @@ YY_RULE_SETUP return T_BLOCK; } YY_BREAK -case 150: +case 152: YY_RULE_SETUP -#line 328 "test_spec_scan.l" +#line 330 "test_spec_scan.l" { if (pgaf_step_brace_depth > 0) { pgaf_step_brace_depth--; @@ -2330,40 +2343,40 @@ YY_RULE_SETUP return T_RBRACE; } YY_BREAK -case 151: +case 153: YY_RULE_SETUP -#line 338 "test_spec_scan.l" +#line 340 "test_spec_scan.l" { yylval.str = pgaf_strdup(yytext); return T_IDENT; } YY_BREAK -case 152: +case 154: YY_RULE_SETUP -#line 343 "test_spec_scan.l" +#line 345 "test_spec_scan.l" { /* skip whitespace before service name */ } YY_BREAK -case 153: +case 155: YY_RULE_SETUP -#line 345 "test_spec_scan.l" +#line 347 "test_spec_scan.l" { yylval.str = pgaf_strdup(yytext); BEGIN(EXEC_ARGS_REST); return T_IDENT; } YY_BREAK -case 154: -/* rule 154 can match eol */ +case 156: +/* rule 156 can match eol */ YY_RULE_SETUP -#line 351 "test_spec_scan.l" +#line 353 "test_spec_scan.l" { pgaf_line_number++; BEGIN(STEP_BODY); } YY_BREAK -case 155: +case 157: YY_RULE_SETUP -#line 356 "test_spec_scan.l" +#line 358 "test_spec_scan.l" { char *p = yytext; while (*p == ' ' || *p == '\t') p++; @@ -2372,21 +2385,21 @@ YY_RULE_SETUP return T_SHELL_ARGS; } YY_BREAK -case 156: -/* rule 156 can match eol */ +case 158: +/* rule 158 can match eol */ YY_RULE_SETUP -#line 364 "test_spec_scan.l" +#line 366 "test_spec_scan.l" { pgaf_line_number++; BEGIN(STEP_BODY); } YY_BREAK -case 157: +case 159: YY_RULE_SETUP -#line 369 "test_spec_scan.l" +#line 371 "test_spec_scan.l" ECHO; YY_BREAK -#line 2389 "test_spec_scan.c" +#line 2402 "test_spec_scan.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(CLUSTER_BODY): case YY_STATE_EOF(STEP_BODY): @@ -2688,7 +2701,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1229 ) + if ( yy_current_state >= 1236 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -2716,11 +2729,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 1229 ) + if ( yy_current_state >= 1236 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 1228); + yy_is_jam = (yy_current_state == 1235); return yy_is_jam ? 0 : yy_current_state; } @@ -3359,7 +3372,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 369 "test_spec_scan.l" +#line 371 "test_spec_scan.l" static void diff --git a/src/bin/pgaftest/test_spec_scan.l b/src/bin/pgaftest/test_spec_scan.l index 12e6355df..a907d1170 100644 --- a/src/bin/pgaftest/test_spec_scan.l +++ b/src/bin/pgaftest/test_spec_scan.l @@ -277,6 +277,7 @@ static void pgaf_read_raw_block(void); "connect" { return T_CONNECT; } "sleep" { return T_SLEEP; } "compose" { return T_COMPOSE; } +"nodeini" { return T_NODEINI; } "down" { return T_DOWN; } "start" { return T_START; } "stop" { return T_STOP; } @@ -298,6 +299,7 @@ static void pgaf_read_raw_block(void); "passing"[ \t\r\n]+"through" { return T_THROUGH; } "through" { return T_THROUGH; } "set" { return T_SET; } +"get" { return T_GET; } "inject" { BEGIN(EXEC_ARGS); return T_INJECT; } "logs" { return T_LOGS; } "not" { return T_NOT; } diff --git a/tests/tap/specs/config_get_set.pgaf b/tests/tap/specs/config_get_set.pgaf index f1d83fb48..bb95d8f5d 100644 --- a/tests/tap/specs/config_get_set.pgaf +++ b/tests/tap/specs/config_get_set.pgaf @@ -8,7 +8,7 @@ cluster { monitor formation { - node1 + node1 region dc1 } } @@ -46,3 +46,39 @@ step test_002b_config_set_node { exec node1 pg_autoctl config get postgresql.pg_ctl expect { /bin/pg_ctl } } + +# region is set at create time (node1 region dc1) and, unlike +# candidate-priority/replication-quorum, has no FSM impact -- changing it +# should not require a wait for convergence. +step test_003_region_cli_roundtrip { + exec node1 pg_autoctl get node region + expect { dc1 } + exec node1 pg_autoctl set node region dc2 + exec node1 pg_autoctl get node region + expect { dc2 } +} + +# Edit node1's host-side .ini file directly, bypassing the CLI entirely, to +# exercise the supervisor's automatic file-watch apply path (nodespec.c) -- +# region must be picked up with no restart and no explicit apply command. +# +# Known local-only limitation: under Docker Desktop for macOS (virtiofs), +# host-side writes to a bind-mounted file sync content into the container +# immediately, but do NOT reliably raise the inotify event the supervisor's +# watcher listens for -- confirmed by editing the file, `compose exec`-ing a +# `cat` of it (shows the new value right away), yet seeing no "nodespec: +# applied" log line and no monitor-side update. This is a virtiofs/gRPC-fuse +# gap in relaying host-originated filesystem events into the Linux guest, +# not a bug in nodespec.c/nodeini -- native Linux Docker (CI runners) has no +# such VM boundary and should pick the change up within one ~100ms tick. +step test_004_region_nodeini_live_apply { + nodeini set node1 region dc3 + nodeini get node1 region dc3 + + # The supervisor checks the spec file on its ~100ms tick; give it a + # little room before asserting the change was applied automatically. + sleep 8s + + exec node1 pg_autoctl get node region + expect { dc3 } +} From 7625ccde89d6ba6c26b62c4439959da4a81d98bd Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Sat, 25 Jul 2026 00:27:04 +0200 Subject: [PATCH 4/5] nodespec: live-apply region; make file-watch detection CRC-based nodespec_apply() gains a region block matching the existing candidate_priority/replication_quorum pattern exactly: shells out to `pg_autoctl set node region --pgdata ` via run_program() when node.ini's region entry changes -- i.e. node.ini editing was never a second, parallel implementation for these settings, just automation that types the same CLI command a human would. Separately, hardened the watcher itself: change detection is now always CRC32C-hash based (nodespec_file_crc / NodeSpecWatcher.last_crc), with inotify (Linux only) used purely as a low-latency hint to check sooner, never trusted as the sole signal. inotify has been observed to silently miss host-originated writes to a bind-mounted node.ini under Docker Desktop for macOS's virtiofs -- the write's content lands in the container immediately, but no IN_CLOSE_WRITE event is ever raised. The hash poll (NODESPEC_HASH_POLL_INTERVAL_SECS, currently 1s) guarantees a change is picked up regardless of whether inotify fires, on any platform/filesystem. --- src/bin/pg_autoctl/nodespec.c | 130 +++++++++++++++++++++++++--------- src/bin/pg_autoctl/nodespec.h | 19 +++-- 2 files changed, 108 insertions(+), 41 deletions(-) diff --git a/src/bin/pg_autoctl/nodespec.c b/src/bin/pg_autoctl/nodespec.c index c83921389..d57655d2d 100644 --- a/src/bin/pg_autoctl/nodespec.c +++ b/src/bin/pg_autoctl/nodespec.c @@ -818,6 +818,30 @@ nodespec_apply(const NodeSpec *new_spec, const NodeSpec *old_spec) free_program(&prog); } + if (strcmp(new_spec->region, old_spec->region) != 0) + { + Program prog = run_program(pg_autoctl_program, + "set", "node", "region", + "--pgdata", new_spec->pgdata, + new_spec->region, NULL); + + if (prog.returnCode != 0) + { + log_warn("nodespec_apply: set region %s failed (rc=%d)", + new_spec->region, prog.returnCode); + if (prog.stdOut) + { + log_warn("%s", prog.stdOut); + } + } + else + { + log_info("nodespec: applied region = %s", new_spec->region); + changed = true; + } + free_program(&prog); + } + /* immediate → deferred on an already-started node: non-fatal, ignored */ if (!old_spec->launchDeferred && new_spec->launchDeferred) { @@ -1001,16 +1025,43 @@ nodespec_apply(const NodeSpec *new_spec, const NodeSpec *old_spec) * Watcher * ----------------------------------------------------------------------- */ +/* + * nodespec_file_crc computes the CRC32C of the current content of *path + * into *crc. Returns false (leaving *crc untouched) if the file can't be + * read right now — a transient condition while it's being rewritten, not + * treated as a change. + */ +static bool +nodespec_file_crc(const char *path, pg_crc32c *crc) +{ + char *contents = NULL; + long fileSize = 0; + + if (!read_file(path, &contents, &fileSize)) + { + return false; + } + + pg_crc32c newCrc; + INIT_CRC32C(newCrc); + COMP_CRC32C(newCrc, contents, fileSize); + FIN_CRC32C(newCrc); + + free(contents); + + *crc = newCrc; + return true; +} + + /* * nodespec_watcher_init sets up file watching for *path. - * On Linux we try inotify first; everywhere else (and on failure) we fall - * back to mtime polling every NODESPEC_WATCH_INTERVAL_SECS. + * On Linux, inotify is also armed as a low-latency hint; see + * nodespec_watcher_check for why it is never the sole source of truth. */ bool nodespec_watcher_init(NodeSpecWatcher *w, const char *path) { - struct stat st; - memset(w, 0, sizeof(*w)); strlcpy(w->path, path, sizeof(w->path)); @@ -1026,32 +1077,31 @@ nodespec_watcher_init(NodeSpecWatcher *w, const char *path) if (w->watch_fd < 0) { log_debug("nodespec_watcher_init: inotify_add_watch(\"%s\"): %m; " - "falling back to mtime poll", path); + "relying on the CRC hash poll instead", path); close(w->inotify_fd); w->inotify_fd = -1; } else { - log_info("nodespec: watching \"%s\" via inotify", path); + log_info("nodespec: watching \"%s\" via inotify " + "(plus a %ds CRC hash poll as a reliability net)", + path, NODESPEC_HASH_POLL_INTERVAL_SECS); } } else { log_debug("nodespec_watcher_init: inotify_init1: %m; " - "falling back to mtime poll"); + "relying on the CRC hash poll instead"); w->inotify_fd = -1; w->watch_fd = -1; } #endif - /* record initial mtime so we don't fire on the very first check */ - if (stat(path, &st) == 0) - { - w->last_mtime = st.st_mtime; - } - else + /* record initial CRC so we don't fire on the very first check */ + if (!nodespec_file_crc(path, &w->last_crc)) { - w->last_mtime = 0; + INIT_CRC32C(w->last_crc); + FIN_CRC32C(w->last_crc); } w->active = true; @@ -1062,12 +1112,21 @@ nodespec_watcher_init(NodeSpecWatcher *w, const char *path) /* * nodespec_watcher_check is called from the supervisor's 100 ms tick. * + * Change detection is always CRC32C-hash based: inotify (when available) is + * only used to check sooner than the next scheduled hash poll, never as the + * sole signal that something changed. inotify has been observed to silently + * miss host-originated writes to a bind-mounted file under some + * containerized/virtualized filesystems (e.g. Docker Desktop for macOS's + * virtiofs: the write's content lands in the container right away, but no + * IN_CLOSE_WRITE event is ever raised) — the hash poll guarantees a change + * is still picked up within NODESPEC_HASH_POLL_INTERVAL_SECS regardless. + * * Returns true if the file changed and nodespec_apply() was attempted. */ bool nodespec_watcher_check(NodeSpecWatcher *w, const NodeSpec *current) { - bool file_changed = false; + bool inotify_hint = false; if (!w->active) { @@ -1078,52 +1137,53 @@ nodespec_watcher_check(NodeSpecWatcher *w, const NodeSpec *current) if (w->inotify_fd >= 0) { /* - * Drain all pending inotify events. We don't care about the event - * details — any event means the file was written. + * Drain all pending inotify events. This only decides whether to + * hash-check *now* instead of waiting for the next poll interval — + * see the function comment for why it can't be trusted alone. */ char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; ssize_t n; while ((n = read(w->inotify_fd, buf, sizeof(buf))) > 0) { - file_changed = true; + inotify_hint = true; } if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { log_warn("nodespec watcher: inotify read error: %m; " - "switching to mtime poll"); + "continuing with the CRC hash poll"); close(w->inotify_fd); w->inotify_fd = -1; w->watch_fd = -1; } } - else #endif - { - /* mtime poll — only stat every NODESPEC_WATCH_INTERVAL_SECS */ - time_t now = time(NULL); - if (now - w->last_checked < NODESPEC_WATCH_INTERVAL_SECS) - { - return false; - } + time_t now = time(NULL); + + if (!inotify_hint && + now - w->last_checked < NODESPEC_HASH_POLL_INTERVAL_SECS) + { + return false; + } - w->last_checked = now; + w->last_checked = now; - struct stat st; - if (stat(w->path, &st) == 0 && st.st_mtime != w->last_mtime) - { - w->last_mtime = st.st_mtime; - file_changed = true; - } + pg_crc32c newCrc; + if (!nodespec_file_crc(w->path, &newCrc)) + { + /* file transiently unreadable; try again on the next poll */ + return false; } - if (!file_changed) + if (EQ_CRC32C(newCrc, w->last_crc)) { return false; } + w->last_crc = newCrc; + /* File changed — re-parse and apply */ log_info("nodespec: \"%s\" changed, re-reading and converging", w->path); diff --git a/src/bin/pg_autoctl/nodespec.h b/src/bin/pg_autoctl/nodespec.h index c561469f3..944c2923f 100644 --- a/src/bin/pg_autoctl/nodespec.h +++ b/src/bin/pg_autoctl/nodespec.h @@ -28,6 +28,7 @@ #include "postgres_fe.h" /* MAXPGPATH, NAMEDATALEN, etc. */ #include "pgsql.h" /* MAXCONNINFO */ #include "pgsetup.h" /* PgInstanceKind, NODE_KIND_* */ +#include "port/pg_crc32c.h" /* * Fixed location inside every container. The compose generator writes one @@ -39,10 +40,15 @@ #define PG_AUTOCTL_NODESPEC_PATH "/etc/pgaf/node.ini" /* - * How often the supervisor polls the spec file for changes (seconds). - * inotify/kqueue are used when available; this is the fallback interval. + * How often the supervisor re-hashes the spec file to check for changes + * (seconds). This is the ground truth check: inotify is used to react + * sooner when it's available and actually delivering events, but content + * hashing runs on this interval regardless of inotify's reported state, so + * a silently-broken inotify backend (observed under Docker Desktop for + * macOS/virtiofs: host-side writes land in the container but never raise + * the IN_CLOSE_WRITE event) can never cause a change to go undetected. */ -#define NODESPEC_WATCH_INTERVAL_SECS 10 +#define NODESPEC_HASH_POLL_INTERVAL_SECS 1 /* ----------------------------------------------------------------------- * NodeSpec — one-to-one with the [sections] of pg_autoctl_node.ini @@ -116,8 +122,8 @@ typedef struct NodeSpecWatcher { bool active; /* true once nodespec_watcher_init() succeeds */ char path[MAXPGPATH]; /* path of the watched file */ - time_t last_mtime; /* mtime at last check */ - time_t last_checked; /* wall-clock time of last poll */ + pg_crc32c last_crc; /* CRC32C of the file content at last check */ + time_t last_checked; /* wall-clock time of last hash check */ #ifdef __linux__ int inotify_fd; /* inotify instance fd, -1 if unavailable */ @@ -155,7 +161,8 @@ bool nodespec_write_to_path(const NodeSpec *spec, const char *path); /* Initialise watcher state. Sets up inotify on Linux if available. */ bool nodespec_watcher_init(NodeSpecWatcher *w, const char *path); -/* Called from the supervisor's 100 ms tick. +/* Called from the supervisor's 100 ms tick. Actually re-hashes the file at + * most once every NODESPEC_HASH_POLL_INTERVAL_SECS (sooner if inotify fires). * Returns true if the file changed and nodespec_apply() was called. */ bool nodespec_watcher_check(NodeSpecWatcher *w, const NodeSpec *current); From 0ff1e6a86e7cd2c7124073e659c2c2eb091efa77 Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Sat, 25 Jul 2026 00:27:21 +0200 Subject: [PATCH 5/5] region: full parity with candidate_priority/replication_quorum region previously lived on KeeperConfig as a plain INI-backed option (OPTION_AUTOCTL_REGION), meaning it was read from and written to pg_autoctl.cfg and reachable via the generic `pg_autoctl config get/set pg_autoctl.region` -- a second, disconnected mutation path that never notified the monitor and (a pre-existing bug) didn't even persist reliably. candidate_priority/replication_quorum never had this generic exposure: they live on PostgresSetup.settings, merged into the config via a single direct struct-copy in keeper_config_merge_options() (config->pgSetup = pgSetup), entirely bypassing the INI option array, config file, and config get/set. region now follows the exact same path: - Moved from KeeperConfig.region to a new PostgresSetup.settings.region field (pgsetup.h), alongside candidatePriority/replicationQuorum. - OPTION_AUTOCTL_REGION and its SET_INI_OPTIONS_ARRAY entry removed entirely (keeper_config.c) -- region is no longer read from, written to, or merged through pg_autoctl.cfg in any way, and no longer reachable via keeper_config_to_json/config get/set at all. - --region at creation time now writes into LocalOptionConfig.pgSetup.settings.region (cli_common.c), riding the same direct struct-copy that already carries candidate_priority/ replication_quorum through keeper_config_merge_options. - Both monitor_register_node() call sites (keeper.c) updated to read config->pgSetup.settings.region. - `pg_autoctl config get/set pg_autoctl.region` now given a clear, dedicated error pointing to `pg_autoctl set/get node region` instead of falling through to a bare "unknown option" lookup failure (cli_config.c). The monitor remains the sole source of truth after registration, same as before. Verified with a full local Docker image rebuild (the generated docker-compose.yml has no `build:` section -- pg_autoctl:pgNN must be rebuilt manually for local source changes to take effect): config_get_set.pgaf passes reliably across repeated runs, and basic_operation.pgaf's full 27-step create/failover/maintenance/ network-partition lifecycle is unaffected. --- src/bin/common/pgsetup.h | 1 + src/bin/pg_autoctl/cli_common.c | 6 ++++-- src/bin/pg_autoctl/cli_config.c | 20 ++++++++++++++++++++ src/bin/pg_autoctl/keeper.c | 4 ++-- src/bin/pg_autoctl/keeper_config.c | 5 ----- src/bin/pg_autoctl/keeper_config.h | 1 - 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/bin/common/pgsetup.h b/src/bin/common/pgsetup.h index f4d4b182d..f66d3c78d 100644 --- a/src/bin/common/pgsetup.h +++ b/src/bin/common/pgsetup.h @@ -154,6 +154,7 @@ typedef struct NodeReplicationSettings char name[_POSIX_HOST_NAME_MAX]; int candidatePriority; /* promotion candidate priority */ bool replicationQuorum; /* true if participates in write quorum */ + char region[NAMEDATALEN]; /* data-centre / availability-zone label */ } NodeReplicationSettings; diff --git a/src/bin/pg_autoctl/cli_common.c b/src/bin/pg_autoctl/cli_common.c index 04c31165a..9c819fad3 100644 --- a/src/bin/pg_autoctl/cli_common.c +++ b/src/bin/pg_autoctl/cli_common.c @@ -410,8 +410,10 @@ cli_common_keeper_getopts(int argc, char **argv, case 'G': { /* { "region", required_argument, NULL, 'G' } */ - strlcpy(LocalOptionConfig.region, optarg, NAMEDATALEN); - log_trace("--region %s", LocalOptionConfig.region); + strlcpy(LocalOptionConfig.pgSetup.settings.region, + optarg, NAMEDATALEN); + log_trace("--region %s", + LocalOptionConfig.pgSetup.settings.region); break; } diff --git a/src/bin/pg_autoctl/cli_config.c b/src/bin/pg_autoctl/cli_config.c index 882f2fb6f..dfb867764 100644 --- a/src/bin/pg_autoctl/cli_config.c +++ b/src/bin/pg_autoctl/cli_config.c @@ -479,6 +479,16 @@ cli_keeper_config_get(int argc, char **argv) char *path = argv[0]; char value[BUFSIZE]; + if (strcmp(path, "pg_autoctl.region") == 0) + { + log_error("pg_autoctl.region is not available through " + "\"pg_autoctl config get\"; use " + "\"pg_autoctl get node region\" instead, which " + "reflects the monitor's view rather than a local, " + "disconnected copy"); + exit(EXIT_CODE_BAD_ARGS); + } + if (keeper_config_get_setting(&config, path, value, @@ -646,6 +656,16 @@ cli_keeper_config_set(int argc, char **argv) /* we print out the value that we parsed, as a double-check */ char value[BUFSIZE]; + if (strcmp(argv[0], "pg_autoctl.region") == 0) + { + log_error("pg_autoctl.region is not settable through " + "\"pg_autoctl config set\"; use " + "\"pg_autoctl set node region\" instead, which " + "updates the monitor directly, same as editing " + "node.ini's region entry does"); + exit(EXIT_CODE_BAD_ARGS); + } + if (!keeper_config_set_setting(&config, argv[0], argv[1])) diff --git a/src/bin/pg_autoctl/keeper.c b/src/bin/pg_autoctl/keeper.c index 26145c462..ee4997558 100644 --- a/src/bin/pg_autoctl/keeper.c +++ b/src/bin/pg_autoctl/keeper.c @@ -1670,7 +1670,7 @@ keeper_register_and_init(Keeper *keeper, NodeState initialState) config->pgSetup.settings.candidatePriority, config->pgSetup.settings.replicationQuorum, config->pgSetup.citusClusterName, - config->region, + config->pgSetup.settings.region, &mayRetry, &assignedState)) { @@ -1876,7 +1876,7 @@ keeper_register_again(Keeper *keeper) config->pgSetup.settings.candidatePriority, config->pgSetup.settings.replicationQuorum, DEFAULT_CITUS_CLUSTER_NAME, - config->region, + config->pgSetup.settings.region, &mayRetry, &assignedState)) { diff --git a/src/bin/pg_autoctl/keeper_config.c b/src/bin/pg_autoctl/keeper_config.c index 0d145b0ec..23815d28d 100644 --- a/src/bin/pg_autoctl/keeper_config.c +++ b/src/bin/pg_autoctl/keeper_config.c @@ -61,10 +61,6 @@ make_strbuf_option("pg_autoctl", "nodekind", NULL, false, NAMEDATALEN, \ config->nodeKind) -#define OPTION_AUTOCTL_REGION(config) \ - make_strbuf_option_default("pg_autoctl", "region", "region", \ - false, NAMEDATALEN, config->region, "") - #define OPTION_POSTGRESQL_PGDATA(config) \ make_strbuf_option("postgresql", "pgdata", "pgdata", true, MAXPGPATH, \ config->pgSetup.pgdata) @@ -231,7 +227,6 @@ OPTION_AUTOCTL_HOSTNAME(config), \ OPTION_AUTOCTL_NODENAME(config), \ OPTION_AUTOCTL_NODEKIND(config), \ - OPTION_AUTOCTL_REGION(config), \ OPTION_POSTGRESQL_PGDATA(config), \ OPTION_POSTGRESQL_PG_CTL(config), \ OPTION_POSTGRESQL_USERNAME(config), \ diff --git a/src/bin/pg_autoctl/keeper_config.h b/src/bin/pg_autoctl/keeper_config.h index 0ed9af1d4..0c71a65e0 100644 --- a/src/bin/pg_autoctl/keeper_config.h +++ b/src/bin/pg_autoctl/keeper_config.h @@ -46,7 +46,6 @@ typedef struct KeeperConfig char name[_POSIX_HOST_NAME_MAX]; char hostname[_POSIX_HOST_NAME_MAX]; char nodeKind[NAMEDATALEN]; - char region[NAMEDATALEN]; /* PostgreSQL setup */ PostgresSetup pgSetup;