1
1
package byzzbench .simulator .scheduler ;
2
2
3
3
import byzzbench .simulator .Scenario ;
4
+ import byzzbench .simulator .config .ByzzBenchConfig ;
4
5
import byzzbench .simulator .faults .Fault ;
5
6
import byzzbench .simulator .faults .FaultContext ;
6
7
import byzzbench .simulator .faults .FaultFactory ;
7
8
import byzzbench .simulator .faults .factories .ByzzFuzzScenarioFaultFactory ;
8
9
import byzzbench .simulator .service .MessageMutatorService ;
9
- import byzzbench .simulator .transport .ClientRequestEvent ;
10
- import byzzbench .simulator .transport .Event ;
11
- import byzzbench .simulator .transport .MessageEvent ;
12
- import byzzbench .simulator .transport .TimeoutEvent ;
13
10
import com .fasterxml .jackson .databind .JsonNode ;
14
11
import lombok .Getter ;
15
12
import lombok .extern .java .Log ;
16
13
import org .springframework .stereotype .Component ;
17
14
18
15
import java .util .ArrayList ;
19
16
import java .util .List ;
20
- import java .util .Optional ;
21
17
import java .util .Random ;
22
18
23
19
/**
28
24
@ Component
29
25
@ Log
30
26
@ Getter
31
- public class ByzzFuzzScheduler extends BaseScheduler {
27
+ public class ByzzFuzzScheduler extends RandomScheduler {
32
28
/**
33
29
* Small-scope mutations to be applied to protocol messages
34
30
*/
@@ -40,22 +36,30 @@ public class ByzzFuzzScheduler extends BaseScheduler {
40
36
/**
41
37
* Number of protocol rounds with process faults
42
38
*/
39
+ @ Getter
43
40
private int numRoundsWithProcessFaults = 1 ;
44
41
/**
45
42
* Number of protocol rounds with network faults
46
43
*/
44
+ @ Getter
47
45
private int numRoundsWithNetworkFaults = 1 ;
48
46
/**
49
47
* Number of protocol rounds among which the faults will be injected
50
48
*/
49
+ @ Getter
51
50
private int numRoundsWithFaults = 3 ;
52
51
53
- public ByzzFuzzScheduler (MessageMutatorService messageMutatorService ) {
54
- super ("ByzzFuzz" , messageMutatorService );
52
+ public ByzzFuzzScheduler (ByzzBenchConfig config , MessageMutatorService messageMutatorService ) {
53
+ super (config , messageMutatorService );
55
54
}
56
55
57
56
@ Override
58
- protected void loadSchedulerParameters (JsonNode parameters ) {
57
+ public String getId () {
58
+ return "ByzzFuzz" ;
59
+ }
60
+
61
+ @ Override
62
+ public void loadSchedulerParameters (JsonNode parameters ) {
59
63
System .out .println ("Loading ByzzFuzz parameters:" );
60
64
61
65
if (parameters != null )
@@ -76,100 +80,29 @@ protected void loadSchedulerParameters(JsonNode parameters) {
76
80
77
81
@ Override
78
82
public void initializeScenario (Scenario scenario ) {
83
+ super .initializeScenario (scenario );
84
+
85
+ // Generate round-aware small-scope mutations for the scenario
79
86
FaultFactory faultFactory = new ByzzFuzzScenarioFaultFactory ();
80
87
FaultContext context = new FaultContext (scenario );
81
88
List <Fault > faults = faultFactory .generateFaults (context );
82
89
faults .forEach (fault -> scenario .getTransport ().addFault (fault , true ));
83
90
}
84
91
85
92
@ Override
86
- public synchronized Optional <EventDecision > scheduleNext (Scenario scenario ) throws Exception {
87
- // Get a random event
88
- List <Event > queuedEvents = scenario .getTransport ().getEventsInState (Event .Status .QUEUED );
89
-
90
- // if there are no events, return empty
91
- if (queuedEvents .isEmpty ()) {
92
- System .out .println ("No events!" );
93
- return Optional .empty ();
94
- }
95
-
96
- int eventCount = queuedEvents .size ();
97
- int timeoutEventCount = (int ) queuedEvents .stream ().filter (TimeoutEvent .class ::isInstance ).count ();
98
- int clientRequestEventCount = (int ) queuedEvents .stream ().filter (ClientRequestEvent .class ::isInstance ).count ();
99
- int messageEventCount = eventCount - (timeoutEventCount + clientRequestEventCount );
100
-
101
- double timeoutEventProb = (double ) timeoutEventCount / eventCount ;
102
- double clientRequestEventProb = (double ) clientRequestEventCount / eventCount ;
103
- double messageEventProb = (double ) messageEventCount / eventCount ;
104
-
105
- assert timeoutEventProb + clientRequestEventProb + messageEventProb == 1.0 ;
106
-
107
- double dieRoll = random .nextDouble ();
108
-
109
- // check if we should schedule a timeout
110
- if (dieRoll < timeoutEventProb ) {
111
- // select a random event of type timeout
112
- List <Event > queuedTimeouts = queuedEvents .stream ()
113
- .filter (TimeoutEvent .class ::isInstance )
114
- .toList ();
115
-
116
- if (queuedTimeouts .isEmpty ()) {
117
- return Optional .empty ();
118
- }
119
-
120
- Event timeout = queuedTimeouts .get (random .nextInt (queuedTimeouts .size ()));
121
- scenario .getTransport ().deliverEvent (timeout .getEventId ());
122
-
123
- EventDecision decision = new EventDecision (EventDecision .DecisionType .DELIVERED , timeout .getEventId ());
124
- return Optional .of (decision );
125
- }
126
-
127
- // check if we should target a message
128
- if (dieRoll < timeoutEventProb + messageEventProb ) {
129
- // select a random event of type message
130
- List <Event > queuedMessages = queuedEvents .stream ()
131
- .filter (MessageEvent .class ::isInstance )
132
- .toList ();
133
-
134
- // if there are no messages, return an empty action
135
- if (queuedMessages .isEmpty ()) {
136
- return Optional .empty ();
137
- }
138
-
139
- Event message = queuedMessages .get (random .nextInt (queuedMessages .size ()));
140
-
141
- // deliver the message, without changes
142
- scenario .getTransport ().deliverEvent (message .getEventId ());
143
-
144
- EventDecision decision = new EventDecision (EventDecision .DecisionType .DELIVERED , message .getEventId ());
145
- return Optional .of (decision );
146
- }
147
-
148
- if (dieRoll < timeoutEventProb + messageEventProb + clientRequestEventProb ) {
149
- List <Event > queuedClientRequests = queuedEvents .stream ().filter (ClientRequestEvent .class ::isInstance ).toList ();
150
-
151
- if (queuedClientRequests .isEmpty ()) {
152
- return Optional .empty ();
153
- }
154
-
155
- Event request = queuedClientRequests .get (random .nextInt (clientRequestEventCount ));
156
-
157
- scenario .getTransport ().deliverEvent (request .getEventId ());
158
-
159
- EventDecision decision = new EventDecision (EventDecision .DecisionType .DELIVERED , request .getEventId ());
160
- return Optional .of (decision );
161
- }
162
-
163
- return Optional .empty ();
93
+ public int dropMessageWeight (Scenario scenario ) {
94
+ // ByzzFuzz does not drop messages as a scheduler decision
95
+ return 0 ;
164
96
}
165
97
166
98
@ Override
167
- public void reset () {
168
- // nothing to do
99
+ public int mutateMessageWeight (Scenario scenario ) {
100
+ // ByzzFuzz does not mutate messages as a scheduler decision
101
+ return 0 ;
169
102
}
170
103
171
104
@ Override
172
- public void stopDropMessages () {
173
- // FIXME: refactor
105
+ public void reset () {
106
+ // nothing to do
174
107
}
175
108
}
0 commit comments