org.apache.solr.cloud.NodeStateWatcher.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.solr.cloud.NodeStateWatcher.java

Source

package org.apache.solr.cloud;

/**
 * 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.
 */

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.solr.common.cloud.CoreState;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Watcher for node state changes.
 */
public class NodeStateWatcher implements Watcher {

    private static Logger log = LoggerFactory.getLogger(NodeStateWatcher.class);

    public static interface NodeStateChangeListener {
        void coreChanged(String nodeName, Set<CoreState> states) throws KeeperException, InterruptedException;

        void coreDeleted(String nodeName, Collection<CoreState> states)
                throws KeeperException, InterruptedException;
    }

    private final SolrZkClient zkClient;
    private final String path;
    private volatile Set<CoreState> currentState = new HashSet<CoreState>();
    private final NodeStateChangeListener listener;
    private final String nodeName;

    public Set<CoreState> getCurrentState() {
        return currentState;
    }

    public NodeStateWatcher(SolrZkClient zkClient, String nodeName, String path, NodeStateChangeListener listener)
            throws KeeperException, InterruptedException {
        this.nodeName = nodeName;
        this.zkClient = zkClient;
        this.path = path;
        this.listener = listener;
        processStateChange();
    }

    @Override
    public void process(WatchedEvent event) {
        try {
            processStateChange();
        } catch (InterruptedException e) {
            // Restore the interrupted status
            Thread.currentThread().interrupt();
            return;
        } catch (Exception e) {
            log.warn("Error processing state change", e);
        }
    }

    private void processStateChange() throws KeeperException, InterruptedException {
        byte[] data = zkClient.getData(path, this, null, true);

        if (data != null) {
            CoreState[] states = CoreState.load(data);
            List<CoreState> stateList = Arrays.asList(states);
            HashSet<CoreState> modifiedCores = new HashSet<CoreState>();
            modifiedCores.addAll(stateList);
            modifiedCores.removeAll(currentState);

            HashSet<CoreState> newState = new HashSet<CoreState>();
            newState.addAll(stateList);

            HashMap<String, CoreState> lookup = new HashMap<String, CoreState>();
            for (CoreState state : states) {
                lookup.put(state.getCoreName(), state);
            }

            //check for status change
            for (CoreState state : currentState) {
                if (lookup.containsKey(state.getCoreName())) {
                    if (!state.getProperties().equals(lookup.get(state.getCoreName()).getProperties())) {
                        modifiedCores.add(lookup.get(state.getCoreName()));
                    }
                }
            }

            HashMap<String, CoreState> deletedCores = new HashMap<String, CoreState>();
            for (CoreState state : currentState) {
                deletedCores.put(state.getCoreNodeName(), state);
            }

            for (CoreState state : stateList) {
                deletedCores.remove(state.getCoreNodeName());
            }

            if (deletedCores.size() > 0) {
                listener.coreDeleted(nodeName, deletedCores.values());
            }

            currentState = Collections.unmodifiableSet(newState);

            if (modifiedCores.size() > 0) {
                try {
                    listener.coreChanged(nodeName, Collections.unmodifiableSet(modifiedCores));
                } catch (KeeperException e) {
                    log.warn("Could not talk to ZK", e);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("Could not talk to ZK", e);
                }
            }

        } else {
            // ignore null state
        }
    }
}