/** * Copyright 2011 Molindo GmbH * * Licensed 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 at.molindo.elastic.compass; import static org.elasticsearch.node.NodeBuilder.nodeBuilder; import org.compass.core.CompassException; import org.compass.core.config.CompassConfigurable; import org.compass.core.config.CompassSettings; import org.compass.core.engine.SearchEngineException; import org.elasticsearch.common.collect.IdentityHashSet; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.node.Node; public class ElasticNode implements CompassConfigurable { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory .getLogger(ElasticNode.class); private static final String ELASTIC_NODE_KEY = ElasticNode.class.getName(); private NodeHolder _nodeHolder; private ElasticSearchEngineFactory _searchEngineFactory; private ElasticSettings _settings; private ElasticIndex _index; public ElasticNode(ElasticSearchEngineFactory searchEngineFactory) { if (searchEngineFactory == null) { throw new NullPointerException("searchEngineFactory"); } _searchEngineFactory = searchEngineFactory; } @Override public void configure(CompassSettings settings) throws CompassException { _settings = new ElasticSettings(settings); synchronized (ELASTIC_NODE_KEY) { _nodeHolder = (NodeHolder) settings.getRegistry(ELASTIC_NODE_KEY); if (_nodeHolder == null) { boolean local = _settings.getLocal(); ImmutableSettings.Builder settingsBuilder = ImmutableSettings.settingsBuilder() .put("cluster.name", _settings.getClusterName()); if (local) { // TODO some hard coded testing preferences settingsBuilder.put("index.store.type", "ram"); settingsBuilder.put("index.refresh_interval", "-1"); } Node node = nodeBuilder().local(local).client(!local).data(local) .settings(settingsBuilder.build()).node(); _nodeHolder = new NodeHolder(node, this); settings.setRegistry(ELASTIC_NODE_KEY, _nodeHolder); // wait for cluster to become ready if necessary String nodeCount = _settings.getLocal() ? "1" : ">1"; log.info("waiting for " + nodeCount + " nodes"); node.client().admin().cluster().prepareHealth().setWaitForNodes(nodeCount) .execute().actionGet(); } else { _nodeHolder.add(this); } } _index = new ElasticIndex(_settings, getNode().client(), _searchEngineFactory.getMapping()); } public ElasticClient client() { log.debug("creating new ElasticClient for ElasticNode"); return new ElasticClient(_searchEngineFactory, _index, getNode().client()); } public void start() { // noop } public void stop() { // noop } public void close() { if (_nodeHolder != null) { _nodeHolder.remove(this); } } public ElasticSettings getSettings() { if (_settings == null) { throw new IllegalStateException("ElasticNode not yet configured"); } return _settings; } public void replaceWith(ElasticNode node) { String alias = _index.getAlias(); _index.deleteIndex(); node._index.addAlias(alias); _index = new ElasticIndex(_settings, getNode().client(), _searchEngineFactory.getMapping()); } private Node getNode() { if (_nodeHolder == null) { throw new SearchEngineException("ElasticNode not started"); } return _nodeHolder.getNode(); } private static final class NodeHolder { private final Node _node; final IdentityHashSet<ElasticNode> _elasticNodes = new IdentityHashSet<ElasticNode>(); public NodeHolder(Node node, ElasticNode elasticNode) { if (node == null) { throw new NullPointerException("node"); } if (elasticNode == null) { throw new NullPointerException("elasticNode"); } _node = node; _elasticNodes.add(elasticNode); } public Node getNode() { return _node; } public boolean add(ElasticNode elasticNode) { if (_elasticNodes.size() == 0) { throw new IllegalStateException("node already closed"); } return _elasticNodes.add(elasticNode); } public boolean remove(ElasticNode elasticNode) { boolean removed = _elasticNodes.remove(elasticNode); if (_elasticNodes.size() == 0) { _node.close(); } return removed; } } }