View Javadoc

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