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;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  import java.net.InetSocketAddress;
26  import java.util.Set;
27  
28  import org.apache.hadoop.hbase.regionserver.HRegionServer;
29  import org.apache.hadoop.io.Writable;
30  import org.apache.hadoop.io.WritableComparable;
31  
32  
33  /**
34   * HServerInfo is meta info about an {@link HRegionServer}.  It is the token
35   * by which a master distingushes a particular regionserver from the rest.
36   * It holds hostname, ports, regionserver startcode, and load.  Each server has
37   * a <code>servername</code> where servername is made up of a concatenation of
38   * hostname, port, and regionserver startcode.  This servername is used in
39   * various places identifying this regionserver.  Its even used as part of
40   * a pathname in the filesystem.  As part of the initialization,
41   * master will pass the regionserver the address that it knows this regionserver
42   * by.  In subsequent communications, the regionserver will pass a HServerInfo
43   * with the master-supplied address.
44   */
45  public class HServerInfo implements WritableComparable<HServerInfo> {
46    /*
47     * This character is used as separator between server hostname and port and
48     * its startcode. Servername is formatted as
49     * <code>&lt;hostname> '{@ink #SERVERNAME_SEPARATOR"}' &lt;port> '{@ink #SERVERNAME_SEPARATOR"}' &lt;startcode></code>.
50     */
51    private static final String SERVERNAME_SEPARATOR = ",";
52  
53    private HServerAddress serverAddress;
54    private long startCode;
55    private HServerLoad load;
56    private int infoPort;
57    // Servername is made of hostname, port and startcode.
58    private String serverName = null;
59    // Hostname of the regionserver.
60    private String hostname;
61    private String cachedHostnamePort = null;
62  
63    public HServerInfo() {
64      this(new HServerAddress(), 0, HConstants.DEFAULT_REGIONSERVER_INFOPORT,
65        "default name");
66    }
67  
68    /**
69     * Constructor that creates a HServerInfo with a generated startcode and an
70     * empty load.
71     * @param serverAddress An {@link InetSocketAddress} encased in a {@link Writable}
72     * @param infoPort Port the webui runs on.
73     * @param hostname Server hostname.
74     */
75    public HServerInfo(HServerAddress serverAddress, final int infoPort,
76        final String hostname) {
77      this(serverAddress, System.currentTimeMillis(), infoPort, hostname);
78    }
79  
80    public HServerInfo(HServerAddress serverAddress, long startCode,
81        final int infoPort, String hostname) {
82      this.serverAddress = serverAddress;
83      this.startCode = startCode;
84      this.load = new HServerLoad();
85      this.infoPort = infoPort;
86      this.hostname = hostname;
87    }
88  
89    /**
90     * Copy-constructor
91     * @param other
92     */
93    public HServerInfo(HServerInfo other) {
94      this.serverAddress = new HServerAddress(other.getServerAddress());
95      this.startCode = other.getStartCode();
96      this.load = other.getLoad();
97      this.infoPort = other.getInfoPort();
98      this.hostname = other.hostname;
99    }
100 
101   public HServerLoad getLoad() {
102     return load;
103   }
104 
105   public void setLoad(HServerLoad load) {
106     this.load = load;
107   }
108 
109   public synchronized HServerAddress getServerAddress() {
110     return new HServerAddress(serverAddress);
111   }
112 
113   public synchronized void setServerAddress(HServerAddress serverAddress) {
114     this.serverAddress = serverAddress;
115     this.serverName = null;
116   }
117 
118   public synchronized long getStartCode() {
119     return startCode;
120   }
121 
122   public int getInfoPort() {
123     return this.infoPort;
124   }
125 
126   public String getHostname() {
127     return this.hostname;
128   }
129 
130   /**
131    * @return The hostname and port concatenated with a ':' as separator.
132    */
133   public synchronized String getHostnamePort() {
134     if (this.cachedHostnamePort == null) {
135       this.cachedHostnamePort = getHostnamePort(this.hostname, this.serverAddress.getPort());
136     }
137     return this.cachedHostnamePort;
138   }
139 
140   /**
141    * @param hostname
142    * @param port
143    * @return The hostname and port concatenated with a ':' as separator.
144    */
145   public static String getHostnamePort(final String hostname, final int port) {
146     return hostname + ":" + port;
147   }
148 
149   /**
150    * @return Server name made of the concatenation of hostname, port and
151    * startcode formatted as <code>&lt;hostname> ',' &lt;port> ',' &lt;startcode></code>
152    */
153   public synchronized String getServerName() {
154     if (this.serverName == null) {
155       this.serverName = getServerName(this.hostname,
156         this.serverAddress.getPort(), this.startCode);
157     }
158     return this.serverName;
159   }
160 
161   public static synchronized String getServerName(final String hostAndPort,
162       final long startcode) {
163     int index = hostAndPort.indexOf(":");
164     if (index <= 0) throw new IllegalArgumentException("Expected <hostname> ':' <port>");
165     return getServerName(hostAndPort.substring(0, index),
166       Integer.parseInt(hostAndPort.substring(index + 1)), startcode);
167   }
168 
169   /**
170    * @param address Server address
171    * @param startCode Server startcode
172    * @return Server name made of the concatenation of hostname, port and
173    * startcode formatted as <code>&lt;hostname> ',' &lt;port> ',' &lt;startcode></code>
174    */
175   public static String getServerName(HServerAddress address, long startCode) {
176     return getServerName(address.getHostname(), address.getPort(), startCode);
177   }
178 
179   /*
180    * @param hostName
181    * @param port
182    * @param startCode
183    * @return Server name made of the concatenation of hostname, port and
184    * startcode formatted as <code>&lt;hostname> ',' &lt;port> ',' &lt;startcode></code>
185    */
186   public static String getServerName(String hostName, int port, long startCode) {
187     StringBuilder name = new StringBuilder(hostName);
188     name.append(SERVERNAME_SEPARATOR);
189     name.append(port);
190     name.append(SERVERNAME_SEPARATOR);
191     name.append(startCode);
192     return name.toString();
193   }
194 
195   /**
196    * @return ServerName and load concatenated.
197    * @see #getServerName()
198    * @see #getLoad()
199    */
200   @Override
201   public String toString() {
202     return "serverName=" + getServerName() +
203       ", load=(" + this.load.toString() + ")";
204   }
205 
206   @Override
207   public boolean equals(Object obj) {
208     if (this == obj) {
209       return true;
210     }
211     if (obj == null) {
212       return false;
213     }
214     if (getClass() != obj.getClass()) {
215       return false;
216     }
217     return compareTo((HServerInfo)obj) == 0;
218   }
219 
220   @Override
221   public int hashCode() {
222     return this.getServerName().hashCode();
223   }
224 
225   public void readFields(DataInput in) throws IOException {
226     this.serverAddress.readFields(in);
227     this.startCode = in.readLong();
228     this.load.readFields(in);
229     this.infoPort = in.readInt();
230     this.hostname = in.readUTF();
231   }
232 
233   public void write(DataOutput out) throws IOException {
234     this.serverAddress.write(out);
235     out.writeLong(this.startCode);
236     this.load.write(out);
237     out.writeInt(this.infoPort);
238     out.writeUTF(hostname);
239   }
240 
241   public int compareTo(HServerInfo o) {
242     return this.getServerName().compareTo(o.getServerName());
243   }
244 
245   /**
246    * Utility method that does a find of a servername or a hostandport combination
247    * in the passed Set.
248    * @param servers Set of server names
249    * @param serverName Name to look for
250    * @param hostAndPortOnly If <code>serverName</code> is a
251    * <code>hostname ':' port</code>
252    * or <code>hostname , port , startcode</code>.
253    * @return True if <code>serverName</code> found in <code>servers</code>
254    */
255   public static boolean isServer(final Set<String> servers,
256       final String serverName, final boolean hostAndPortOnly) {
257     if (!hostAndPortOnly) return servers.contains(serverName);
258     String serverNameColonReplaced =
259       serverName.replaceFirst(":", SERVERNAME_SEPARATOR);
260     for (String hostPortStartCode: servers) {
261       int index = hostPortStartCode.lastIndexOf(SERVERNAME_SEPARATOR);
262       String hostPortStrippedOfStartCode = hostPortStartCode.substring(0, index);
263       if (hostPortStrippedOfStartCode.equals(serverNameColonReplaced)) return true;
264     }
265     return false;
266   }
267 }