1
1
package byzzbench .simulator ;
2
2
3
- import byzzbench .simulator .faults .HealNodeNetworkFault ;
4
- import byzzbench .simulator .faults .IsolateProcessNetworkFault ;
3
+ import byzzbench .simulator .config .ByzzBenchConfig ;
4
+ import byzzbench .simulator .faults .Fault ;
5
+ import byzzbench .simulator .faults .FaultContext ;
6
+ import byzzbench .simulator .faults .factories .ByzzFuzzScenarioFaultFactory ;
7
+ import byzzbench .simulator .faults .faults .HealNodeNetworkFault ;
8
+ import byzzbench .simulator .faults .faults .IsolateProcessNetworkFault ;
5
9
import byzzbench .simulator .schedule .Schedule ;
6
10
import byzzbench .simulator .scheduler .Scheduler ;
7
11
import byzzbench .simulator .state .AgreementPredicate ;
@@ -30,98 +34,103 @@ public abstract class BaseScenario implements Scenario {
30
34
*/
31
35
@ ToString .Exclude
32
36
protected final transient Transport transport ;
33
-
34
37
/**
35
- * The scheduler for the scenario.
38
+ * The timekeeper for the scenario.
36
39
*/
37
- protected final Scheduler scheduler ;
38
-
40
+ protected final transient Timekeeper timekeeper ;
39
41
/**
40
- * Map of node id to the {@link Replica} object .
42
+ * The scheduler for the scenario .
41
43
*/
42
- @ Getter (onMethod_ = {@ Synchronized })
43
- @ JsonIgnore
44
- private final NavigableMap <String , Replica > nodes = new TreeMap <>();
45
-
44
+ protected final Scheduler scheduler ;
46
45
/**
47
- * Map of client id to the {@link Client } object.
46
+ * Map of node id to the {@link Node } object.
48
47
*/
49
48
@ Getter (onMethod_ = {@ Synchronized })
50
49
@ JsonIgnore
51
- private final NavigableMap <String , Client > clients = new TreeMap <>();
52
-
50
+ private final NavigableMap <String , Node > nodes = new TreeMap <>();
53
51
/**
54
52
* A unique identifier for the scenario.
55
53
*/
56
54
private final String id ;
57
-
58
55
/**
59
56
* The invariants that must be satisfied by the scenario at all times.
60
57
*/
61
58
private final List <ScenarioPredicate > invariants = List .of (new AgreementPredicate (), new LivenessPredicate ());
62
-
63
59
/**
64
60
* The schedule of events in order of delivery.
65
61
*/
66
62
@ Getter (onMethod_ = {@ Synchronized })
67
63
@ JsonIgnore
68
64
private final Schedule schedule = Schedule .builder ().scenario (this ).build ();
69
-
70
65
/**
71
66
* The observers of this scenario.
72
67
*/
73
68
@ JsonIgnore
74
69
private final transient List <ScenarioObserver > observers = new java .util .ArrayList <>();
70
+ /**
71
+ * The termination condition for the scenario.
72
+ */
73
+ protected ScenarioPredicate terminationCondition ;
74
+ /**
75
+ * Pseudo-random number generator for the scenario.
76
+ */
77
+ Random rand ;
75
78
76
79
/**
77
80
* Creates a new scenario with the given unique identifier and scheduler.
78
81
*
79
- * @param id The unique identifier for the scenario.
82
+ * @param id The unique identifier for the scenario.
80
83
* @param scheduler The scheduler for the scenario.
81
84
*/
82
85
protected BaseScenario (String id , Scheduler scheduler ) {
83
86
this .id = id ;
84
87
this .scheduler = scheduler ;
85
88
this .transport = new Transport (this );
89
+ this .timekeeper = new Timekeeper (this );
86
90
this .setupScenario ();
87
91
this .addObserver (new AdobDistributedState ());
88
92
}
89
93
90
94
/**
91
95
* Adds an observer to the scenario.
96
+ *
92
97
* @param observer The observer to add.
93
98
*/
94
99
public void addObserver (ScenarioObserver observer ) {
95
100
this .observers .add (observer );
96
101
}
97
102
98
103
/**
99
- * Removes an observer from the scenario.
100
- * @param observer The observer to remove.
104
+ * Removes all registered clients
101
105
*/
102
- public void removeObserver (ScenarioObserver observer ) {
103
- this .observers .remove (observer );
106
+ private void removeAllClients () {
107
+ this .nodes .entrySet ().stream ()
108
+ .filter (entry -> entry .getValue () instanceof Client )
109
+ .map (Map .Entry ::getKey )
110
+ .forEach (this .nodes ::remove );
104
111
}
105
112
106
113
/**
107
114
* Sets the number of clients in the scenario.
115
+ *
108
116
* @param numClients The number of clients to set.
109
117
*/
110
118
protected void setNumClients (int numClients ) {
111
- this .clients . clear ();
119
+ this .removeAllClients ();
112
120
for (int i = 0 ; i < numClients ; i ++) {
113
121
String clientId = String .format ("C%d" , i );
114
- Client client = Client .builder ().clientId (clientId ).transport (this . transport ).build ();
122
+ Client client = Client .builder ().id (clientId ).scenario (this ).build ();
115
123
this .addClient (client );
116
124
}
117
125
}
118
126
119
127
/**
120
128
* Adds a client to the scenario.
129
+ *
121
130
* @param client The client to add.
122
131
*/
123
132
public void addClient (Client client ) {
124
- this .clients .put (client .getClientId (), client );
133
+ this .nodes .put (client .getId (), client );
125
134
// notify the observers
126
135
this .observers .forEach (o -> o .onClientAdded (client ));
127
136
}
@@ -133,19 +142,23 @@ public void addClient(Client client) {
133
142
*/
134
143
public void addNode (Replica replica ) {
135
144
// add the node to the list of nodes
136
- getNodes ().put (replica .getNodeId (), replica );
145
+ getNodes ().put (replica .getId (), replica );
137
146
138
147
// for each node, add a IsolateNodeFault and a HealNodeFault
139
- this .transport .addNetworkFault (new IsolateProcessNetworkFault (replica .getNodeId ()));
140
- this .transport .addNetworkFault (new HealNodeNetworkFault (replica .getNodeId ()));
148
+ this .transport .addFault (new IsolateProcessNetworkFault (replica .getId ()), false );
149
+ this .transport .addFault (new HealNodeNetworkFault (replica .getId ()), false );
141
150
142
151
// notify the observers
143
152
this .observers .forEach (o -> o .onReplicaAdded (replica ));
144
153
}
145
154
146
155
@ Override
147
- public synchronized Replica getNode (String replicaId ) {
148
- return this .getNodes ().get (replicaId );
156
+ public synchronized Replica getNode (String nodeId ) {
157
+ Node node = this .getNodes ().get (nodeId );
158
+ if (!(node instanceof Replica replica )) {
159
+ throw new IllegalArgumentException ("Node with ID " + nodeId + " is not a replica." );
160
+ }
161
+ return replica ;
149
162
}
150
163
151
164
/**
@@ -154,8 +167,9 @@ public synchronized Replica getNode(String replicaId) {
154
167
@ Override
155
168
public final void setupScenario () {
156
169
this .setup ();
157
- getClients ().values ().forEach (Client ::initializeClient );
158
- getNodes ().values ().forEach (Replica ::initialize );
170
+ this .getClients ().values ().forEach (Client ::initialize );
171
+ this .getNodes ().values ().forEach (Node ::initialize );
172
+ this .scheduler .initializeScenario (this );
159
173
}
160
174
161
175
public final void loadParameters (JsonNode parameters ) {
@@ -170,11 +184,41 @@ public final void loadParameters(JsonNode parameters) {
170
184
this .scheduler .loadParameters (schedulerParameters );
171
185
}
172
186
187
+ if (parameters .has ("faults" )) {
188
+ System .out .println ("Faults: " + parameters .get ("faults" ).toPrettyString ());
189
+ ByzzFuzzScenarioFaultFactory faultFactory = new ByzzFuzzScenarioFaultFactory ();
190
+ List <Fault > faults = faultFactory .generateFaults (new FaultContext (this ));
191
+ faults .forEach (fault -> this .transport .addFault (fault , true ));
192
+ }
193
+
173
194
this .loadScenarioParameters (parameters );
174
195
}
175
196
197
+ public final void loadParameters (ByzzBenchConfig .ScenarioConfig config ) {
198
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
199
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
200
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
201
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
202
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
203
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
204
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
205
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
206
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
207
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
208
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
209
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
210
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
211
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
212
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
213
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
214
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
215
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
216
+ System .out .println ("Loading parameters for scenario: " + config .getId ());
217
+ }
218
+
176
219
/**
177
220
* Loads the parameters for the scenario from a JSON object.
221
+ *
178
222
* @param parameters The JSON object containing the parameters for the scenario.
179
223
*/
180
224
protected abstract void loadScenarioParameters (JsonNode parameters );
@@ -198,6 +242,7 @@ public final void runScenario() {
198
242
199
243
/**
200
244
* Checks if the invariants are satisfied by the scenario in its current state.
245
+ *
201
246
* @return True if the invariants are satisfied, false otherwise.
202
247
*/
203
248
@ Override
@@ -207,15 +252,53 @@ public final boolean invariantsHold() {
207
252
208
253
/**
209
254
* Returns the invariants that are not satisfied by the scenario in its current state.
255
+ *
210
256
* @return The invariants that are not satisfied by the scenario in its current state.
211
257
*/
212
258
public final SortedSet <ScenarioPredicate > unsatisfiedInvariants () {
213
259
return this .invariants .stream ().filter (invariant -> !invariant .test (this ))
214
260
.collect (Collectors .toCollection (TreeSet ::new ));
215
261
}
216
262
263
+ @ Override
264
+ public boolean isTerminated () {
265
+ return this .terminationCondition .test (this );
266
+ }
267
+
217
268
public final void finalizeSchedule () {
218
269
this .getSchedule ().finalizeSchedule (this .unsatisfiedInvariants ());
219
270
}
220
271
272
+ public void writeToFile () {
273
+
274
+ }
275
+
276
+ @ Override
277
+ public SortedSet <String > getNodeIds (Node node ) {
278
+ return new TreeSet <>(this .getNodes ().keySet ());
279
+ }
280
+
281
+ @ Override
282
+ public NavigableMap <String , Client > getClients () {
283
+ NavigableMap <String , Client > clients = new TreeMap <>();
284
+ this .getNodes ()
285
+ .values ()
286
+ .stream ()
287
+ .filter (Client .class ::isInstance )
288
+ .map (Client .class ::cast )
289
+ .forEach (client -> clients .put (client .getId (), client ));
290
+ return clients ;
291
+ }
292
+
293
+ @ Override
294
+ public NavigableMap <String , Replica > getReplicas () {
295
+ NavigableMap <String , Replica > replicas = new TreeMap <>();
296
+ this .getNodes ()
297
+ .values ()
298
+ .stream ()
299
+ .filter (Replica .class ::isInstance )
300
+ .map (Replica .class ::cast )
301
+ .forEach (replica -> replicas .put (replica .getId (), replica ));
302
+ return replicas ;
303
+ }
221
304
}
0 commit comments