View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.zookeeper;
19  
20  import java.io.IOException;
21  import java.util.List;
22  import java.util.NavigableSet;
23  import java.util.TreeSet;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.hbase.Abortable;
29  import org.apache.hadoop.hbase.ServerName;
30  import org.apache.hadoop.hbase.master.ServerListener;
31  import org.apache.hadoop.hbase.master.ServerManager;
32  import org.apache.zookeeper.KeeperException;
33  
34  /**
35   * Tracks the list of draining region servers via ZK.
36   *
37   * <p>This class is responsible for watching for changes to the draining
38   * servers list.  It handles adds/deletes in the draining RS list and
39   * watches each node.
40   *
41   * <p>If an RS gets deleted from draining list, we call
42   * {@link ServerManager#removeServerFromDrainList(ServerName)}
43   *
44   * <p>If an RS gets added to the draining list, we add a watcher to it and call
45   * {@link ServerManager#addServerToDrainList(ServerName)}
46   *
47   */
48  @InterfaceAudience.Private
49  public class DrainingServerTracker extends ZooKeeperListener {
50    private static final Log LOG = LogFactory.getLog(DrainingServerTracker.class);
51  
52    private ServerManager serverManager;
53    private final NavigableSet<ServerName> drainingServers = new TreeSet<ServerName>();
54    private Abortable abortable;
55  
56    public DrainingServerTracker(ZooKeeperWatcher watcher,
57        Abortable abortable, ServerManager serverManager) {
58      super(watcher);
59      this.abortable = abortable;
60      this.serverManager = serverManager;
61    }
62  
63    /**
64     * Starts the tracking of draining RegionServers.
65     *
66     * <p>All Draining RSs will be tracked after this method is called.
67     *
68     * @throws KeeperException
69     */
70    public void start() throws KeeperException, IOException {
71      watcher.registerListener(this);
72      // Add a ServerListener to check if a server is draining when it's added.
73      serverManager.registerListener(
74          new ServerListener() {
75  
76            @Override
77            public void serverAdded(ServerName sn) {
78              if (drainingServers.contains(sn)){
79                serverManager.addServerToDrainList(sn);
80              }
81            }
82  
83            @Override
84            public void serverRemoved(ServerName serverName) {
85              // no-op
86            }
87          }
88      );
89      List<String> servers =
90        ZKUtil.listChildrenAndWatchThem(watcher, watcher.drainingZNode);
91      add(servers);
92    }
93  
94    private void add(final List<String> servers) throws IOException {
95      synchronized(this.drainingServers) {
96        this.drainingServers.clear();
97        for (String n: servers) {
98          final ServerName sn = ServerName.valueOf(ZKUtil.getNodeName(n));
99          this.drainingServers.add(sn);
100         this.serverManager.addServerToDrainList(sn);
101         LOG.info("Draining RS node created, adding to list [" +
102             sn + "]");
103 
104       }
105     }
106   }
107 
108   private void remove(final ServerName sn) {
109     synchronized(this.drainingServers) {
110       this.drainingServers.remove(sn);
111       this.serverManager.removeServerFromDrainList(sn);
112     }
113   }
114 
115   @Override
116   public void nodeDeleted(final String path) {
117     if(path.startsWith(watcher.drainingZNode)) {
118       final ServerName sn = ServerName.valueOf(ZKUtil.getNodeName(path));
119       LOG.info("Draining RS node deleted, removing from list [" +
120           sn + "]");
121       remove(sn);
122     }
123   }
124 
125   @Override
126   public void nodeChildrenChanged(final String path) {
127     if(path.equals(watcher.drainingZNode)) {
128       try {
129         final List<String> newNodes =
130           ZKUtil.listChildrenAndWatchThem(watcher, watcher.drainingZNode);
131         add(newNodes);
132       } catch (KeeperException e) {
133         abortable.abort("Unexpected zk exception getting RS nodes", e);
134       } catch (IOException e) {
135         abortable.abort("Unexpected zk exception getting RS nodes", e);
136       }
137     }
138   }
139 }