Returns a client to communicate with a Region Server. Note that this method is synchronized, so only one client at a time can be created. In practice this shouldn't be a problem as this method is not expected to be frequently called. @param host The normalized IP address of the
(final String host, final int port)
| 3734 | * @return A client for this region server. |
| 3735 | */ |
| 3736 | private RegionClient newClient(final String host, final int port) { |
| 3737 | // This big synchronized block is required because using a |
| 3738 | // ConcurrentHashMap wouldn't be sufficient. We could still have 2 |
| 3739 | // threads attempt to create the same client at the same time, and they |
| 3740 | // could both test the map at the same time and create 2 instances. |
| 3741 | final String hostport = host + ':' + port; |
| 3742 | |
| 3743 | RegionClient client; |
| 3744 | SocketChannel chan = null; |
| 3745 | synchronized (ip2client) { |
| 3746 | client = ip2client.get(hostport); |
| 3747 | if (client != null && client.isAlive()) { |
| 3748 | return client; |
| 3749 | } |
| 3750 | |
| 3751 | // We don't use Netty's ClientBootstrap class because it makes it |
| 3752 | // unnecessarily complicated to have control over which ChannelPipeline |
| 3753 | // exactly will be given to the channel. It's over-designed. |
| 3754 | final RegionClientPipeline pipeline = new RegionClientPipeline(); |
| 3755 | client = pipeline.init(); |
| 3756 | chan = channel_factory.newChannel(pipeline); |
| 3757 | ip2client.put(hostport, client); // This is guaranteed to return null. |
| 3758 | } |
| 3759 | client2regions.put(client, new ArrayList<RegionInfo>()); |
| 3760 | num_connections_created.increment(); |
| 3761 | // Configure and connect the channel without locking ip2client. |
| 3762 | final SocketChannelConfig socket_config = chan.getConfig(); |
| 3763 | socket_config.setConnectTimeoutMillis( |
| 3764 | config.getInt("hbase.ipc.client.socket.timeout.connect")); |
| 3765 | socket_config.setTcpNoDelay( |
| 3766 | config.getBoolean("hbase.ipc.client.tcpnodelay")); |
| 3767 | // Unfortunately there is no way to override the keep-alive timeout in |
| 3768 | // Java since the JRE doesn't expose any way to call setsockopt() with |
| 3769 | // TCP_KEEPIDLE. And of course the default timeout is >2h. Sigh. |
| 3770 | socket_config.setKeepAlive( |
| 3771 | config.getBoolean("hbase.ipc.client.tcpkeepalive")); |
| 3772 | |
| 3773 | // socket overrides using system defaults instead of setting them in a conf |
| 3774 | if (config.hasProperty("hbase.ipc.client.socket.write.high_watermark")) { |
| 3775 | ((NioChannelConfig)config).setWriteBufferHighWaterMark( |
| 3776 | config.getInt("hbase.ipc.client.socket.write.high_watermark")); |
| 3777 | } |
| 3778 | if (config.hasProperty("hbase.ipc.client.socket.write.low_watermark")) { |
| 3779 | ((NioChannelConfig)config).setWriteBufferLowWaterMark( |
| 3780 | config.getInt("hbase.ipc.client.socket.write.low_watermark")); |
| 3781 | } |
| 3782 | if (config.hasProperty("hbase.ipc.client.socket.sendBufferSize")) { |
| 3783 | socket_config.setOption("sendBufferSize", |
| 3784 | config.getInt("hbase.ipc.client.socket.sendBufferSize")); |
| 3785 | } |
| 3786 | if (config.hasProperty("hbase.ipc.client.socket.receiveBufferSize")) { |
| 3787 | socket_config.setOption("receiveBufferSize", |
| 3788 | config.getInt("hbase.ipc.client.socket.receiveBufferSize")); |
| 3789 | } |
| 3790 | |
| 3791 | chan.connect(new InetSocketAddress(host, port)); // Won't block. |
| 3792 | return client; |
| 3793 | } |
no test coverage detected