001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master; 019 020import java.io.IOException; 021import java.util.List; 022import java.util.NavigableSet; 023import java.util.TreeSet; 024 025import org.apache.hadoop.hbase.zookeeper.ZKListener; 026import org.apache.hadoop.hbase.zookeeper.ZKUtil; 027import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 028import org.apache.yetus.audience.InterfaceAudience; 029import org.apache.hadoop.hbase.Abortable; 030import org.apache.hadoop.hbase.ServerName; 031import org.apache.zookeeper.KeeperException; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * Tracks the list of draining region servers via ZK. 037 * 038 * <p>This class is responsible for watching for changes to the draining 039 * servers list. It handles adds/deletes in the draining RS list and 040 * watches each node. 041 * 042 * <p>If an RS gets deleted from draining list, we call 043 * {@link ServerManager#removeServerFromDrainList(ServerName)} 044 * 045 * <p>If an RS gets added to the draining list, we add a watcher to it and call 046 * {@link ServerManager#addServerToDrainList(ServerName)} 047 * 048 * <p>This class is deprecated in 2.0 because decommission/draining API goes through 049 * master in 2.0. Can remove this class in 3.0. 050 * 051 */ 052@InterfaceAudience.Private 053public class DrainingServerTracker extends ZKListener { 054 private static final Logger LOG = LoggerFactory.getLogger(DrainingServerTracker.class); 055 056 private ServerManager serverManager; 057 private final NavigableSet<ServerName> drainingServers = new TreeSet<>(); 058 private Abortable abortable; 059 060 public DrainingServerTracker(ZKWatcher watcher, 061 Abortable abortable, ServerManager serverManager) { 062 super(watcher); 063 this.abortable = abortable; 064 this.serverManager = serverManager; 065 } 066 067 /** 068 * Starts the tracking of draining RegionServers. 069 * 070 * <p>All Draining RSs will be tracked after this method is called. 071 * 072 * @throws KeeperException 073 */ 074 public void start() throws KeeperException, IOException { 075 watcher.registerListener(this); 076 // Add a ServerListener to check if a server is draining when it's added. 077 serverManager.registerListener(new ServerListener() { 078 @Override 079 public void serverAdded(ServerName sn) { 080 if (drainingServers.contains(sn)){ 081 serverManager.addServerToDrainList(sn); 082 } 083 } 084 }); 085 List<String> servers = 086 ZKUtil.listChildrenAndWatchThem(watcher, watcher.getZNodePaths().drainingZNode); 087 add(servers); 088 } 089 090 private void add(final List<String> servers) throws IOException { 091 synchronized(this.drainingServers) { 092 this.drainingServers.clear(); 093 for (String n: servers) { 094 final ServerName sn = ServerName.valueOf(ZKUtil.getNodeName(n)); 095 this.drainingServers.add(sn); 096 this.serverManager.addServerToDrainList(sn); 097 LOG.info("Draining RS node created, adding to list [" + 098 sn + "]"); 099 100 } 101 } 102 } 103 104 private void remove(final ServerName sn) { 105 synchronized(this.drainingServers) { 106 this.drainingServers.remove(sn); 107 this.serverManager.removeServerFromDrainList(sn); 108 } 109 } 110 111 @Override 112 public void nodeDeleted(final String path) { 113 if(path.startsWith(watcher.getZNodePaths().drainingZNode)) { 114 final ServerName sn = ServerName.valueOf(ZKUtil.getNodeName(path)); 115 LOG.info("Draining RS node deleted, removing from list [" + 116 sn + "]"); 117 remove(sn); 118 } 119 } 120 121 @Override 122 public void nodeChildrenChanged(final String path) { 123 if(path.equals(watcher.getZNodePaths().drainingZNode)) { 124 try { 125 final List<String> newNodes = 126 ZKUtil.listChildrenAndWatchThem(watcher, watcher.getZNodePaths().drainingZNode); 127 add(newNodes); 128 } catch (KeeperException e) { 129 abortable.abort("Unexpected zk exception getting RS nodes", e); 130 } catch (IOException e) { 131 abortable.abort("Unexpected zk exception getting RS nodes", e); 132 } 133 } 134 } 135}