|
@@ -7,31 +7,30 @@
|
|
|
|
|
|
package org.elasticsearch.xpack.profiler;
|
|
|
|
|
|
-import org.apache.logging.log4j.LogManager;
|
|
|
-import org.apache.logging.log4j.Logger;
|
|
|
import org.elasticsearch.action.ActionListener;
|
|
|
+import org.elasticsearch.action.ActionResponse;
|
|
|
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
|
|
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
|
|
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
|
|
+import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
|
|
+import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
|
|
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|
|
import org.elasticsearch.client.internal.Client;
|
|
|
-import org.elasticsearch.cluster.ClusterChangedEvent;
|
|
|
import org.elasticsearch.cluster.ClusterState;
|
|
|
-import org.elasticsearch.cluster.ClusterStateListener;
|
|
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
|
import org.elasticsearch.cluster.service.ClusterService;
|
|
|
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
|
|
import org.elasticsearch.core.TimeValue;
|
|
|
-import org.elasticsearch.gateway.GatewayService;
|
|
|
import org.elasticsearch.threadpool.ThreadPool;
|
|
|
import org.elasticsearch.xpack.core.ClientHelper;
|
|
|
|
|
|
-import java.io.Closeable;
|
|
|
+import java.util.Comparator;
|
|
|
import java.util.List;
|
|
|
import java.util.Locale;
|
|
|
import java.util.Map;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
-import java.util.concurrent.ConcurrentMap;
|
|
|
+import java.util.Objects;
|
|
|
import java.util.concurrent.Executor;
|
|
|
-import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
+import java.util.function.Predicate;
|
|
|
|
|
|
import static org.elasticsearch.core.Strings.format;
|
|
|
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
|
|
@@ -39,107 +38,202 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
|
|
|
/**
|
|
|
* Creates all indices that are required for using Elastic Universal Profiling.
|
|
|
*/
|
|
|
-public class ProfilingIndexManager implements ClusterStateListener, Closeable {
|
|
|
- private static final Logger logger = LogManager.getLogger(ProfilingIndexManager.class);
|
|
|
+public class ProfilingIndexManager extends AbstractProfilingPersistenceManager<ProfilingIndexManager.ProfilingIndex> {
|
|
|
// For testing
|
|
|
public static final List<ProfilingIndex> PROFILING_INDICES = List.of(
|
|
|
- ProfilingIndex.regular("profiling-returnpads-private"),
|
|
|
- ProfilingIndex.regular("profiling-sq-executables"),
|
|
|
- ProfilingIndex.regular("profiling-sq-leafframes"),
|
|
|
- ProfilingIndex.regular("profiling-symbols-private"),
|
|
|
- ProfilingIndex.kv("profiling-executables"),
|
|
|
- ProfilingIndex.kv("profiling-stackframes"),
|
|
|
- ProfilingIndex.kv("profiling-stacktraces"),
|
|
|
- ProfilingIndex.kv("profiling-symbols-global")
|
|
|
+ ProfilingIndex.regular(
|
|
|
+ "profiling-returnpads-private",
|
|
|
+ ProfilingIndexTemplateRegistry.PROFILING_RETURNPADS_PRIVATE_VERSION,
|
|
|
+ OnVersionBump.KEEP_OLD
|
|
|
+ ),
|
|
|
+ ProfilingIndex.regular(
|
|
|
+ "profiling-sq-executables",
|
|
|
+ ProfilingIndexTemplateRegistry.PROFILING_SQ_EXECUTABLES_VERSION,
|
|
|
+ OnVersionBump.DELETE_OLD
|
|
|
+ ),
|
|
|
+ ProfilingIndex.regular(
|
|
|
+ "profiling-sq-leafframes",
|
|
|
+ ProfilingIndexTemplateRegistry.PROFILING_SQ_LEAFFRAMES_VERSION,
|
|
|
+ OnVersionBump.DELETE_OLD
|
|
|
+ ),
|
|
|
+ ProfilingIndex.regular(
|
|
|
+ "profiling-symbols-private",
|
|
|
+ ProfilingIndexTemplateRegistry.PROFILING_SYMBOLS_VERSION,
|
|
|
+ OnVersionBump.KEEP_OLD
|
|
|
+ ),
|
|
|
+ ProfilingIndex.kv("profiling-executables", ProfilingIndexTemplateRegistry.PROFILING_EXECUTABLES_VERSION),
|
|
|
+ ProfilingIndex.kv("profiling-stackframes", ProfilingIndexTemplateRegistry.PROFILING_STACKFRAMES_VERSION),
|
|
|
+ ProfilingIndex.kv("profiling-stacktraces", ProfilingIndexTemplateRegistry.PROFILING_STACKTRACES_VERSION),
|
|
|
+ ProfilingIndex.kv("profiling-symbols-global", ProfilingIndexTemplateRegistry.PROFILING_SYMBOLS_VERSION)
|
|
|
);
|
|
|
|
|
|
private final ThreadPool threadPool;
|
|
|
private final Client client;
|
|
|
- private final ClusterService clusterService;
|
|
|
- private final ConcurrentMap<String, AtomicBoolean> creationInProgressPerIndex = new ConcurrentHashMap<>();
|
|
|
- private volatile boolean templatesEnabled;
|
|
|
|
|
|
public ProfilingIndexManager(ThreadPool threadPool, Client client, ClusterService clusterService) {
|
|
|
+ super(clusterService);
|
|
|
this.threadPool = threadPool;
|
|
|
this.client = client;
|
|
|
- this.clusterService = clusterService;
|
|
|
- }
|
|
|
-
|
|
|
- public void initialize() {
|
|
|
- clusterService.addListener(this);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void close() {
|
|
|
- clusterService.removeListener(this);
|
|
|
- }
|
|
|
-
|
|
|
- public void setTemplatesEnabled(boolean templatesEnabled) {
|
|
|
- this.templatesEnabled = templatesEnabled;
|
|
|
+ protected void onStatus(
|
|
|
+ ClusterState clusterState,
|
|
|
+ Status status,
|
|
|
+ ProfilingIndex index,
|
|
|
+ ActionListener<? super ActionResponse> listener
|
|
|
+ ) {
|
|
|
+ switch (status) {
|
|
|
+ case NEEDS_CREATION -> createIndex(clusterState, index, listener);
|
|
|
+ case NEEDS_VERSION_BUMP -> bumpVersion(clusterState, index, listener);
|
|
|
+ default -> {
|
|
|
+ logger.debug("Skipping status change [{}] for index [{}].", status, index);
|
|
|
+ // ensure that listener is notified we're done
|
|
|
+ listener.onResponse(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void clusterChanged(ClusterChangedEvent event) {
|
|
|
- if (templatesEnabled == false) {
|
|
|
- return;
|
|
|
+ protected IndexMetadata indexMetadata(ClusterState state, ProfilingIndex index) {
|
|
|
+ Map<String, IndexMetadata> indicesMetadata = state.metadata().indices();
|
|
|
+ if (indicesMetadata == null) {
|
|
|
+ return null;
|
|
|
}
|
|
|
- // wait for the cluster state to be recovered
|
|
|
- if (event.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
|
|
|
- return;
|
|
|
+ IndexMetadata metadata = indicesMetadata.get(index.toString());
|
|
|
+ // prioritize the most recent generation from the current version
|
|
|
+ if (metadata == null && index.isKvIndex()) {
|
|
|
+ metadata = indicesMetadata.entrySet()
|
|
|
+ .stream()
|
|
|
+ .filter(e -> index.isMatchWithoutGeneration(e.getKey()))
|
|
|
+ // use the most recent index to make sure we use the most recent version info from the _meta field
|
|
|
+ .max(Comparator.comparingLong(e -> e.getValue().getCreationDate()))
|
|
|
+ .map(Map.Entry::getValue)
|
|
|
+ .orElse(null);
|
|
|
}
|
|
|
|
|
|
- // If this node is not a master node, exit.
|
|
|
- if (event.state().nodes().isLocalNodeElectedMaster() == false) {
|
|
|
- return;
|
|
|
+ // attempt to find an index from an earlier generation
|
|
|
+ if (metadata == null) {
|
|
|
+ metadata = indicesMetadata.entrySet()
|
|
|
+ .stream()
|
|
|
+ .filter(e -> index.isMatchWithoutVersion(e.getKey()))
|
|
|
+ // use the most recent index to make sure we use the most recent version info from the _meta field
|
|
|
+ .max(Comparator.comparingLong(e -> e.getValue().getCreationDate()))
|
|
|
+ .map(Map.Entry::getValue)
|
|
|
+ .orElse(null);
|
|
|
}
|
|
|
|
|
|
- if (event.state().nodes().getMaxNodeVersion().after(event.state().nodes().getSmallestNonClientNodeVersion())) {
|
|
|
- logger.debug("Skipping up-to-date check as cluster has mixed versions");
|
|
|
- return;
|
|
|
- }
|
|
|
+ return metadata;
|
|
|
+ }
|
|
|
|
|
|
- // ensure that all resources are present that we need to create indices
|
|
|
- if (isAllResourcesCreated(event) == false) {
|
|
|
- logger.trace("Skipping index creation; not all required resources are present yet");
|
|
|
- return;
|
|
|
+ private void bumpVersion(ClusterState state, ProfilingIndex index, ActionListener<? super ActionResponse> listener) {
|
|
|
+ if (index.getOnVersionBump() == OnVersionBump.DELETE_OLD) {
|
|
|
+ Map<String, IndexMetadata> indicesMetadata = state.metadata().indices();
|
|
|
+ List<String> priorIndexVersions = indicesMetadata.keySet()
|
|
|
+ .stream()
|
|
|
+ // ignore the current index and look only for old versions
|
|
|
+ .filter(Predicate.not(index::isFullMatch))
|
|
|
+ .filter(index::isMatchWithoutVersion)
|
|
|
+ .toList();
|
|
|
+ if (priorIndexVersions.isEmpty() == false) {
|
|
|
+ logger.debug("deleting indices [{}] on index version bump for [{}].", priorIndexVersions, index.getAlias());
|
|
|
+ deleteIndices(
|
|
|
+ priorIndexVersions.toArray(new String[0]),
|
|
|
+ // the cluster state that we are operating on is a snapshot and won't reflect that the alias has just gone.
|
|
|
+ // Therefore, we use putIndex here which does not check for the existence of an alias
|
|
|
+ ActionListener.wrap(r -> putIndex(index.getName(), index.getAlias(), listener), listener::onFailure)
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ createIndex(state, index, listener);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ createIndex(state, index, listener);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- addIndicesIfMissing(event.state());
|
|
|
+ @Override
|
|
|
+ protected Iterable<ProfilingIndex> getManagedIndices() {
|
|
|
+ return PROFILING_INDICES;
|
|
|
}
|
|
|
|
|
|
- protected boolean isAllResourcesCreated(ClusterChangedEvent event) {
|
|
|
- return ProfilingIndexTemplateRegistry.isAllResourcesCreated(event.state());
|
|
|
+ private void onCreateIndexFailure(String index, Exception ex) {
|
|
|
+ logger.error(() -> format("error adding index [%s] for [%s]", index, ClientHelper.PROFILING_ORIGIN), ex);
|
|
|
}
|
|
|
|
|
|
- private void addIndicesIfMissing(ClusterState state) {
|
|
|
- Map<String, IndexMetadata> indicesMetadata = state.metadata().indices();
|
|
|
- for (ProfilingIndex profilingIndex : PROFILING_INDICES) {
|
|
|
- String index = profilingIndex.toString();
|
|
|
- final AtomicBoolean creationInProgress = creationInProgressPerIndex.computeIfAbsent(index, key -> new AtomicBoolean(false));
|
|
|
- if (creationInProgress.compareAndSet(false, true)) {
|
|
|
- // Do a quick (exact) check first
|
|
|
- boolean indexNeedsToBeCreated = indicesMetadata == null || indicesMetadata.get(index) == null;
|
|
|
- // for K/V indices we must not create the index if a newer generation exists
|
|
|
- if (indexNeedsToBeCreated && profilingIndex.isKvIndex()) {
|
|
|
- indexNeedsToBeCreated = indicesMetadata != null
|
|
|
- && indicesMetadata.keySet().stream().anyMatch(profilingIndex::isMatchWithoutGeneration) == false;
|
|
|
- }
|
|
|
- if (indexNeedsToBeCreated) {
|
|
|
- logger.debug("adding index [{}], because it doesn't exist", index);
|
|
|
- putIndex(index, profilingIndex.getAlias(), creationInProgress);
|
|
|
- } else {
|
|
|
- logger.trace("not adding index [{}], because it already exists", index);
|
|
|
- creationInProgress.set(false);
|
|
|
- }
|
|
|
- }
|
|
|
+ private void createIndex(final ClusterState state, final ProfilingIndex index, final ActionListener<? super ActionResponse> listener) {
|
|
|
+ if (state.metadata().hasAlias(index.getAlias())) {
|
|
|
+ // there is an existing index from a prior version. Use the rollover API to move the write alias atomically. This has the
|
|
|
+ // following implications:
|
|
|
+ //
|
|
|
+ // * A new index will be created according to the currently installed version of the matching index template.
|
|
|
+ // * The write alias will point to that index.
|
|
|
+ // * The prior index will continue to be managed by ILM but will advance to the next phase after rollover. As
|
|
|
+ // rollover blocks phase transitions, the prior index may move a bit sooner than expected to the warm tier
|
|
|
+ // after version bumps; still all conditions need to be met, it's just that due to the earlier rollover, the
|
|
|
+ // condition will be reached sooner than without a version bump.
|
|
|
+ rolloverIndex(index.getName(), index.getAlias(), listener);
|
|
|
+ } else {
|
|
|
+ // newly create index
|
|
|
+ putIndex(index.getName(), index.getAlias(), listener);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void onPutIndexFailure(String index, Exception ex) {
|
|
|
- logger.error(() -> format("error adding index [%s] for [%s]", index, ClientHelper.PROFILING_ORIGIN), ex);
|
|
|
+ private void rolloverIndex(final String newIndex, final String alias, ActionListener<? super ActionResponse> listener) {
|
|
|
+ logger.debug("rolling over to index [{}] for alias [{}].", newIndex, alias);
|
|
|
+ final Executor executor = threadPool.generic();
|
|
|
+ executor.execute(() -> {
|
|
|
+ RolloverRequest request = new RolloverRequest(alias, newIndex);
|
|
|
+ request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
|
|
|
+ executeAsyncWithOrigin(
|
|
|
+ client.threadPool().getThreadContext(),
|
|
|
+ ClientHelper.PROFILING_ORIGIN,
|
|
|
+ request,
|
|
|
+ new ActionListener<RolloverResponse>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(RolloverResponse response) {
|
|
|
+ if (response.isAcknowledged() == false) {
|
|
|
+ logger.error(
|
|
|
+ "error rolling over index [{}] for [{}], request was not acknowledged",
|
|
|
+ newIndex,
|
|
|
+ ClientHelper.PROFILING_ORIGIN
|
|
|
+ );
|
|
|
+ } else if (response.isShardsAcknowledged() == false) {
|
|
|
+ logger.warn(
|
|
|
+ "rolling over index [{}] for [{}], shards were not acknowledged",
|
|
|
+ newIndex,
|
|
|
+ ClientHelper.PROFILING_ORIGIN
|
|
|
+ );
|
|
|
+ } else if (response.isRolledOver() == false) {
|
|
|
+ logger.warn(
|
|
|
+ "could not rollover alias [{}] to index [{}] for [{}].",
|
|
|
+ alias,
|
|
|
+ newIndex,
|
|
|
+ ClientHelper.PROFILING_ORIGIN
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ logger.debug(
|
|
|
+ "rolled over alias [{}] from [{}] to index [{}] for [{}].",
|
|
|
+ alias,
|
|
|
+ response.getOldIndex(),
|
|
|
+ response.getNewIndex(),
|
|
|
+ ClientHelper.PROFILING_ORIGIN
|
|
|
+ );
|
|
|
+ }
|
|
|
+ listener.onResponse(response);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception e) {
|
|
|
+ onCreateIndexFailure(newIndex, e);
|
|
|
+ listener.onFailure(e);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (req, l) -> client.admin().indices().rolloverIndex(req, l)
|
|
|
+ );
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- private void putIndex(final String index, final String alias, final AtomicBoolean creationCheck) {
|
|
|
+ private void putIndex(final String index, final String alias, final ActionListener<? super ActionResponse> listener) {
|
|
|
final Executor executor = threadPool.generic();
|
|
|
executor.execute(() -> {
|
|
|
CreateIndexRequest request = new CreateIndexRequest(index);
|
|
@@ -148,8 +242,8 @@ public class ProfilingIndexManager implements ClusterStateListener, Closeable {
|
|
|
Map<String, Object> sourceAsMap = Map.of("aliases", Map.of(alias, Map.of("is_write_index", true)));
|
|
|
request.source(sourceAsMap, LoggingDeprecationHandler.INSTANCE);
|
|
|
} catch (Exception ex) {
|
|
|
- creationCheck.set(false);
|
|
|
- onPutIndexFailure(index, ex);
|
|
|
+ onCreateIndexFailure(index, ex);
|
|
|
+ listener.onFailure(ex);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -161,7 +255,6 @@ public class ProfilingIndexManager implements ClusterStateListener, Closeable {
|
|
|
new ActionListener<CreateIndexResponse>() {
|
|
|
@Override
|
|
|
public void onResponse(CreateIndexResponse response) {
|
|
|
- creationCheck.set(false);
|
|
|
if (response.isAcknowledged() == false) {
|
|
|
logger.error(
|
|
|
"error adding index [{}] for [{}], request was not acknowledged",
|
|
@@ -171,64 +264,155 @@ public class ProfilingIndexManager implements ClusterStateListener, Closeable {
|
|
|
} else if (response.isShardsAcknowledged() == false) {
|
|
|
logger.warn("adding index [{}] for [{}], shards were not acknowledged", index, ClientHelper.PROFILING_ORIGIN);
|
|
|
}
|
|
|
+ listener.onResponse(response);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onFailure(Exception e) {
|
|
|
- creationCheck.set(false);
|
|
|
- onPutIndexFailure(index, e);
|
|
|
+ onCreateIndexFailure(index, e);
|
|
|
+ listener.onFailure(e);
|
|
|
}
|
|
|
},
|
|
|
- (req, listener) -> client.admin().indices().create(req, listener)
|
|
|
+ (req, l) -> client.admin().indices().create(req, l)
|
|
|
);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ private void onDeleteIndexFailure(String[] indices, Exception ex) {
|
|
|
+ logger.error(() -> format("error deleting indices [%s] for [%s]", indices, ClientHelper.PROFILING_ORIGIN), ex);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void deleteIndices(final String[] indices, final ActionListener<AcknowledgedResponse> listener) {
|
|
|
+ final Executor executor = threadPool.generic();
|
|
|
+ executor.execute(() -> {
|
|
|
+ DeleteIndexRequest request = new DeleteIndexRequest(indices);
|
|
|
+ request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
|
|
|
+ executeAsyncWithOrigin(
|
|
|
+ client.threadPool().getThreadContext(),
|
|
|
+ ClientHelper.PROFILING_ORIGIN,
|
|
|
+ request,
|
|
|
+ new ActionListener<AcknowledgedResponse>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(AcknowledgedResponse response) {
|
|
|
+ if (response.isAcknowledged() == false) {
|
|
|
+ logger.error(
|
|
|
+ "error deleting indices [{}] for [{}], request was not acknowledged",
|
|
|
+ indices,
|
|
|
+ ClientHelper.PROFILING_ORIGIN
|
|
|
+ );
|
|
|
+ }
|
|
|
+ listener.onResponse(response);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception e) {
|
|
|
+ onDeleteIndexFailure(indices, e);
|
|
|
+ listener.onFailure(e);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (req, l) -> client.admin().indices().delete(req, l)
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ enum OnVersionBump {
|
|
|
+ DELETE_OLD,
|
|
|
+ KEEP_OLD
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* An index that is used by Universal Profiling.
|
|
|
*/
|
|
|
- static class ProfilingIndex {
|
|
|
- private final String name;
|
|
|
+ static class ProfilingIndex implements ProfilingIndexAbstraction {
|
|
|
+ private final String namePrefix;
|
|
|
+ private final int version;
|
|
|
private final String generation;
|
|
|
+ private final OnVersionBump onVersionBump;
|
|
|
|
|
|
- public static ProfilingIndex regular(String name) {
|
|
|
- return new ProfilingIndex(name, null);
|
|
|
+ public static ProfilingIndex regular(String name, int version, OnVersionBump onVersionBump) {
|
|
|
+ return new ProfilingIndex(name, version, null, onVersionBump);
|
|
|
}
|
|
|
|
|
|
- public static ProfilingIndex kv(String name) {
|
|
|
- return new ProfilingIndex(name, "000001");
|
|
|
+ public static ProfilingIndex kv(String name, int version) {
|
|
|
+ // K/V indices will age automatically as per the ILM policy, and we won't force-upgrade them on version bumps
|
|
|
+ return new ProfilingIndex(name, version, "000001", OnVersionBump.KEEP_OLD);
|
|
|
}
|
|
|
|
|
|
- private ProfilingIndex(String namePrefix, String generation) {
|
|
|
- this.name = namePrefix;
|
|
|
+ private ProfilingIndex(String namePrefix, int version, String generation, OnVersionBump onVersionBump) {
|
|
|
+ this.namePrefix = namePrefix;
|
|
|
+ this.version = version;
|
|
|
this.generation = generation;
|
|
|
+ this.onVersionBump = onVersionBump;
|
|
|
+ }
|
|
|
+
|
|
|
+ public ProfilingIndex withVersion(int version) {
|
|
|
+ return new ProfilingIndex(namePrefix, version, generation, onVersionBump);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ProfilingIndex withGeneration(String generation) {
|
|
|
+ return new ProfilingIndex(namePrefix, version, generation, onVersionBump);
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isMatchWithoutVersion(String indexName) {
|
|
|
+ return indexName.startsWith("." + namePrefix);
|
|
|
}
|
|
|
|
|
|
public boolean isMatchWithoutGeneration(String indexName) {
|
|
|
return indexName.startsWith(indexPrefix());
|
|
|
}
|
|
|
|
|
|
+ public boolean isFullMatch(String indexName) {
|
|
|
+ return toString().equals(indexName);
|
|
|
+ }
|
|
|
+
|
|
|
public boolean isKvIndex() {
|
|
|
return generation != null;
|
|
|
}
|
|
|
|
|
|
public String getAlias() {
|
|
|
- return name;
|
|
|
+ return namePrefix;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getName() {
|
|
|
+ return isKvIndex() ? String.format(Locale.ROOT, "%s-%s", indexPrefix(), generation) : indexPrefix();
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getVersion() {
|
|
|
+ return version;
|
|
|
+ }
|
|
|
+
|
|
|
+ public OnVersionBump getOnVersionBump() {
|
|
|
+ return onVersionBump;
|
|
|
}
|
|
|
|
|
|
private String indexPrefix() {
|
|
|
- return String.format(Locale.ROOT, ".%s-v%03d", name, ProfilingIndexTemplateRegistry.INDEX_TEMPLATE_VERSION);
|
|
|
+ return String.format(Locale.ROOT, ".%s-v%03d", namePrefix, version);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String toString() {
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- sb.append(indexPrefix());
|
|
|
- if (generation != null) {
|
|
|
- sb.append("-");
|
|
|
- sb.append(generation);
|
|
|
+ return getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (o == null || getClass() != o.getClass()) {
|
|
|
+ return false;
|
|
|
}
|
|
|
- return sb.toString();
|
|
|
+ ProfilingIndex index = (ProfilingIndex) o;
|
|
|
+ return version == index.version
|
|
|
+ && Objects.equals(namePrefix, index.namePrefix)
|
|
|
+ && Objects.equals(generation, index.generation)
|
|
|
+ && onVersionBump == index.onVersionBump;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(namePrefix, version, generation, onVersionBump);
|
|
|
}
|
|
|
}
|
|
|
}
|