All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.server.es.IndexCreator Maven / Gradle / Ivy

There is a newer version: 7.2.1
Show newest version
/*
 * SonarQube
 * Copyright (C) 2009-2016 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.server.es;

import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.settings.Settings;
import org.picocontainer.Startable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

/**
 * Creates/deletes all indices in Elasticsearch during server startup.
 */
@ServerSide
public class IndexCreator implements Startable {

  private static final Logger LOGGER = Loggers.get(IndexCreator.class);

  /**
   * Internal setting stored on index to know its version. It's used to re-create index
   * when something changed between versions.
   */
  private static final String SETTING_HASH = "sonar_hash";

  private final EsClient client;
  private final IndexDefinitions definitions;

  public IndexCreator(EsClient client, IndexDefinitions definitions) {
    this.client = client;
    this.definitions = definitions;
  }

  @Override
  public void start() {
    // create indices that do not exist or that have a new definition (different mapping, cluster enabled, ...)
    for (IndexDefinitions.Index index : definitions.getIndices().values()) {
      boolean exists = client.prepareIndicesExist(index.getName()).get().isExists();
      if (exists && needsToDeleteIndex(index)) {
        LOGGER.info(String.format("Delete index %s (settings changed)", index.getName()));
        deleteIndex(index.getName());
        exists = false;
      }
      if (!exists) {
        createIndex(index);
      }
    }
  }

  @Override
  public void stop() {
    // nothing to do
  }

  private void createIndex(IndexDefinitions.Index index) {
    LOGGER.info(String.format("Create index %s", index.getName()));
    Settings.Builder settings = Settings.builder();
    settings.put(index.getSettings());
    settings.put(SETTING_HASH, new IndexDefinitionHash().of(index));
    CreateIndexResponse indexResponse = client
      .prepareCreate(index.getName())
      .setSettings(settings)
      .get();
    if (!indexResponse.isAcknowledged()) {
      throw new IllegalStateException("Failed to create index " + index.getName());
    }
    client.waitForStatus(ClusterHealthStatus.YELLOW);

    // create types
    for (Map.Entry entry : index.getTypes().entrySet()) {
      LOGGER.info(String.format("Create type %s/%s", index.getName(), entry.getKey()));
      PutMappingResponse mappingResponse = client.preparePutMapping(index.getName())
        .setType(entry.getKey())
        .setSource(entry.getValue().getAttributes())
        .get();
      if (!mappingResponse.isAcknowledged()) {
        throw new IllegalStateException("Failed to create type " + entry.getKey());
      }
    }
    client.waitForStatus(ClusterHealthStatus.YELLOW);
  }

  private void deleteIndex(String indexName) {
    client.nativeClient().admin().indices().prepareDelete(indexName).get();
  }

  private boolean needsToDeleteIndex(IndexDefinitions.Index index) {
    boolean toBeDeleted = false;
    String hash = client.nativeClient().admin().indices().prepareGetSettings(index.getName()).get().getSetting(index.getName(), "index." + SETTING_HASH);
    if (hash != null) {
      String defHash = new IndexDefinitionHash().of(index);
      toBeDeleted = !StringUtils.equals(hash, defHash);
    }
    return toBeDeleted;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy