/* * 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.solr.common.cloud; import java.util.Locale; import java.util.Map; import java.util.Set; import org.noggit.JSONUtil; import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP; import static org.apache.solr.common.cloud.ZkStateReader.CORE_NAME_PROP; public class Replica extends ZkNodeProps { /** * The replica's state. In general, if the node the replica is hosted on is * not under {@code /live_nodes} in ZK, the replica's state should be * discarded. */ public enum State { /** * The replica is ready to receive updates and queries. * <p> * <b>NOTE</b>: when the node the replica is hosted on crashes, the * replica's state may remain ACTIVE in ZK. To determine if the replica is * truly active, you must also verify that its {@link Replica#getNodeName() * node} is under {@code /live_nodes} in ZK (or use * {@link ClusterState#liveNodesContain(String)}). * </p> */ ACTIVE, /** * The first state before {@link State#RECOVERING}. A node in this state * should be actively trying to move to {@link State#RECOVERING}. * <p> * <b>NOTE</b>: a replica's state may appear DOWN in ZK also when the node * it's hosted on gracefully shuts down. This is a best effort though, and * should not be relied on. * </p> */ DOWN, /** * The node is recovering from the leader. This might involve peer-sync, * full replication or finding out things are already in sync. */ RECOVERING, /** * Recovery attempts have not worked, something is not right. * <p> * <b>NOTE</b>: This state doesn't matter if the node is not part of * {@code /live_nodes} in ZK; in that case the node is not part of the * cluster and it's state should be discarded. * </p> */ RECOVERY_FAILED; @Override public String toString() { return super.toString().toLowerCase(Locale.ROOT); } /** Converts the state string to a State instance. */ public static State getState(String stateStr) { return stateStr == null ? null : State.valueOf(stateStr.toUpperCase(Locale.ROOT)); } } private final String name; private final String nodeName; private final State state; public Replica(String name, Map<String,Object> propMap) { super(propMap); this.name = name; this.nodeName = (String) propMap.get(ZkStateReader.NODE_NAME_PROP); if (propMap.get(ZkStateReader.STATE_PROP) != null) { this.state = State.getState((String) propMap.get(ZkStateReader.STATE_PROP)); } else { this.state = State.ACTIVE; //Default to ACTIVE propMap.put(ZkStateReader.STATE_PROP, state.toString()); } } public String getName() { return name; } public String getCoreUrl() { return ZkCoreNodeProps.getCoreUrl(getStr(BASE_URL_PROP), getStr(CORE_NAME_PROP)); } public String getBaseUrl(){ return getStr(ZkStateReader.BASE_URL_PROP); } public String getCoreName() { return getStr(CORE_NAME_PROP); } /** The name of the node this replica resides on */ public String getNodeName() { return nodeName; } /** Returns the {@link State} of this replica. */ public State getState() { return state; } public boolean isActive(Set<String> liveNodes) { return liveNodes.contains(this.nodeName) && this.state == State.ACTIVE; } @Override public String toString() { return name + ':' + JSONUtil.toJSON(propMap, -1); // small enough, keep it on one line (i.e. no indent) } }