From 01750d3f8b954c047ca9313abd3e94bc750fa9ea Mon Sep 17 00:00:00 2001 From: xuxiong1 Date: Fri, 15 Aug 2025 17:11:59 -0700 Subject: [PATCH 1/2] Add StoreFactory plugin interface for custom Store implementations Signed-off-by: xuxiong1 --- .../common/settings/IndexScopedSettings.java | 1 + .../org/opensearch/index/IndexModule.java | 32 ++++++ .../org/opensearch/index/IndexService.java | 7 +- .../org/opensearch/index/store/Store.java | 22 ++-- .../opensearch/indices/IndicesService.java | 6 + .../main/java/org/opensearch/node/Node.java | 7 ++ .../opensearch/plugins/IndexStorePlugin.java | 46 +++++++- .../opensearch/index/IndexModuleTests.java | 107 ++++++++++++++++++ .../plugins/IndexStorePluginTests.java | 27 +++++ 9 files changed, 243 insertions(+), 12 deletions(-) diff --git a/server/src/main/java/org/opensearch/common/settings/IndexScopedSettings.java b/server/src/main/java/org/opensearch/common/settings/IndexScopedSettings.java index 918384de34bbf..a8b76a3f2ac01 100644 --- a/server/src/main/java/org/opensearch/common/settings/IndexScopedSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/IndexScopedSettings.java @@ -199,6 +199,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings { BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING, IndexModule.INDEX_STORE_TYPE_SETTING, IndexModule.INDEX_COMPOSITE_STORE_TYPE_SETTING, + IndexModule.INDEX_STORE_FACTORY_SETTING, IndexModule.INDEX_STORE_PRE_LOAD_SETTING, IndexModule.INDEX_STORE_HYBRID_NIO_EXTENSIONS, IndexModule.INDEX_RECOVERY_TYPE_SETTING, diff --git a/server/src/main/java/org/opensearch/index/IndexModule.java b/server/src/main/java/org/opensearch/index/IndexModule.java index 266d48b3b996e..2f98a22b64fbf 100644 --- a/server/src/main/java/org/opensearch/index/IndexModule.java +++ b/server/src/main/java/org/opensearch/index/IndexModule.java @@ -79,6 +79,7 @@ import org.opensearch.index.similarity.SimilarityService; import org.opensearch.index.store.DefaultCompositeDirectoryFactory; import org.opensearch.index.store.FsDirectoryFactory; +import org.opensearch.index.store.Store; import org.opensearch.index.store.remote.directory.RemoteSnapshotDirectoryFactory; import org.opensearch.index.store.remote.filecache.FileCache; import org.opensearch.index.translog.TranslogFactory; @@ -156,6 +157,17 @@ public final class IndexModule { Property.NodeScope ); + /** + * Index setting that selects a custom StoreFactory provided by plugins. If empty, the default store is used + */ + public static final Setting INDEX_STORE_FACTORY_SETTING = new Setting<>( + "index.store.factory", + "", + Function.identity(), + Property.IndexScope, + Property.NodeScope + ); + /** * Index setting which used to determine how the data is cached locally fully or partially. */ @@ -260,6 +272,7 @@ public final class IndexModule { private final AtomicBoolean frozen = new AtomicBoolean(false); private final BooleanSupplier allowExpensiveQueries; private final Map recoveryStateFactories; + private final Map storeFactories; private final FileCache fileCache; private final CompositeIndexSettings compositeIndexSettings; @@ -283,6 +296,7 @@ public IndexModule( final BooleanSupplier allowExpensiveQueries, final IndexNameExpressionResolver expressionResolver, final Map recoveryStateFactories, + final Map storeFactories, final FileCache fileCache, final CompositeIndexSettings compositeIndexSettings ) { @@ -297,6 +311,7 @@ public IndexModule( this.allowExpensiveQueries = allowExpensiveQueries; this.expressionResolver = expressionResolver; this.recoveryStateFactories = recoveryStateFactories; + this.storeFactories = storeFactories == null ? Collections.emptyMap() : Collections.unmodifiableMap(storeFactories); this.fileCache = fileCache; this.compositeIndexSettings = compositeIndexSettings; } @@ -322,6 +337,7 @@ public IndexModule( allowExpensiveQueries, expressionResolver, recoveryStateFactories, + Collections.emptyMap(), null, null ); @@ -759,6 +775,7 @@ public IndexService newIndexService( directoryFactory, compositeDirectoryFactory, remoteDirectoryFactory, + resolveStoreFactory(indexSettings, storeFactories), eventListener, readerWrapperFactory, mapperRegistry, @@ -858,6 +875,21 @@ private static IndexStorePlugin.RecoveryStateFactory getRecoveryStateFactory( return factory; } + private static IndexStorePlugin.StoreFactory resolveStoreFactory( + final IndexSettings indexSettings, + final Map storeFactories + ) { + final String key = indexSettings.getValue(INDEX_STORE_FACTORY_SETTING); + if (key != null && key.isEmpty() == false) { + final IndexStorePlugin.StoreFactory factory = storeFactories.get(key); + if (factory == null) { + throw new IllegalArgumentException("Unknown store factory [" + key + "]"); + } + return factory; + } + return Store::new; + } + /** * creates a new mapper service to do administrative work like mapping updates. This *should not* be used for document parsing. * doing so will result in an exception. diff --git a/server/src/main/java/org/opensearch/index/IndexService.java b/server/src/main/java/org/opensearch/index/IndexService.java index fb579e3d55be1..22441df923bf8 100644 --- a/server/src/main/java/org/opensearch/index/IndexService.java +++ b/server/src/main/java/org/opensearch/index/IndexService.java @@ -206,6 +206,7 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust private final Object refreshMutex = new Object(); private volatile TimeValue refreshInterval; private volatile boolean shardLevelRefreshEnabled; + private final IndexStorePlugin.StoreFactory storeFactory; @InternalApi public IndexService( @@ -228,6 +229,7 @@ public IndexService( IndexStorePlugin.DirectoryFactory directoryFactory, IndexStorePlugin.CompositeDirectoryFactory compositeDirectoryFactory, IndexStorePlugin.DirectoryFactory remoteDirectoryFactory, + IndexStorePlugin.StoreFactory storeFactory, IndexEventListener eventListener, Function> wrapperFactory, MapperRegistry mapperRegistry, @@ -253,6 +255,7 @@ public IndexService( Supplier clusterDefaultMaxMergeAtOnceSupplier ) { super(indexSettings); + this.storeFactory = storeFactory; this.allowExpensiveQueries = allowExpensiveQueries; this.indexSettings = indexSettings; this.xContentRegistry = xContentRegistry; @@ -378,6 +381,7 @@ public IndexService( QueryCache queryCache, IndexStorePlugin.DirectoryFactory directoryFactory, IndexStorePlugin.DirectoryFactory remoteDirectoryFactory, + IndexStorePlugin.StoreFactory storeFactory, IndexEventListener eventListener, Function> wrapperFactory, MapperRegistry mapperRegistry, @@ -418,6 +422,7 @@ public IndexService( directoryFactory, null, remoteDirectoryFactory, + storeFactory, eventListener, wrapperFactory, mapperRegistry, @@ -742,7 +747,7 @@ protected void closeInternal() { } else { directory = directoryFactory.newDirectory(this.indexSettings, path); } - store = new Store( + store = storeFactory.newStore( shardId, this.indexSettings, directory, diff --git a/server/src/main/java/org/opensearch/index/store/Store.java b/server/src/main/java/org/opensearch/index/store/Store.java index 53bbb6e298991..9645741ccf20f 100644 --- a/server/src/main/java/org/opensearch/index/store/Store.java +++ b/server/src/main/java/org/opensearch/index/store/Store.java @@ -1080,21 +1080,22 @@ public long getNumDocs() { /** * Metadata that is currently loaded * - * @opensearch.internal + * @opensearch.api */ - static class LoadedMetadata { - final Map fileMetadata; - final Map userData; - final long numDocs; + @PublicApi(since = "3.1.0") + public static class LoadedMetadata { + public final Map fileMetadata; + public final Map userData; + public final long numDocs; - LoadedMetadata(Map fileMetadata, Map userData, long numDocs) { + public LoadedMetadata(Map fileMetadata, Map userData, long numDocs) { this.fileMetadata = fileMetadata; this.userData = userData; this.numDocs = numDocs; } } - static LoadedMetadata loadMetadata(IndexCommit commit, Directory directory, Logger logger) throws IOException { + public static LoadedMetadata loadMetadata(IndexCommit commit, Directory directory, Logger logger) throws IOException { try { final SegmentInfos segmentCommitInfos = Store.readSegmentsInfo(commit, directory); return loadMetadata(segmentCommitInfos, directory, logger); @@ -1125,11 +1126,11 @@ static LoadedMetadata loadMetadata(IndexCommit commit, Directory directory, Logg } } - static LoadedMetadata loadMetadata(SegmentInfos segmentInfos, Directory directory, Logger logger) throws IOException { + public static LoadedMetadata loadMetadata(SegmentInfos segmentInfos, Directory directory, Logger logger) throws IOException { return loadMetadata(segmentInfos, directory, logger, false); } - static LoadedMetadata loadMetadata(SegmentInfos segmentInfos, Directory directory, Logger logger, boolean ignoreSegmentsFile) + public static LoadedMetadata loadMetadata(SegmentInfos segmentInfos, Directory directory, Logger logger, boolean ignoreSegmentsFile) throws IOException { long numDocs = Lucene.getNumDocs(segmentInfos); Map commitUserDataBuilder = new HashMap<>(); @@ -1732,8 +1733,9 @@ public void markStoreCorrupted(IOException exception) throws IOException { /** * A listener that is executed once the store is closed and all references to it are released * - * @opensearch.internal + * @opensearch.api */ + @PublicApi(since = "3.1.0") public interface OnClose extends Consumer { OnClose EMPTY = new OnClose() { /** diff --git a/server/src/main/java/org/opensearch/indices/IndicesService.java b/server/src/main/java/org/opensearch/indices/IndicesService.java index 3ce6f9798e972..fa03134803c9a 100644 --- a/server/src/main/java/org/opensearch/indices/IndicesService.java +++ b/server/src/main/java/org/opensearch/indices/IndicesService.java @@ -392,6 +392,7 @@ public class IndicesService extends AbstractLifecycleComponent private final Map compositeDirectoryFactories; private final Map ingestionConsumerFactories; private final Map recoveryStateFactories; + private final Map storeFactories; final AbstractRefCounted indicesRefCount; // pkg-private for testing private final CountDownLatch closeLatch = new CountDownLatch(1); private volatile boolean idFieldDataEnabled; @@ -445,6 +446,7 @@ public IndicesService( Map compositeDirectoryFactories, ValuesSourceRegistry valuesSourceRegistry, Map recoveryStateFactories, + Map storeFactories, IndexStorePlugin.DirectoryFactory remoteDirectoryFactory, Supplier repositoriesServiceSupplier, SearchRequestStats searchRequestStats, @@ -509,6 +511,7 @@ public void onRemoval(ShardId shardId, String fieldName, boolean wasEvicted, lon this.directoryFactories = directoryFactories; this.compositeDirectoryFactories = compositeDirectoryFactories; this.recoveryStateFactories = recoveryStateFactories; + this.storeFactories = storeFactories; this.ingestionConsumerFactories = ingestionConsumerFactories; // doClose() is called when shutting down a node, yet there might still be ongoing requests // that we need to wait for before closing some resources such as the caches. In order to @@ -643,6 +646,7 @@ public IndicesService( Collections.emptyMap(), valuesSourceRegistry, recoveryStateFactories, + Collections.emptyMap(), remoteDirectoryFactory, repositoriesServiceSupplier, searchRequestStats, @@ -1060,6 +1064,7 @@ private synchronized IndexService createIndexService( () -> allowExpensiveQueries, indexNameExpressionResolver, recoveryStateFactories, + storeFactories, fileCache, compositeIndexSettings ); @@ -1179,6 +1184,7 @@ public synchronized MapperService createIndexMapperService(IndexMetadata indexMe () -> allowExpensiveQueries, indexNameExpressionResolver, recoveryStateFactories, + storeFactories, fileCache, compositeIndexSettings ); diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index 35630b8bec0b3..a88e595ca9a94 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -938,6 +938,12 @@ protected Node(final Environment initialEnvironment, Collection clas .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final Map storeFactories = pluginsService.filterPlugins(IndexStorePlugin.class) + .stream() + .map(IndexStorePlugin::getStoreFactories) + .flatMap(m -> m.entrySet().stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final RerouteService rerouteService = new BatchedRerouteService(clusterService, clusterModule.getAllocationService()::reroute); rerouteServiceReference.set(rerouteService); clusterService.setRerouteService(rerouteService); @@ -991,6 +997,7 @@ protected Node(final Environment initialEnvironment, Collection clas Map.copyOf(compositeDirectoryFactories), searchModule.getValuesSourceRegistry(), recoveryStateFactories, + storeFactories, remoteDirectoryFactory, repositoriesServiceReference::get, searchRequestStats, diff --git a/server/src/main/java/org/opensearch/plugins/IndexStorePlugin.java b/server/src/main/java/org/opensearch/plugins/IndexStorePlugin.java index 112c0f9dc39b7..052026c6b9c0d 100644 --- a/server/src/main/java/org/opensearch/plugins/IndexStorePlugin.java +++ b/server/src/main/java/org/opensearch/plugins/IndexStorePlugin.java @@ -38,9 +38,12 @@ import org.opensearch.common.Nullable; import org.opensearch.common.annotation.ExperimentalApi; import org.opensearch.common.annotation.PublicApi; +import org.opensearch.core.index.shard.ShardId; +import org.opensearch.env.ShardLock; import org.opensearch.index.IndexSettings; import org.opensearch.index.shard.ShardPath; import org.opensearch.index.store.IndexStoreListener; +import org.opensearch.index.store.Store; import org.opensearch.index.store.remote.filecache.FileCache; import org.opensearch.indices.recovery.RecoveryState; import org.opensearch.threadpool.ThreadPool; @@ -83,7 +86,9 @@ interface DirectoryFactory { * * @return a map from store type to an directory factory */ - Map getDirectoryFactories(); + default Map getDirectoryFactories() { + return Collections.emptyMap(); + } /** * An interface that describes how to create a new composite directory instance per shard. @@ -153,4 +158,43 @@ default Map getRecoveryStateFactories() { default Optional getIndexStoreListener() { return Optional.empty(); } + + /** + * An interface that describes how to create a new Store instance per shard. + * + * @opensearch.api + */ + @FunctionalInterface + @ExperimentalApi + interface StoreFactory { + /** + * Creates a new Store per shard. This method is called once per shard on shard creation. + * @param shardId the shard id + * @param indexSettings the shard's index settings + * @param directory the Lucene directory selected for this shard + * @param shardLock the shard lock to associate with the store + * @param onClose listener invoked on store close + * @param shardPath the shard path + * @return a new Store instance + */ + Store newStore( + ShardId shardId, + IndexSettings indexSettings, + Directory directory, + ShardLock shardLock, + Store.OnClose onClose, + ShardPath shardPath + ) throws IOException; + } + + /** + * The {@link StoreFactory} mappings for this plugin. When an index is created a custom store factory can be selected via + * {@code index.store.factory}. If not set, the default store is used. + * + * @return a map from store type key to a store factory + */ + @ExperimentalApi + default Map getStoreFactories() { + return Collections.emptyMap(); + } } diff --git a/server/src/test/java/org/opensearch/index/IndexModuleTests.java b/server/src/test/java/org/opensearch/index/IndexModuleTests.java index aa425305d762c..3d75e354871c5 100644 --- a/server/src/test/java/org/opensearch/index/IndexModuleTests.java +++ b/server/src/test/java/org/opensearch/index/IndexModuleTests.java @@ -96,6 +96,7 @@ import org.opensearch.index.similarity.SimilarityService; import org.opensearch.index.store.FsDirectoryFactory; import org.opensearch.index.store.RemoteSegmentStoreDirectoryFactory; +import org.opensearch.index.store.Store; import org.opensearch.index.translog.InternalTranslogFactory; import org.opensearch.index.translog.RemoteBlobStoreInternalTranslogFactory; import org.opensearch.index.translog.TranslogFactory; @@ -649,6 +650,98 @@ public void testRegisterCustomRecoveryStateFactory() throws IOException { indexService.close("closing", false); } + public void testStoreFactory() throws IOException { + final Settings settings = Settings.builder() + .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT) + .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) + .put(IndexModule.INDEX_STORE_FACTORY_SETTING.getKey(), "test_store") + .build(); + + final IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(index, settings); + final TestStoreFactory testStoreFactory = new TestStoreFactory(); + final Map storeFactories = singletonMap("test_store", testStoreFactory); + + final IndexModule module = new IndexModule( + indexSettings, + emptyAnalysisRegistry, + new InternalEngineFactory(), + new EngineConfigFactory(indexSettings), + Collections.emptyMap(), + Collections.emptyMap(), + () -> true, + new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)), + Collections.emptyMap(), + storeFactories, + null, + null + ); + + // Test that IndexService can be created successfully with valid store factory + final IndexService indexService = newIndexService(module); + assertNotNull(indexService); + indexService.close("closing", false); + } + + public void testStoreFactoryWithEmptySetting() throws IOException { + final Settings settings = Settings.builder() + .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT) + .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) + .put(IndexModule.INDEX_STORE_FACTORY_SETTING.getKey(), "") + .build(); + + final IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(index, settings); + final TestStoreFactory testStoreFactory = new TestStoreFactory(); + final Map storeFactories = singletonMap("test_store", testStoreFactory); + + final IndexModule module = new IndexModule( + indexSettings, + emptyAnalysisRegistry, + new InternalEngineFactory(), + new EngineConfigFactory(indexSettings), + Collections.emptyMap(), + Collections.emptyMap(), + () -> true, + new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)), + Collections.emptyMap(), + storeFactories, + null, + null + ); + + // Test that IndexService uses default store when setting is empty + final IndexService indexService = newIndexService(module); + assertNotNull(indexService); + indexService.close("closing", false); + } + + public void testUnknownStoreFactory() { + final Settings settings = Settings.builder() + .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT) + .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) + .put(IndexModule.INDEX_STORE_FACTORY_SETTING.getKey(), "unknown_store") + .build(); + + final IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(index, settings); + + final IndexModule module = new IndexModule( + indexSettings, + emptyAnalysisRegistry, + new InternalEngineFactory(), + new EngineConfigFactory(indexSettings), + Collections.emptyMap(), + Collections.emptyMap(), + () -> true, + new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)), + Collections.emptyMap(), + Collections.emptyMap(), + null, + null + ); + + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> newIndexService(module)); + assertThat(exception.getMessage(), containsString("Unknown store factory [unknown_store]")); + } + private ShardRouting createInitializedShardRouting() { ShardRouting shard = ShardRouting.newUnassigned( new ShardId("test", "_na_", 0), @@ -736,4 +829,18 @@ public DirectoryReader apply(DirectoryReader reader) { return null; } } + + public static final class TestStoreFactory implements IndexStorePlugin.StoreFactory { + @Override + public Store newStore( + ShardId shardId, + IndexSettings indexSettings, + Directory directory, + ShardLock shardLock, + Store.OnClose onClose, + ShardPath shardPath + ) throws IOException { + return new Store(shardId, indexSettings, directory, shardLock, onClose, shardPath); + } + } } diff --git a/server/src/test/java/org/opensearch/plugins/IndexStorePluginTests.java b/server/src/test/java/org/opensearch/plugins/IndexStorePluginTests.java index 5fd76fc90568c..0bb6d4d74f6da 100644 --- a/server/src/test/java/org/opensearch/plugins/IndexStorePluginTests.java +++ b/server/src/test/java/org/opensearch/plugins/IndexStorePluginTests.java @@ -35,12 +35,18 @@ import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.routing.ShardRouting; import org.opensearch.common.settings.Settings; +import org.opensearch.core.index.shard.ShardId; +import org.opensearch.env.ShardLock; import org.opensearch.index.IndexModule; +import org.opensearch.index.IndexSettings; +import org.opensearch.index.shard.ShardPath; import org.opensearch.index.store.FsDirectoryFactory; +import org.opensearch.index.store.Store; import org.opensearch.indices.recovery.RecoveryState; import org.opensearch.node.MockNode; import org.opensearch.test.OpenSearchTestCase; +import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -115,6 +121,27 @@ public RecoveryState newRecoveryState(ShardRouting shardRouting, DiscoveryNode t } } + public static class FooStoreFactoryPlugin extends Plugin implements IndexStorePlugin { + @Override + public Map getStoreFactories() { + return Collections.singletonMap("foo_store", new TestStoreFactory()); + } + } + + public static class TestStoreFactory implements IndexStorePlugin.StoreFactory { + @Override + public Store newStore( + ShardId shardId, + IndexSettings indexSettings, + org.apache.lucene.store.Directory directory, + ShardLock shardLock, + Store.OnClose onClose, + ShardPath shardPath + ) throws IOException { + return new Store(shardId, indexSettings, directory, shardLock, onClose, shardPath); + } + } + public void testIndexStoreFactoryConflictsWithBuiltInIndexStoreType() { final Settings settings = Settings.builder().put("path.home", createTempDir()).build(); final IllegalStateException e = expectThrows( From f56b79cfd2eb12dd89cf4fbd08edef4ad79dc5f1 Mon Sep 17 00:00:00 2001 From: xuxiong1 Date: Mon, 18 Aug 2025 17:30:45 -0700 Subject: [PATCH 2/2] Resolve comments Signed-off-by: xuxiong1 --- CHANGELOG.md | 1 + .../java/org/opensearch/index/IndexModule.java | 16 ++++++++-------- .../java/org/opensearch/index/store/Store.java | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf24167152486..f5415fdd1d486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Add temporal routing processors for time-based document routing ([#18920](https://github.com/opensearch-project/OpenSearch/issues/18920)) - The dynamic mapping parameter supports false_allow_templates ([#19065](https://github.com/opensearch-project/OpenSearch/pull/19065)) - Add a toBuilder method in EngineConfig to support easy modification of configs([#19054](https://github.com/opensearch-project/OpenSearch/pull/19054)) +- Add StoreFactory plugin interface for custom Store implementations([#19091](https://github.com/opensearch-project/OpenSearch/pull/19091)) ### Changed - Add CompletionStage variants to methods in the Client Interface and default to ActionListener impl ([#18998](https://github.com/opensearch-project/OpenSearch/pull/18998)) diff --git a/server/src/main/java/org/opensearch/index/IndexModule.java b/server/src/main/java/org/opensearch/index/IndexModule.java index 2f98a22b64fbf..7a8eee076fa37 100644 --- a/server/src/main/java/org/opensearch/index/IndexModule.java +++ b/server/src/main/java/org/opensearch/index/IndexModule.java @@ -311,7 +311,7 @@ public IndexModule( this.allowExpensiveQueries = allowExpensiveQueries; this.expressionResolver = expressionResolver; this.recoveryStateFactories = recoveryStateFactories; - this.storeFactories = storeFactories == null ? Collections.emptyMap() : Collections.unmodifiableMap(storeFactories); + this.storeFactories = storeFactories; this.fileCache = fileCache; this.compositeIndexSettings = compositeIndexSettings; } @@ -880,14 +880,14 @@ private static IndexStorePlugin.StoreFactory resolveStoreFactory( final Map storeFactories ) { final String key = indexSettings.getValue(INDEX_STORE_FACTORY_SETTING); - if (key != null && key.isEmpty() == false) { - final IndexStorePlugin.StoreFactory factory = storeFactories.get(key); - if (factory == null) { - throw new IllegalArgumentException("Unknown store factory [" + key + "]"); - } - return factory; + if (key == null || key.isEmpty()) { + return Store::new; } - return Store::new; + final IndexStorePlugin.StoreFactory factory = storeFactories.get(key); + if (factory == null) { + throw new IllegalArgumentException("Unknown store factory [" + key + "]"); + } + return factory; } /** diff --git a/server/src/main/java/org/opensearch/index/store/Store.java b/server/src/main/java/org/opensearch/index/store/Store.java index 9645741ccf20f..cb11f48310e45 100644 --- a/server/src/main/java/org/opensearch/index/store/Store.java +++ b/server/src/main/java/org/opensearch/index/store/Store.java @@ -1082,7 +1082,7 @@ public long getNumDocs() { * * @opensearch.api */ - @PublicApi(since = "3.1.0") + @PublicApi(since = "3.2.0") public static class LoadedMetadata { public final Map fileMetadata; public final Map userData; @@ -1735,7 +1735,7 @@ public void markStoreCorrupted(IOException exception) throws IOException { * * @opensearch.api */ - @PublicApi(since = "3.1.0") + @PublicApi(since = "3.2.0") public interface OnClose extends Consumer { OnClose EMPTY = new OnClose() { /**