/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch 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.elasticsearch.gateway; import java.nio.file.Path; import org.apache.lucene.util.IOUtils; import org.elassandra.NoPersistedMetaDataException; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.NodeEnvironment; /** * */ public class Gateway extends AbstractComponent implements ClusterStateListener { private final ClusterService clusterService; private final NodeEnvironment nodeEnv; private final String initialMeta; private final ClusterName clusterName; @Inject public Gateway(Settings settings, ClusterService clusterService, NodeEnvironment nodeEnv, ClusterName clusterName) { super(settings); this.clusterService = clusterService; this.nodeEnv = nodeEnv; this.clusterName = clusterName; clusterService.addLast(this); // we define what is our minimum "master" nodes, use that to allow for recovery this.initialMeta = settings.get("gateway.initial_meta", settings.get("gateway.local.initial_meta", settings.get("discovery.zen.minimum_master_nodes", "1"))); } public void performStateRecovery(final GatewayStateRecoveredListener listener) throws GatewayException { logger.debug("performing metadata recovery from cassandra"); ClusterState.Builder builder = ClusterState.builder(clusterService.state()); MetaData metadata; try { /* * Recovery performed from comment because elatic_admin keyspace won't be available before replaying commmit logs. */ metadata = clusterService.readMetaDataAsComment(); } catch (NoPersistedMetaDataException |ActionRequestValidationException e) { logger.trace("Failed to read metadata from table comment", e); metadata = clusterService.state().metaData(); if (metadata.uuid().equals("_na_")) { metadata = MetaData.builder(metadata).clusterUUID(clusterService.localNode().id()).build(); } } listener.onSuccess( clusterService.updateNumberOfShards(builder.metaData(metadata).build()) ); } public void reset() throws Exception { try { Path[] dataPaths = nodeEnv.nodeDataPaths(); logger.trace("removing node data paths: [{}]", dataPaths); IOUtils.rm(dataPaths); } catch (Exception ex) { logger.debug("failed to delete shard locations", ex); } } @Override public void clusterChanged(final ClusterChangedEvent event) { // order is important, first metaState, and then shardsState // so dangling indices will be recorded //metaState.clusterChanged(event); } public interface GatewayStateRecoveredListener { void onSuccess(ClusterState build); void onFailure(String s); } }