Merge branch 'cassandra-4.0' into cassandra-4.1

This commit is contained in:
David Capwell 2023-10-10 14:05:19 -07:00
commit 1920571861
4 changed files with 113 additions and 1 deletions

View File

@ -5,6 +5,7 @@
* Allow empty keystore_password in encryption_options (CASSANDRA-18778)
* Skip ColumnFamilyStore#topPartitions initialization when client or tool mode (CASSANDRA-18697)
Merged from 4.0:
* Gossip NPE due to shutdown event corrupting empty statuses (CASSANDRA-18913)
* Fix closing iterator in SecondaryIndexBuilder (CASSANDRA-18361)
* Update hdrhistogram to 2.1.12 (CASSANDRA-18893)
* Improve performance of compactions when table does not have an index (CASSANDRA-18773)

View File

@ -196,6 +196,11 @@ public class EndpointState
isAlive = false;
}
public boolean isStateEmpty()
{
return applicationState.get().isEmpty();
}
/**
* @return true if {@link HeartBeatState#isEmpty()} is true and no STATUS application state exists
*/

View File

@ -590,7 +590,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean
{
checkProperThreadForStateMutation();
EndpointState epState = endpointStateMap.get(endpoint);
if (epState == null)
if (epState == null || epState.isStateEmpty())
return;
VersionedValue shutdown = StorageService.instance.valueFactory.shutdown(true);
epState.addApplicationState(ApplicationState.STATUS_WITH_PORT, shutdown);

View File

@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.distributed.test.gossip;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.junit.Test;
import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.api.Feature;
import org.apache.cassandra.distributed.api.IInvokableInstance;
import org.apache.cassandra.distributed.api.TokenSupplier;
import org.apache.cassandra.distributed.shared.ClusterUtils;
import org.apache.cassandra.distributed.test.TestBaseImpl;
import org.apache.cassandra.net.Verb;
public class GossipShutdownTest extends TestBaseImpl
{
@Test
public void emptyStateAndShutdownEvent() throws IOException
{
try (Cluster cluster = builder()
.withNodes(2)
.withConfig(c -> c.with(Feature.values()))
.start())
{
IInvokableInstance n1 = cluster.get(1);
IInvokableInstance n2 = cluster.get(2);
ClusterUtils.awaitRingJoin(n1, n2);
ClusterUtils.awaitRingJoin(n2, n1);
ClusterUtils.stopUnchecked(n1);
// make sure we don't see gossip events, but do allow gossip shutdown
cluster.filters().verbs(Verb.GOSSIP_DIGEST_ACK.id,
Verb.GOSSIP_DIGEST_ACK.id,
Verb.GOSSIP_DIGEST_ACK2.id)
.to(1)
.drop();
n1.startup();
n2.nodetoolResult("disablegossip").asserts().success();
}
}
@Test
public void emptyStateAndHostJoin() throws IOException, InterruptedException
{
try (Cluster cluster = builder()
.withNodes(2)
.withTokenSupplier(TokenSupplier.evenlyDistributedTokens(3))
.withConfig(c -> c.with(Feature.values()))
.start())
{
IInvokableInstance n1 = cluster.get(1);
IInvokableInstance n2 = cluster.get(2);
ClusterUtils.awaitRingJoin(n1, n2);
ClusterUtils.awaitRingJoin(n2, n1);
ClusterUtils.stopUnchecked(n1);
// make sure we don't see gossip events, but do allow gossip shutdown
cluster.filters().verbs(Verb.GOSSIP_DIGEST_ACK.id,
Verb.GOSSIP_DIGEST_ACK.id,
Verb.GOSSIP_DIGEST_ACK2.id)
.to(1)
.drop();
n1.startup();
CountDownLatch latch = new CountDownLatch(1);
cluster.filters().verbs(Verb.GOSSIP_SHUTDOWN.id).messagesMatching((from, to, iMessage) -> {
latch.countDown();
return false;
}).drop();
n2.nodetoolResult("disablegossip").asserts().success();
latch.await();
cluster.filters().reset();
IInvokableInstance n3 = ClusterUtils.addInstance(cluster, n1.config(), c -> {});
n3.startup();
}
}
}