-
Bug
-
Resolution: Done
-
Minor
-
None
-
None
-
Using Simulator to test protocol layers in isolation.
The Simulator.start() method in its original form does the following:
process Event.SET_LOCAL_ADDRESS
(ii) process Event.VIEW_CHANGE
(iii) for each protocol layer, call init() followed by start()
When used with the NAKACK layer, this throws an exception with the stack trace:
org.jgroups.tests.NakackTest:
java.lang.IllegalStateException: timer has to be provided and cannot be null
at org.jgroups.stack.NakReceiverWindow.<init>(NakReceiverWindow.java:139)
at org.jgroups.protocols.pbcast.NAKACK.createNakReceiverWindow(NAKACK.java:1325)
at org.jgroups.protocols.pbcast.NAKACK.adjustReceivers(NAKACK.java:1176)
at org.jgroups.protocols.pbcast.NAKACK.down(NAKACK.java:600)
at org.jgroups.debug.Simulator.start(Simulator.java:147)
at org.jgroups.tests.NakackTest.testReceptionOfAllMessages(NakackTest.java:165)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:580)
at org.testng.internal.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:49)
at org.testng.internal.InvokeMethodRunnable.run(InvokeMethodRunnable.java:40)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)
at java.util.concurrent.FutureTask.run(FutureTask.java:123)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
This exception arises because for NAKACK to process a VIEW_CHANGE, it needs to create a NakReceiverWindow, which requires access to the timer variable. This timer variable is initialised
in the call to NAKACK.init() which follows after.
Solution is to move the processing of events above after the initialization of the layers.