/*
* Copyright (c) 2017 Strapdata (http://www.strapdata.com)
* Contains some code from Elasticsearch (http://www.elastic.co)
*
* Licensed 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.elassandra.cluster.routing;
import java.net.InetAddress;
import java.util.BitSet;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import org.apache.cassandra.dht.Murmur3Partitioner.LongToken;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.routing.ShardRoutingState;
import org.elasticsearch.common.transport.TransportAddress;
import com.carrotsearch.hppc.cursors.ObjectCursor;
/**
* return primary ranges of all nodes (and some replica for unreachable nodes).
*
* @author vroyer
*
*/
public class PrimaryFirstSearchStrategy extends AbstractSearchStrategy {
public Router newRouter(final String index, final String ksName, final Map<UUID, ShardRoutingState> shardStates, final ClusterState clusterState) {
return new PrimaryFirstRouter(index, ksName, shardStates, clusterState);
}
public class PrimaryFirstRouter extends Router {
Route route;
public PrimaryFirstRouter(final String index, final String ksName, final Map<UUID, ShardRoutingState> shardStates, final ClusterState clusterState) {
super(index, ksName, shardStates, clusterState, false);
if (!StorageService.instance.isJoined() || !Keyspace.isInitialized()) {
// temporary fake routing table in order to start local shards before cassandra services.
BitSet singletonBitSet = new BitSet(1);
singletonBitSet.set(0, true);
this.greenShards.put(localNode, singletonBitSet);
this.route = new Router.Route() {
@Override
public Map<DiscoveryNode, BitSet> selectedShards() {
return greenShards;
}
};
return;
}
if (logger.isTraceEnabled())
logger.trace("index={} keyspace={} greenShards={} yellowShards={} redShards={}", index, ksName, greenShards, yellowShards, redShards);
this.route = new Router.Route() {
@Override
public Map<DiscoveryNode, BitSet> selectedShards() {
return greenShards;
}
};
}
private void clearReplicaRange(InetAddress endpoint, int tokenIndex, Token token, ClusterState clusterState) {
for(DiscoveryNode node : this.tokenToNodes.get(token)) {
if (this.greenShards.get(node) != null) {
if (logger.isTraceEnabled())
logger.trace("clear bit={} for token={} node={}", tokenIndex, token, node);
this.greenShards.get(node).set(tokenIndex, false);
} else {
if (logger.isTraceEnabled())
logger.trace("uuid={} for replica={} node found", node.uuid(), node.getInetAddress());
}
}
if (logger.isTraceEnabled())
logger.trace("index={} keyspace={} greenShards={} yellowShards={} redShards={}", index, ksName, greenShards, yellowShards, redShards);
this.route = new Router.Route() {
@Override
public Map<DiscoveryNode, BitSet> selectedShards() {
return greenShards;
}
};
}
@Override
public Route newRoute(String preference, TransportAddress src) {
return this.route;
}
}
}