View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.client;
20  
21  import java.io.IOException;
22  import java.lang.management.ManagementFactory;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.util.Addressing;
28  import org.apache.hadoop.hbase.util.Bytes;
29  
30  /**
31   * The class that is able to determine some unique strings for the client,
32   * such as an IP address, PID, and composite deterministic ID.
33   */
34  @InterfaceAudience.Private
35  class ClientIdGenerator {
36    private static final Log LOG = LogFactory.getLog(ClientIdGenerator.class);
37  
38    /**
39     * @return a unique ID incorporating IP address, PID, TID and timer. Might be an overkill...
40     * Note though that new UUID in java by default is just a random number.
41     */
42    public static byte[] generateClientId() {
43      byte[] selfBytes = getIpAddressBytes();
44      Long pid = getPid();
45      long tid = Thread.currentThread().getId();
46      long ts = System.currentTimeMillis();
47  
48      byte[] id = new byte[selfBytes.length + ((pid != null ? 1 : 0) + 2) * Bytes.SIZEOF_LONG];
49      int offset = Bytes.putBytes(id, 0, selfBytes, 0, selfBytes.length);
50      if (pid != null) {
51        offset = Bytes.putLong(id, offset, pid);
52      }
53      offset = Bytes.putLong(id, offset, tid);
54      offset = Bytes.putLong(id, offset, ts);
55      assert offset == id.length;
56      return id;
57    }
58  
59    /**
60     * @return PID of the current process, if it can be extracted from JVM name, or null.
61     */
62    public static Long getPid() {
63      String name = ManagementFactory.getRuntimeMXBean().getName();
64      String[] nameParts = name.split("@");
65      if (nameParts.length == 2) { // 12345@somewhere
66        try {
67          return Long.parseLong(nameParts[0]);
68        } catch (NumberFormatException ex) {
69          LOG.warn("Failed to get PID from [" + name + "]", ex);
70        }
71      } else {
72        LOG.warn("Don't know how to get PID from [" + name + "]");
73      }
74      return null;
75    }
76  
77    /**
78     * @return Some IPv4/IPv6 address available on the current machine that is up, not virtual
79     *         and not a loopback address. Empty array if none can be found or error occured.
80     */
81    public static byte[] getIpAddressBytes() {
82      try {
83        return Addressing.getIpAddress().getAddress();
84      } catch (IOException ex) {
85        LOG.warn("Failed to get IP address bytes", ex);
86      }
87      return new byte[0];
88    }
89  }