diff --git a/CHANGES.txt b/CHANGES.txt index 305aec3f9a..dc7c263cc8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,7 @@ * Revert CASSANDRA-18543 (CASSANDRA-18854) * Fix NPE when using udfContext in UDF after a restart of a node (CASSANDRA-18739) Merged from 3.0: + * Fix nodetool enable/disablebinary to correctly set rpc readiness in gossip (CASSANDRA-18935) * Implement the logic in bin/stop-server (CASSANDRA-18838) * Upgrade snappy-java to 1.1.10.4 (CASSANDRA-18878) * Add cqlshrc.sample and credentials.sample into Debian package (CASSANDRA-18818) diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index a4edca7097..d1fd08fb59 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -550,10 +550,7 @@ public class CassandraDaemon { String nativeFlag = System.getProperty("cassandra.start_native_transport"); if ((nativeFlag != null && Boolean.parseBoolean(nativeFlag)) || (nativeFlag == null && DatabaseDescriptor.startNativeTransport())) - { startNativeTransport(); - StorageService.instance.setRpcReady(true); - } else logger.info("Not starting native transport as requested. Use JMX (StorageService->startNativeTransport()) or nodetool (enablebinary) to start it"); @@ -713,13 +710,22 @@ public class CassandraDaemon if (nativeTransportService == null) throw new IllegalStateException("setup() must be called first for CassandraDaemon"); + // this iterates over a collection of servers and returns true if one of them is started + boolean alreadyRunning = nativeTransportService.isRunning(); + + // this might in practice start all servers which are not started yet nativeTransportService.start(); + + // interact with gossip only in case if no server was started before to signal they are started now + if (!alreadyRunning) + StorageService.instance.setRpcReady(true); } public void stopNativeTransport() { if (nativeTransportService != null) { + StorageService.instance.setRpcReady(false); nativeTransportService.stop(); } } diff --git a/test/distributed/org/apache/cassandra/distributed/test/NativeProtocolTest.java b/test/distributed/org/apache/cassandra/distributed/test/NativeProtocolTest.java index a8bf5ebf20..44e989c235 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/NativeProtocolTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/NativeProtocolTest.java @@ -33,6 +33,7 @@ import org.apache.cassandra.distributed.api.IInvokableInstance; import org.apache.cassandra.distributed.api.IIsolatedExecutor; import org.apache.cassandra.distributed.impl.RowUtil; import org.apache.cassandra.service.StorageService; +import org.apache.cassandra.utils.FBUtilities; import static org.apache.cassandra.distributed.action.GossipHelper.withProperty; import static org.apache.cassandra.distributed.api.Feature.GOSSIP; @@ -119,4 +120,28 @@ public class NativeProtocolTest extends TestBaseImpl () -> StorageService.instance.isNativeTransportRunning())); } } + + @Test + public void testBinaryReflectsRpcReadiness() throws Throwable + { + try (Cluster cluster = builder().withNodes(1) + .withConfig(config -> config.with(NETWORK, GOSSIP, NATIVE_PROTOCOL) + .set("start_native_transport", "false")) + .start()) + { + IInvokableInstance i = cluster.get(1); + + // rpc is false when native transport is not enabled + assertFalse(i.callOnInstance((IIsolatedExecutor.SerializableCallable) () -> StorageService.instance.isNativeTransportRunning())); + assertFalse(i.callOnInstance((IIsolatedExecutor.SerializableCallable) () -> StorageService.instance.isRpcReady(FBUtilities.getBroadcastAddress()))); + + // but if we enable it, e.g. by nodetool enablebinary, rpc will be enabled + i.runOnInstance((IIsolatedExecutor.SerializableRunnable) () -> StorageService.instance.startNativeTransport()); + assertTrue(i.callOnInstance((IIsolatedExecutor.SerializableCallable) () -> StorageService.instance.isRpcReady(FBUtilities.getBroadcastAddress()))); + + // by calling e.g. nodetool disablebinary, rpc will be set to false again + i.runOnInstance((IIsolatedExecutor.SerializableRunnable) () -> StorageService.instance.stopNativeTransport()); + assertFalse(i.callOnInstance((IIsolatedExecutor.SerializableCallable) () -> StorageService.instance.isRpcReady(FBUtilities.getBroadcastAddress()))); + } + } } \ No newline at end of file