Skip to content

Commit 6adf074

Browse files
committed
Merge branch 'main' into fixed-fab-with-main
2 parents 5f5cf52 + 0b41de3 commit 6adf074

File tree

11 files changed

+160
-124
lines changed

11 files changed

+160
-124
lines changed

simulator/src/main/java/byzzbench/simulator/config/ByzzBenchConfig.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public final class SchedulerConfig {
8383
* The ID of the scheduler to use.
8484
*/
8585
private String id;
86+
/**
87+
* Execution mode for the scheduler, limiting which messages can be delivered as the next scheduler action.
88+
*/
89+
private ExecutionMode executionMode = ExecutionMode.ASYNC;
8690
/**
8791
* Maximum number of messages to drop for a given scenario.
8892
*/
@@ -113,11 +117,24 @@ public final class SchedulerConfig {
113117
* The default is 0 (no messages are mutated as a scheduler decision).
114118
*/
115119
private int mutateMessageWeight = 0;
116-
117120
private Map<String, String> params;
118-
119121
private List<FaultConfig> faults = new ArrayList<>();
120122
private List<FaultConfig> mutations = new ArrayList<>();
123+
124+
// execution should be either "async" or "sync". Here is the enum:
125+
public enum ExecutionMode {
126+
/**
127+
* The scheduler will deliver any message that is currently queued.
128+
* This is the default behavior.
129+
*/
130+
ASYNC,
131+
/**
132+
* The scheduler will deliver the earliest-sent message that is currently queued.
133+
* This follows the communication-closure hypothesis.
134+
* This should be used with a non-zero "dropMessageWeight" to emulate the behavior in ByzzFuzz.
135+
*/
136+
SYNC,
137+
}
121138
}
122139

123140
/**

simulator/src/main/java/byzzbench/simulator/scheduler/BaseScheduler.java

+25-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
import lombok.Getter;
1414
import lombok.RequiredArgsConstructor;
1515

16-
import java.util.Comparator;
17-
import java.util.HashMap;
18-
import java.util.List;
19-
import java.util.Map;
16+
import java.util.*;
2017

2118
/**
2219
* Abstract base class for a scheduler.
@@ -42,6 +39,11 @@ public abstract class BaseScheduler implements Scheduler {
4239
@Getter(AccessLevel.PROTECTED)
4340
private final transient MessageMutatorService messageMutatorService;
4441

42+
/**
43+
* Random number generator
44+
*/
45+
protected Random rand = new Random();
46+
4547
/**
4648
* Loads the parameters for the scheduler from a JSON object.
4749
*
@@ -110,6 +112,25 @@ public List<ClientRequestEvent> getQueuedClientRequestEvents(Scenario scenario)
110112
*/
111113
protected abstract void loadSchedulerParameters(JsonNode parameters);
112114

115+
/**
116+
* Retrieve one of the queued message events.
117+
*
118+
* @param messageEvents The list of queued message events
119+
* @return The next message event
120+
*/
121+
public Event getNextMessageEvent(List<Event> messageEvents) {
122+
switch (config.getScheduler().getExecutionMode()) {
123+
case SYNC -> {
124+
return messageEvents.stream().min(Comparator.comparing(Event::getEventId)).orElseThrow();
125+
}
126+
case ASYNC -> {
127+
return messageEvents.get(rand.nextInt(messageEvents.size()));
128+
}
129+
default ->
130+
throw new IllegalStateException("Unknown execution mode: " + config.getScheduler().getExecutionMode());
131+
}
132+
}
133+
113134
/**
114135
* Returns the weight of delivering a message
115136
*

simulator/src/main/java/byzzbench/simulator/scheduler/ByzzFuzzScheduler.java

-12
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,4 @@ public void initializeScenario(Scenario scenario) {
8989
faults.forEach(fault -> scenario.getTransport().addFault(fault, true));
9090
}
9191

92-
@Override
93-
public int dropMessageWeight(Scenario scenario) {
94-
// ByzzFuzz does not drop messages as a scheduler decision
95-
return 0;
96-
}
97-
98-
@Override
99-
public int mutateMessageWeight(Scenario scenario) {
100-
// ByzzFuzz does not mutate messages as a scheduler decision
101-
return 0;
102-
}
103-
10492
}

simulator/src/main/java/byzzbench/simulator/scheduler/FifoScheduler.java

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public FifoScheduler(ByzzBenchConfig config, MessageMutatorService messageMutato
2020
super(config, messageMutatorService);
2121
}
2222

23+
@Override
2324
public String getId() {
2425
return "FIFO";
2526
}

simulator/src/main/java/byzzbench/simulator/scheduler/RandomScheduler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public RandomScheduler(ByzzBenchConfig config, MessageMutatorService messageMuta
3030
super(config, messageMutatorService);
3131
}
3232

33+
@Override
3334
public String getId() {
3435
return "Random";
3536
}
@@ -74,7 +75,7 @@ public synchronized Optional<EventDecision> scheduleNext(Scenario scenario) thro
7475
// check if we should deliver a message (without changes)
7576
dieRoll -= deliverMessageWeight;
7677
if (dieRoll < 0) {
77-
Event message = messageEvents.get(random.nextInt(messageEvents.size()));
78+
Event message = getNextMessageEvent(messageEvents);
7879
scenario.getTransport().deliverEvent(message.getEventId());
7980
EventDecision decision = new EventDecision(EventDecision.DecisionType.DELIVERED, message.getEventId());
8081
return Optional.of(decision);

simulator/src/main/java/byzzbench/simulator/scheduler/RandomSchedulerConfig.java

-7
This file was deleted.

simulator/src/main/java/byzzbench/simulator/scheduler/twins/TwinsScheduler.java

-12
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,4 @@ public void initializeScenario(Scenario scenario) {
6262
}
6363
}
6464

65-
@Override
66-
public int dropMessageWeight(Scenario scenario) {
67-
// Twins does not drop messages as a scheduler decision
68-
return 0;
69-
}
70-
71-
@Override
72-
public int mutateMessageWeight(Scenario scenario) {
73-
// Twins does not mutate messages as a scheduler decision
74-
return 0;
75-
}
76-
7765
}

simulator/src/main/resources/application.yml

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ byzzbench:
2323

2424
scheduler:
2525
id: "byzzfuzz" # The ID of the scheduler to use
26+
executionMode: async # async (default, any message delivered) or sync (communication-closure hypothesis, FIFO)
2627
maxDropMessages: 0 # Maximum number of messages to drop per scenario
2728
maxMutateMessages: 0 # Maximum number of messages to mutate per scenario
2829
deliverTimeoutWeight: 1 # The weight for scheduler to trigger a timeout

webui/app/page.tsx

+103-82
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
"use client";
22

3-
import {ClientList} from "@/components/ClientList";
4-
import {DroppedMessagesList} from "@/components/Events";
5-
import {ScenarioEnabledFaultsList} from "@/components/FaultsList";
6-
import {NodeList} from "@/components/NodeList";
7-
import {PredicateList} from "@/components/PredicateList";
8-
import {RunningSimulatorStats} from "@/components/RunningSimulatorStats";
9-
import {ScheduleDetails} from "@/components/Schedule";
10-
import {ScenarioScheduledFaultsList} from "@/components/ScheduledFaultsList";
11-
import {useGetMode, useGetSchedule} from "@/lib/byzzbench-client";
12-
import {Accordion, AppShell, Container, Group, ScrollArea, Stack, Title,} from "@mantine/core";
13-
import {useLocalStorage} from "@mantine/hooks";
14-
import dynamic from "next/dynamic";
3+
import { ClientList } from "@/components/ClientList";
4+
import { DroppedMessagesList } from "@/components/Events";
5+
import { ScenarioEnabledFaultsList } from "@/components/FaultsList";
6+
import { NodeList } from "@/components/NodeList";
7+
import { PredicateList } from "@/components/PredicateList";
8+
import { RunningSimulatorStats } from "@/components/RunningSimulatorStats";
9+
import { ScheduleDetails } from "@/components/Schedule";
10+
import { ScenarioScheduledFaultsList } from "@/components/ScheduledFaultsList";
11+
import { useGetMode, useGetSchedule } from "@/lib/byzzbench-client";
12+
import {
13+
Accordion,
14+
AppShell,
15+
Container,
16+
Group,
17+
ScrollArea,
18+
Stack,
19+
Switch,
20+
Title,
21+
} from "@mantine/core";
22+
import { useLocalStorage } from "@mantine/hooks";
1523
import React from "react";
1624

25+
/*
1726
const AdoBStateDiagram = dynamic<{}>(
1827
() =>
1928
import("@/components/adob/AdoBStateDiagram").then(
@@ -22,86 +31,98 @@ const AdoBStateDiagram = dynamic<{}>(
2231
{
2332
ssr: false,
2433
},
25-
);
34+
);*/
2635

2736
export default function Home() {
28-
const [selectedAccordionEntries, setSelectedAccordionEntries] =
29-
useLocalStorage<string[]>({
30-
key: "byzzbench/selectedAccordionEntries",
31-
defaultValue: ["nodes", "schedule"],
32-
});
37+
const [selectedAccordionEntries, setSelectedAccordionEntries] =
38+
useLocalStorage<string[]>({
39+
key: "byzzbench/selectedAccordionEntries",
40+
defaultValue: ["nodes", "schedule"],
41+
});
3342

34-
const {data: schedule} = useGetSchedule();
43+
const { data: schedule } = useGetSchedule();
3544

36-
const mode = useGetMode();
45+
const mode = useGetMode();
3746

38-
if (mode.data?.data === "RUNNING") {
39-
return (
40-
<Container fluid p="xl">
41-
<RunningSimulatorStats/>
42-
</Container>
43-
);
44-
}
47+
const [showMailboxes, setShowMailboxes] = useLocalStorage<boolean>({
48+
key: "byzzbench/showMailboxes",
49+
defaultValue: true,
50+
});
4551

52+
if (mode.data?.data === "RUNNING") {
4653
return (
47-
<Container fluid p="xl">
48-
<Stack gap="md">
49-
<Accordion
50-
multiple
51-
variant="separated"
52-
value={selectedAccordionEntries}
53-
onChange={setSelectedAccordionEntries}
54-
>
55-
<Group wrap="nowrap" gap="xs" align="center">
56-
<Title order={3}>{schedule?.data.scenarioId}</Title>
57-
<PredicateList/>
58-
</Group>
59-
<Accordion.Item key="clients" value="clients">
60-
<Accordion.Control>Clients</Accordion.Control>
61-
<Accordion.Panel>
62-
<ClientList/>
63-
</Accordion.Panel>
64-
</Accordion.Item>
65-
<Accordion.Item key="nodes" value="nodes">
66-
<Accordion.Control>Nodes</Accordion.Control>
67-
<Accordion.Panel>
68-
<NodeList/>
69-
</Accordion.Panel>
70-
</Accordion.Item>
71-
<Accordion.Item key="adob" value="adob">
54+
<Container fluid p="xl">
55+
<RunningSimulatorStats />
56+
</Container>
57+
);
58+
}
59+
60+
return (
61+
<Container fluid p="xl">
62+
<Stack gap="md">
63+
<Accordion
64+
multiple
65+
variant="separated"
66+
value={selectedAccordionEntries}
67+
onChange={setSelectedAccordionEntries}
68+
>
69+
<Group wrap="nowrap" gap="xs" align="center">
70+
<Title order={3}>{schedule?.data.scenarioId}</Title>
71+
<PredicateList />
72+
<Switch
73+
label="Show mailboxes"
74+
checked={showMailboxes}
75+
onChange={(event) => {
76+
setShowMailboxes(event.currentTarget.checked);
77+
}}
78+
/>
79+
</Group>
80+
<Accordion.Item key="clients" value="clients">
81+
<Accordion.Control>Clients</Accordion.Control>
82+
<Accordion.Panel>
83+
<ClientList />
84+
</Accordion.Panel>
85+
</Accordion.Item>
86+
<Accordion.Item key="nodes" value="nodes">
87+
<Accordion.Control>Nodes</Accordion.Control>
88+
<Accordion.Panel>
89+
<NodeList showMailboxes={showMailboxes} />
90+
</Accordion.Panel>
91+
</Accordion.Item>
92+
{/*<Accordion.Item key="adob" value="adob">
7293
<Accordion.Control>AdoB State</Accordion.Control>
7394
<Accordion.Panel>
7495
<AdoBStateDiagram/>
7596
</Accordion.Panel>
76-
</Accordion.Item>
77-
</Accordion>
78-
</Stack>
97+
</Accordion.Item>*/}
98+
</Accordion>
99+
</Stack>
79100

80-
<AppShell.Aside p="md" maw={400}>
81-
<Stack gap="xs">
82-
<Title order={5}>Schedule</Title>
83-
<ScrollArea mah={500} type="auto">
84-
{schedule?.data && (
85-
<ScheduleDetails
86-
hideTitle
87-
hideMaterializeButton
88-
hideDownloadButton
89-
hideDetailsButton
90-
hideScenario
91-
hideSaveButton
92-
title="Current Schedule"
93-
schedule={schedule.data}
94-
/>
95-
)}
96-
</ScrollArea>
97-
<Title order={5}>Trigger Faulty Behaviors</Title>
98-
<ScenarioEnabledFaultsList/>
99-
<Title order={5}>Scheduled Faults</Title>
100-
<ScenarioScheduledFaultsList/>
101-
<Title order={5}>Discarded Events</Title>
102-
<DroppedMessagesList/>
103-
</Stack>
104-
</AppShell.Aside>
105-
</Container>
106-
);
101+
<AppShell.Aside p="md" maw={400}>
102+
<Stack gap="xs">
103+
<Title order={5}>Schedule</Title>
104+
<ScrollArea mah={500} type="auto">
105+
{schedule?.data && (
106+
<ScheduleDetails
107+
hideTitle
108+
hideMaterializeButton
109+
hideDownloadButton
110+
hideDetailsButton
111+
hideScenario
112+
hideSaveButton
113+
title="Current Schedule"
114+
schedule={schedule.data}
115+
/>
116+
)}
117+
</ScrollArea>
118+
<Title order={5}>Trigger Faulty Behaviors</Title>
119+
<ScenarioEnabledFaultsList />
120+
<Title order={5}>Scheduled Faults</Title>
121+
<ScenarioScheduledFaultsList />
122+
<Title order={5}>Discarded Events</Title>
123+
<DroppedMessagesList />
124+
</Stack>
125+
</AppShell.Aside>
126+
</Container>
127+
);
107128
}

webui/components/NodeCard.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ import React from "react";
2121

2222
export type NodeCardProps = {
2323
nodeId: string;
24+
showMailboxes?: boolean;
2425
};
2526

26-
export const NodeCard = ({ nodeId }: NodeCardProps) => {
27+
export const NodeCard = ({ nodeId, showMailboxes = true }: NodeCardProps) => {
2728
const { data, isLoading } = useGetNode(nodeId);
2829
const faultyReplicasQuery = useGetFaultyReplicas();
2930
const partitionsQuery = useGetPartitions();
@@ -69,7 +70,7 @@ export const NodeCard = ({ nodeId }: NodeCardProps) => {
6970
/>
7071
)}
7172
<Space h="xs" />
72-
<NodeMailbox nodeId={nodeId} />
73+
{showMailboxes && <NodeMailbox nodeId={nodeId} />}
7374
</Card>
7475
);
7576
};

0 commit comments

Comments
 (0)