/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.usergrid.persistence.index.impl; import java.net.InetAddress; import java.net.UnknownHostException; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.lang.RandomStringUtils; import org.apache.usergrid.persistence.index.IndexFig; import com.google.inject.Inject; import com.google.inject.Singleton; /** * Provides access to ElasticSearch client and, optionally, embedded ElasticSearch for testing. */ @Singleton public class EsProvider { private static final Logger logger = LoggerFactory.getLogger( EsProvider.class ); private final IndexFig indexFig; private static Client client; public static String LOCAL_ES_PORT_PROPNAME = "EMBEDDED_ES_PORT"; @Inject public EsProvider( IndexFig fig ) { this.indexFig = fig; } /** * Get the client instnace */ public Client getClient() { if ( client == null ) { //synchronize on creating the client so we don't create too many createClient(); } return client; } /** * Reset the client instance */ public synchronized void releaseClient() { //reset our static variables if ( client != null ) { try { client.close(); } //if we fail for any reason, null it so the next request creates a new client finally { client = null; } } } /** * Create our client */ private synchronized void createClient() { if ( client != null ) { return; } final ClientType clientType = ClientType.valueOf( indexFig.getClientType() ); switch ( clientType ) { case NODE: client = createNodeClient(); break; case TRANSPORT: client = createTransportClient(); break; default: throw new RuntimeException( "Only client types of NODE and TRANSPORT are supported" ); } } /** * Create the transport client * @return */ private Client createTransportClient() { final String clusterName = indexFig.getClusterName(); final int port = indexFig.getPort(); ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder().put( "cluster.name", clusterName ) .put( "client.transport.sniff", true ); String nodeName = indexFig.getNodeName(); if ( "default".equals( nodeName ) ) { // no nodeName was specified, use hostname try { nodeName = InetAddress.getLocalHost().getHostName(); } catch ( UnknownHostException ex ) { nodeName = "client-" + RandomStringUtils.randomAlphabetic( 8 ); logger.warn( "Couldn't get hostname to use as ES node name, using {}", nodeName ); } } settings.put( "node.name", nodeName ); TransportClient transportClient = new TransportClient( settings.build() ); // we will connect to ES on all configured hosts for ( String host : indexFig.getHosts().split( "," ) ) { transportClient.addTransportAddress( new InetSocketTransportAddress( host, port ) ); } return transportClient; } /** * Create a node client * @return */ public Client createNodeClient() { // we will connect to ES on all configured hosts final String clusterName = indexFig.getClusterName(); final String nodeName = indexFig.getNodeName(); final int port = indexFig.getPort(); /** * Create our hosts */ final StringBuffer hosts = new StringBuffer(); for ( String host : indexFig.getHosts().split( "," ) ) { hosts.append( host ).append( ":" ).append( port ).append( "," ); } //remove the last comma hosts.deleteCharAt( hosts.length() - 1 ); final String hostString = hosts.toString(); Settings settings = ImmutableSettings.settingsBuilder() .put( "cluster.name", clusterName ) // this assumes that we're using zen for host discovery. Putting an // explicit set of bootstrap hosts ensures we connect to a valid cluster. .put( "discovery.zen.ping.unicast.hosts", hostString ) .put( "discovery.zen.ping.multicast.enabled", "false" ).put( "http.enabled", false ) .put( "client.transport.ping_timeout", 2000 ) // milliseconds .put( "client.transport.nodes_sampler_interval", 100 ).put( "network.tcp.blocking", true ) .put( "node.client", true ).put( "node.name", nodeName ) .build(); if (logger.isTraceEnabled()) { logger.trace("Creating ElasticSearch client with settings: {}", settings.getAsMap()); } Node node = NodeBuilder.nodeBuilder().settings( settings ).client( true ).data( false ).node(); return node.client(); } /** * */ public enum ClientType { TRANSPORT, NODE } }