Skip to content

Commit bc80b91

Browse files
committed
Rename CauseStack to PhaseStack, eliminating more ambiguity. Clean up some of the verbosity of errors and such with the PhaseTracker. Now it will properly silence itself after one instance of an error of a particular kind, unless verbose is enabled.
Signed-off-by: Gabriel Harris-Rouquette <[email protected]>
1 parent e1d0079 commit bc80b91

File tree

3 files changed

+68
-39
lines changed

3 files changed

+68
-39
lines changed

src/main/java/org/spongepowered/common/event/tracking/CauseStack.java renamed to src/main/java/org/spongepowered/common/event/tracking/PhaseStack.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,25 @@
4141
* Note that the {@link PhaseContext} must be marked as {@link PhaseContext#isComplete()},
4242
* otherwise an {@link IllegalArgumentException} is thrown.
4343
*/
44-
final class CauseStack {
44+
final class PhaseStack {
4545

4646
private static final PhaseContext<?> EMPTY = new GeneralizedContext(GeneralPhase.State.COMPLETE).markEmpty();
4747
static final PhaseData EMPTY_DATA = new PhaseData(EMPTY, GeneralPhase.State.COMPLETE);
4848
private static final int DEFAULT_QUEUE_SIZE = 16;
4949

5050
private final Deque<PhaseData> states;
5151

52-
CauseStack() {
52+
PhaseStack() {
5353
this(DEFAULT_QUEUE_SIZE);
5454
}
5555

56-
private CauseStack(int size) {
56+
private PhaseStack(int size) {
5757
this.states = new ArrayDeque<>(size);
5858
}
5959

6060
PhaseData peek() {
6161
final PhaseData phase = this.states.peek();
62-
return phase == null ? CauseStack.EMPTY_DATA : phase;
62+
return phase == null ? PhaseStack.EMPTY_DATA : phase;
6363
}
6464

6565
IPhaseState<?> peekState() {
@@ -69,21 +69,21 @@ IPhaseState<?> peekState() {
6969

7070
PhaseContext<?> peekContext() {
7171
final PhaseData peek = this.states.peek();
72-
return peek == null ? CauseStack.EMPTY : peek.context;
72+
return peek == null ? PhaseStack.EMPTY : peek.context;
7373
}
7474

7575
PhaseData pop() {
7676
return this.states.pop();
7777
}
7878

79-
private CauseStack push(PhaseData tuple) {
79+
private PhaseStack push(PhaseData tuple) {
8080
checkNotNull(tuple, "Tuple cannot be null!");
8181
checkArgument(tuple.context.isComplete(), "Phase context must be complete: %s", tuple);
8282
this.states.push(tuple);
8383
return this;
8484
}
8585

86-
CauseStack push(IPhaseState<?> state, PhaseContext<?> context) {
86+
PhaseStack push(IPhaseState<?> state, PhaseContext<?> context) {
8787
return push(new PhaseData(context, state));
8888
}
8989

@@ -112,7 +112,7 @@ public boolean equals(Object obj) {
112112
if (obj == null || getClass() != obj.getClass()) {
113113
return false;
114114
}
115-
final CauseStack other = (CauseStack) obj;
115+
final PhaseStack other = (PhaseStack) obj;
116116
return Objects.equals(this.states, other.states);
117117
}
118118

src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.spongepowered.api.event.SpongeEventFactory;
5050
import org.spongepowered.api.event.entity.SpawnEntityEvent;
5151
import org.spongepowered.api.plugin.PluginContainer;
52+
import org.spongepowered.api.util.Tuple;
5253
import org.spongepowered.api.world.BlockChangeFlag;
5354
import org.spongepowered.api.world.World;
5455
import org.spongepowered.asm.util.PrettyPrinter;
@@ -98,12 +99,15 @@ public final class PhaseTracker {
9899
*/
99100
};
100101

101-
private final CauseStack stack = new CauseStack();
102+
private final PhaseStack stack = new PhaseStack();
102103

103104
@Nullable private PhaseData currentProcessingState = null;
104105

105106
public final boolean isVerbose = SpongeImpl.getGlobalConfig().getConfig().getCauseTracker().isVerbose();
106107
public final boolean verboseErrors = SpongeImpl.getGlobalConfig().getConfig().getCauseTracker().verboseErrors();
108+
private boolean hasPrintedEmptyOnce = false;
109+
private boolean hasPrintedAboutRunnawayPhases = false;
110+
private List<Tuple<IPhaseState<?>, IPhaseState<?>>> completedIncorrectStates = new ArrayList<>();
107111

108112
private PhaseTracker() {
109113
// We cannot have two instances ever. ever ever.
@@ -118,7 +122,7 @@ public static PhaseTracker getInstance() {
118122

119123
// ----------------- STATE ACCESS ----------------------------------
120124

121-
public void switchToPhase(IPhaseState<?> state, PhaseContext<?> phaseContext) {
125+
void switchToPhase(IPhaseState<?> state, PhaseContext<?> phaseContext) {
122126
checkNotNull(state, "State cannot be null!");
123127
checkNotNull(state.getPhase(), "Phase cannot be null!");
124128
checkNotNull(phaseContext, "PhaseContext cannot be null!");
@@ -139,28 +143,6 @@ public void switchToPhase(IPhaseState<?> state, PhaseContext<?> phaseContext) {
139143
this.stack.push(state, phaseContext);
140144
}
141145

142-
public void switchToPhase(PhaseData phaseData) {
143-
checkNotNull(phaseData.state, "State cannot be null!");
144-
checkNotNull(phaseData.state.getPhase(), "Phase cannot be null!");
145-
checkNotNull(phaseData.context, "PhaseContext cannot be null!");
146-
checkArgument(phaseData.context.isComplete(), "PhaseContext must be complete!");
147-
148-
final IPhaseState<?> currentState = this.stack.peek().state;
149-
if (this.isVerbose) {
150-
if (this.stack.size() > 6 && !currentState.isExpectedForReEntrance()) {
151-
// This printing is to detect possibilities of a phase not being cleared properly
152-
// and resulting in a "runaway" phase state accumulation.
153-
printRunawayPhase(phaseData.state, phaseData.context);
154-
}
155-
if (!currentState.canSwitchTo(phaseData.state) && phaseData.state != GeneralPhase.Post.UNWINDING && currentState == GeneralPhase.Post.UNWINDING) {
156-
// This is to detect incompatible phase switches.
157-
printPhaseIncompatibility(currentState, phaseData.state);
158-
}
159-
}
160-
161-
this.stack.push(phaseData.state, phaseData.context);
162-
}
163-
164146
/**
165147
* Used when exception occurs during the main body of a phase.
166148
* Avoids running the normal unwinding code
@@ -222,6 +204,10 @@ public void completePhase(IPhaseState<?> prevState) {
222204
}
223205

224206
private void printRunnawayPhaseCompletion(IPhaseState<?> state) {
207+
if (!this.isVerbose && !this.hasPrintedAboutRunnawayPhases) {
208+
// Avoiding spam logs.
209+
return;
210+
}
225211
final PrettyPrinter printer = new PrettyPrinter(60);
226212
printer.add("Completing Phase").centre().hr();
227213
printer.addWrapped(50, "Detecting a runaway phase! Potentially a problem where something isn't completing a phase!!!");
@@ -234,6 +220,9 @@ private void printRunnawayPhaseCompletion(IPhaseState<?> state) {
234220
printer.add();
235221
generateVersionInfo(printer);
236222
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
223+
if (!this.isVerbose) {
224+
this.hasPrintedAboutRunnawayPhases = true;
225+
}
237226
}
238227

239228
public void generateVersionInfo(PrettyPrinter printer) {
@@ -245,6 +234,17 @@ public void generateVersionInfo(PrettyPrinter printer) {
245234
}
246235

247236
private void printIncorrectPhaseCompletion(IPhaseState<?> prevState, IPhaseState<?> state) {
237+
if (!this.isVerbose && !this.completedIncorrectStates.isEmpty()) {
238+
for (Tuple<IPhaseState<?>, IPhaseState<?>> tuple : this.completedIncorrectStates) {
239+
if ((tuple.getFirst().equals(prevState)
240+
&& tuple.getSecond().equals(state))) {
241+
// we've already printed once about the previous state and the current state
242+
// being completed incorrectly. only print it once.
243+
return;
244+
}
245+
}
246+
}
247+
248248
PrettyPrinter printer = new PrettyPrinter(60).add("Completing incorrect phase").centre().hr()
249249
.addWrapped(50, "Sponge's tracking system is very dependent on knowing when"
250250
+ "a change to any world takes place, however, we are attempting"
@@ -260,9 +260,19 @@ private void printIncorrectPhaseCompletion(IPhaseState<?> prevState, IPhaseState
260260
printer.add();
261261
generateVersionInfo(printer);
262262
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
263+
if (!this.isVerbose) {
264+
this.completedIncorrectStates.add(new Tuple<>(prevState, state));
265+
}
263266
}
264267

265268
private void printEmptyStackOnCompletion() {
269+
if (!this.isVerbose && this.hasPrintedEmptyOnce) {
270+
// We want to only mention it once that we are completing an
271+
// empty state, of course something is bound to break, but
272+
// we don't want to spam megabytes worth of log files just
273+
// because of it.
274+
return;
275+
}
266276
final PrettyPrinter printer = new PrettyPrinter(60).add("Unexpectedly Completing An Empty Stack").centre().hr()
267277
.addWrapped(50, "Sponge's tracking system is very dependent on knowing when"
268278
+ "a change to any world takes place, however, we have been told"
@@ -274,9 +284,16 @@ private void printEmptyStackOnCompletion() {
274284
.add();
275285
generateVersionInfo(printer);
276286
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
287+
if (!this.isVerbose) {
288+
this.hasPrintedEmptyOnce = true;
289+
}
277290
}
278291

279292
private void printRunawayPhase(IPhaseState<?> state, PhaseContext<?> context) {
293+
if (!this.isVerbose && !this.hasPrintedAboutRunnawayPhases) {
294+
// Avoiding spam logs.
295+
return;
296+
}
280297
final PrettyPrinter printer = new PrettyPrinter(40);
281298
printer.add("Switching Phase").centre().hr();
282299
printer.addWrapped(50, "Detecting a runaway phase! Potentially a problem where something isn't completing a phase!!!");
@@ -290,9 +307,22 @@ private void printRunawayPhase(IPhaseState<?> state, PhaseContext<?> context) {
290307
printer.add();
291308
generateVersionInfo(printer);
292309
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
310+
if (!this.isVerbose) {
311+
this.hasPrintedAboutRunnawayPhases = true;
312+
}
293313
}
294314

295315
private void printPhaseIncompatibility(IPhaseState<?> currentState, IPhaseState<?> incompatibleState) {
316+
if (!this.isVerbose && !this.completedIncorrectStates.isEmpty()) {
317+
for (Tuple<IPhaseState<?>, IPhaseState<?>> tuple : this.completedIncorrectStates) {
318+
if ((tuple.getFirst().equals(currentState)
319+
&& tuple.getSecond().equals(incompatibleState))) {
320+
// we've already printed once about the previous state and the current state
321+
// being completed incorrectly. only print it once.
322+
return;
323+
}
324+
}
325+
}
296326
PrettyPrinter printer = new PrettyPrinter(80);
297327
printer.add("Switching Phase").centre().hr();
298328
printer.add("Phase incompatibility detected! Attempting to switch to an invalid phase!");
@@ -307,13 +337,16 @@ private void printPhaseIncompatibility(IPhaseState<?> currentState, IPhaseState<
307337
printer.add();
308338
generateVersionInfo(printer);
309339
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
340+
if (!this.isVerbose) {
341+
this.completedIncorrectStates.add(Tuple.of(currentState, incompatibleState));
342+
}
310343
}
311344

312345
public void printMessageWithCaughtException(String header, String subHeader, Throwable e) {
313346
this.printMessageWithCaughtException(header, subHeader, this.getCurrentState(), this.getCurrentContext(), e);
314347
}
315348

316-
public void printMessageWithCaughtException(String header, String subHeader, IPhaseState<?> state, PhaseContext<?> context, Throwable t) {
349+
private void printMessageWithCaughtException(String header, String subHeader, IPhaseState<?> state, PhaseContext<?> context, Throwable t) {
317350
final PrettyPrinter printer = new PrettyPrinter(40);
318351
printer.add(header).centre().hr()
319352
.add("%s %s", subHeader, state)
@@ -328,7 +361,7 @@ public void printMessageWithCaughtException(String header, String subHeader, IPh
328361
printer.trace(System.err, SpongeImpl.getLogger(), Level.ERROR);
329362
}
330363

331-
public String dumpStack() {
364+
String dumpStack() {
332365
if (this.stack.isEmpty()) {
333366
return "[Empty stack]";
334367
}
@@ -356,10 +389,6 @@ public PhaseContext<?> getCurrentContext() {
356389
return this.stack.peekContext();
357390
}
358391

359-
public PhaseData getCurrentProcessingPhase() {
360-
return this.currentProcessingState == null ? CauseStack.EMPTY_DATA : this.currentProcessingState;
361-
}
362-
363392
// --------------------- DELEGATED WORLD METHODS -------------------------
364393

365394
/**

src/test/java/org/spongepowered/common/event/CauseStackManagerTest.java renamed to src/test/java/org/spongepowered/common/event/PhaseStackManagerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.spongepowered.lwts.runner.LaunchWrapperTestRunner;
3535

3636
@RunWith(LaunchWrapperTestRunner.class)
37-
public class CauseStackManagerTest {
37+
public class PhaseStackManagerTest {
3838

3939
@Test
4040
public void testPoppingFramePopsCauses() throws Exception {

0 commit comments

Comments
 (0)