Skip to content

Commit ebd4459

Browse files
authored
Merge pull request #5153 from garlick/issue#5145
broker: redefine broker.quorum as a size
2 parents 73b5a75 + 4386b2f commit ebd4459

File tree

11 files changed

+81
-73
lines changed

11 files changed

+81
-73
lines changed

doc/man1/flux-start.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ OPTIONS
7777
**--test-start-mode**\ =\ *MODE*
7878
Set the start mode. If set to ``all``, all brokers are started immediately.
7979
If set to ``leader``, only the leader is started. Hint: in ``leader`` mode,
80-
use ``--setattr=broker.quorum=0`` to let the initial program start before
80+
use ``--setattr=broker.quorum=1`` to let the initial program start before
8181
the other brokers are online. Default: ``all``.
8282

8383
**--test-rundir**\ =\ *PATH*

doc/man1/flux-uptime.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ init
5959
The local broker is waiting for the ``rc1`` script to complete locally.
6060

6161
quorum
62-
All brokers are waiting for a configured set of brokers to reach **quorum**
63-
state. The default quorum set is all brokers. A Flux system instance
64-
typically defines the quorum set to only the rank 0 broker.
62+
All brokers are waiting for a configured number of brokers to reach
63+
**quorum** state. The default quorum is the instance size. A Flux
64+
system instance typically defines the quorum size to 1.
6565

6666
run
6767
Flux is fully up and running.

doc/man7/flux-broker-attributes.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ broker.pid
107107
The process id of the local broker.
108108

109109
broker.quorum [Updates: C]
110-
An RFC 22 idset representing broker ranks that are required to be online
111-
before the rank 0 broker enters the RUN state and starts the initial
112-
program, if any. Default: all ranks.
110+
The number of brokers that are required to be online before the rank 0
111+
broker enters the RUN state and starts the initial program, if any.
112+
Default: instance size.
113113

114114
broker.quorum-timeout [Updates: C]
115115
The amount of time (in RFC 23 Flux Standard Duration format) that the

etc/flux.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ExecStart=/bin/bash -c '\
1919
-Slog-stderr-level=6 \
2020
-Slog-stderr-mode=local \
2121
-Sbroker.rc2_none \
22-
-Sbroker.quorum=0 \
22+
-Sbroker.quorum=1 \
2323
-Sbroker.quorum-timeout=none \
2424
-Sbroker.exit-norestart=42 \
2525
-Sbroker.sd-notify=1 \

src/broker/state_machine.c

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "src/common/libutil/errprintf.h"
2828
#include "src/common/libsubprocess/server.h"
2929
#include "ccan/array_size/array_size.h"
30+
#include "ccan/str/str.h"
3031

3132
#include "state_machine.h"
3233

@@ -38,8 +39,9 @@
3839
#include "shutdown.h"
3940

4041
struct quorum {
41-
struct idset *want;
42-
struct idset *have; // cumulative on rank 0, batch buffer on rank > 0
42+
uint32_t size;
43+
struct idset *all;
44+
struct idset *online; // cumulative on rank 0, batch buffer on rank > 0
4345
flux_future_t *f;
4446
double timeout;
4547
bool warned;
@@ -182,21 +184,6 @@ static broker_state_t state_next (broker_state_t current, const char *event)
182184
return current;
183185
}
184186

185-
/* return true if a is a subset of b */
186-
static bool is_subset_of (const struct idset *a, const struct idset *b)
187-
{
188-
struct idset *ids;
189-
int count;
190-
191-
if (!(ids = idset_difference (a, b)))
192-
return false;
193-
count = idset_count (ids);
194-
idset_destroy (ids);
195-
if (count > 0)
196-
return false;
197-
return true;
198-
}
199-
200187
static void action_init (struct state_machine *s)
201188
{
202189
s->ctx->online = true;
@@ -245,7 +232,7 @@ static void quorum_timer_cb (flux_reactor_t *r,
245232
if (s->state != STATE_QUORUM)
246233
return;
247234

248-
if (!(ids = idset_difference (s->quorum.want, s->quorum.have))
235+
if (!(ids = idset_difference (s->quorum.all, s->quorum.online))
249236
|| !(rankstr = idset_encode (ids, IDSET_FLAG_RANGE))
250237
|| !(hl = hostlist_create ())) {
251238
flux_log_error (h, "error computing slow brokers");
@@ -749,43 +736,54 @@ static void quorum_check_parent (struct state_machine *s)
749736
}
750737
}
751738

752-
/* Configure the set of broker ranks needed for quorum (default=all).
739+
/* For backwards compatibility, translate "0" and "0-<size-1>" to 1 and <size>,
740+
* respectively, but print a warning on stderr.
741+
*/
742+
static bool quorum_configure_deprecated (struct state_machine *s,
743+
const char *val)
744+
{
745+
char all[64];
746+
snprintf (all, sizeof (all), "0-%lu", (unsigned long)s->ctx->size - 1);
747+
if (streq (val, all))
748+
s->quorum.size = s->ctx->size;
749+
else if (streq (val, "0"))
750+
s->quorum.size = 1;
751+
else
752+
return false;
753+
if (s->ctx->rank == 0) {
754+
log_msg ("warning: broker.quorum is now a size - assuming %lu",
755+
(unsigned long)s->quorum.size);
756+
}
757+
return true;
758+
}
759+
760+
/* Configure the count of broker ranks needed for quorum (default=<size>).
753761
*/
754762
static int quorum_configure (struct state_machine *s)
755763
{
756764
const char *val;
757-
char *tmp;
758-
unsigned long id;
759-
760765
if (attr_get (s->ctx->attrs, "broker.quorum", &val, NULL) == 0) {
761-
if (!(s->quorum.want = idset_decode (val))) {
762-
log_msg ("Error parsing broker.quorum attribute");
763-
return -1;
764-
}
765-
id = idset_last (s->quorum.want);
766-
if (id != IDSET_INVALID_ID && id >= s->ctx->size) {
767-
log_msg ("Error parsing broker.quorum attribute: exceeds size");
768-
return -1;
766+
if (!quorum_configure_deprecated (s, val)) {
767+
errno = 0;
768+
s->quorum.size = strtoul (val, NULL, 10);
769+
if (errno != 0
770+
|| s->quorum.size < 1
771+
|| s->quorum.size > s->ctx->size) {
772+
log_msg ("Error parsing broker.quorum attribute");
773+
errno = EINVAL;
774+
return -1;
775+
}
769776
}
770-
if (attr_delete (s->ctx->attrs, "broker.quorum", true) < 0)
777+
if (attr_set_flags (s->ctx->attrs, "broker.quorum", ATTR_IMMUTABLE) < 0)
771778
return -1;
772779
}
773780
else {
774-
if (!(s->quorum.want = idset_create (s->ctx->size, 0)))
781+
s->quorum.size = s->ctx->size;
782+
char buf[16];
783+
snprintf (buf, sizeof (buf), "%lu", (unsigned long)s->quorum.size);
784+
if (attr_add (s->ctx->attrs, "broker.quorum", buf, ATTR_IMMUTABLE) < 0)
775785
return -1;
776-
if (idset_range_set (s->quorum.want, 0, s->ctx->size - 1) < 0)
777-
return -1;
778-
}
779-
if (!(tmp = idset_encode (s->quorum.want, IDSET_FLAG_RANGE)))
780-
return -1;
781-
if (attr_add (s->ctx->attrs,
782-
"broker.quorum",
783-
tmp,
784-
ATTR_IMMUTABLE) < 0) {
785-
ERRNO_SAFE_WRAP (free, tmp);
786-
return -1;
787786
}
788-
free (tmp);
789787
return 0;
790788
}
791789

@@ -837,11 +835,10 @@ static void broker_online_cb (flux_future_t *f, void *arg)
837835
return;
838836
}
839837

840-
idset_destroy (s->quorum.have);
841-
s->quorum.have = ids;
842-
if (is_subset_of (s->quorum.want, s->quorum.have)) {
838+
idset_destroy (s->quorum.online);
839+
s->quorum.online = ids;
840+
if (idset_count (s->quorum.online) >= s->quorum.size)
843841
quorum_reached = true;
844-
}
845842

846843
if (strlen (members) > 0
847844
&& (quorum_reached || now - last_update > 5)) {
@@ -1150,8 +1147,8 @@ void state_machine_destroy (struct state_machine *s)
11501147
flux_msglist_destroy (s->wait_requests);
11511148
flux_future_destroy (s->monitor.f);
11521149
flux_msglist_destroy (s->monitor.requests);
1153-
idset_destroy (s->quorum.want);
1154-
idset_destroy (s->quorum.have);
1150+
idset_destroy (s->quorum.all);
1151+
idset_destroy (s->quorum.online);
11551152
flux_watcher_destroy (s->quorum.timer);
11561153
flux_future_destroy (s->quorum.f);
11571154
free (s);
@@ -1190,8 +1187,12 @@ struct state_machine *state_machine_create (struct broker *ctx)
11901187
if (!(s->monitor.f = monitor_parent (ctx->h, s)))
11911188
goto error;
11921189
}
1193-
if (!(s->quorum.have = idset_create (ctx->size, 0)))
1190+
if (!(s->quorum.online = idset_create (ctx->size, 0)))
1191+
goto error;
1192+
if (!(s->quorum.all = idset_create (s->ctx->size, 0))
1193+
|| idset_range_set (s->quorum.all, 0, s->ctx->size - 1) < 0)
11941194
goto error;
1195+
11951196
if (quorum_configure (s) < 0
11961197
|| quorum_timeout_configure (s) < 0) {
11971198
log_err ("error configuring quorum attributes");

src/cmd/flux-start.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ int exec_broker (const char *cmd_argz, size_t cmd_argz_len,
540540
struct stat sb;
541541

542542
add_argzf (&argz, &argz_len, "-Sbroker.recovery-mode=1");
543-
add_argzf (&argz, &argz_len, "-Sbroker.quorum=0");
543+
add_argzf (&argz, &argz_len, "-Sbroker.quorum=1");
544544
add_argzf (&argz, &argz_len, "-Slog-stderr-level=5");
545545

546546
// if --recovery has no optional argument, assume this is the system

t/sharness.d/flux-sharness.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ make_bootstrap_config() {
118118
echo "--test-hosts=$fakehosts -o,-c$workdir/conf.d"
119119
echo "--test-exit-mode=${TEST_UNDER_FLUX_EXIT_MODE:-leader}"
120120
echo "--test-exit-timeout=${TEST_UNDER_FLUX_EXIT_TIMEOUT:-0}"
121-
echo "-o,-Sbroker.quorum=${TEST_UNDER_FLUX_QUORUM:-$full}"
121+
echo "-o,-Sbroker.quorum=${TEST_UNDER_FLUX_QUORUM:-$size}"
122122
echo "--test-start-mode=${TEST_UNDER_FLUX_START_MODE:-all}"
123123
echo "-o,-Stbon.topo=${TEST_UNDER_FLUX_TOPO:-custom}"
124124
echo "-o,-Stbon.zmqdebug=1"
@@ -173,7 +173,7 @@ remove_trashdir_wrapper() {
173173
# - TEST_UNDER_FLUX_EXIT_TIMEOUT
174174
# Set the flux-start exit timeout (default: 0)
175175
# - TEST_UNDER_FLUX_QUORUM
176-
# Set the broker.quorum attribute (default: 0-<highest_rank>)
176+
# Set the broker.quorum attribute (default: <size>)
177177
# - TEST_UNDER_FLUX_START_MODE
178178
# Set the flux-start start mode (default: all)
179179
# - TEST_UNDER_FLUX_TOPO

t/t0025-broker-state-machine.t

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,30 @@ test_expect_success 'quorum reached on instance with 3 TBON levels' '
3131
'
3232

3333
test_expect_success 'broker.quorum can be set on the command line' '
34-
flux start -s3 ${ARGS} -o,-Sbroker.quorum="0-2" \
34+
flux start -s3 ${ARGS} -o,-Sbroker.quorum=3 \
3535
${GROUPSCMD} get broker.online >full1_explicit.out &&
3636
test_cmp full1.exp full1_explicit.out
3737
'
3838

3939
test_expect_success 'broker fails with malformed broker.quorum' '
4040
test_must_fail flux start ${ARGS} \
41-
-o,-Sbroker.quorum="badids" /bin/true 2>qmalformed.err &&
41+
-o,-Sbroker.quorum=9-10 /bin/true 2>qmalformed.err &&
4242
grep "Error parsing broker.quorum attribute" qmalformed.err
4343
'
4444

4545
test_expect_success 'broker fails with broker.quorum that exceeds size' '
4646
test_must_fail flux start ${ARGS} \
47-
-o,-Sbroker.quorum="0-1" /bin/true 2>qtoobig.err &&
48-
grep "Error parsing broker.quorum attribute: exceeds size" qtoobig.err
47+
-o,-Sbroker.quorum=99 /bin/true 2>qtoobig.err &&
48+
grep "Error parsing broker.quorum attribute" qtoobig.err
49+
'
50+
test_expect_success 'broker.quorum can be 0 for compatibility' '
51+
flux start ${ARGS} -o,-Sbroker.quorum=0 /bin/true 2>compat1.err &&
52+
grep assuming compat1.err
53+
'
54+
test_expect_success 'broker.quorum can be 0-1 (size=2) for compatibility' '
55+
flux start -s2 ${ARGS} -o,-Sbroker.quorum=0-1 /bin/true 2>compat2.err &&
56+
grep assuming compat2.err
4957
'
50-
5158
test_expect_success 'create rc1 that blocks on FIFO for rank != 0' '
5259
cat <<-EOT >rc1_block &&
5360
#!/bin/bash
@@ -77,7 +84,7 @@ test_expect_success 'instance functions with late-joiner' '
7784
-o,-Slog-stderr-level=6 \
7885
-o,-Sbroker.rc1_path="$(pwd)/rc1_block" \
7986
-o,-Sbroker.rc3_path= \
80-
-o,-Sbroker.quorum="0" \
87+
-o,-Sbroker.quorum=1 \
8188
$(pwd)/rc2_unblock >late.out &&
8289
test_cmp late.exp late.out
8390
'

t/t3203-instance-recovery.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test_expect_success 'start a persistent instance of size 4' '
1616
test_expect_success 'expected broker attributes are set in recovery mode' '
1717
cat >recov_attrs.exp <<-EOT &&
1818
1
19-
0
19+
1
2020
5
2121
EOT
2222
flux start --recovery=$(pwd)/test1 \

t/t3301-system-latestart.t

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ and ensure that it wires up.
1010

1111
. `dirname $0`/sharness.sh
1212

13-
export TEST_UNDER_FLUX_QUORUM=0
13+
export TEST_UNDER_FLUX_QUORUM=1
1414
export TEST_UNDER_FLUX_START_MODE=leader
1515

1616
test_under_flux 2 system
1717

1818
startctl="flux python ${SHARNESS_TEST_SRCDIR}/scripts/startctl.py"
1919

20-
test_expect_success 'broker.quorum was set to 0 by system test personality' '
21-
echo 0 >quorum.exp &&
20+
test_expect_success 'broker.quorum was set to 1 by system test personality' '
21+
echo 1 >quorum.exp &&
2222
flux getattr broker.quorum >quorum.out &&
2323
test_cmp quorum.exp quorum.out
2424
'

0 commit comments

Comments
 (0)