From aea6bd29e40af170124791a5b19dcd62ec17e019 Mon Sep 17 00:00:00 2001 From: Kunal Kotwani Date: Thu, 27 Apr 2023 17:36:14 -0700 Subject: [PATCH] Add API for clearing file cache on search nodes Signed-off-by: Kunal Kotwani --- CHANGELOG.md | 3 +- .../client/RestHighLevelClientTests.java | 1 + .../api/nodes.clear_filecache.json | 19 +++ .../snapshots/SearchableSnapshotIT.java | 38 ++++++ .../org/opensearch/action/ActionModule.java | 5 + .../clear/ClearNodeFileCacheResponse.java | 73 ++++++++++++ .../clear/ClearNodesFileCacheAction.java | 26 +++++ .../clear/ClearNodesFileCacheRequest.java | 36 ++++++ .../clear/ClearNodesFileCacheResponse.java | 63 ++++++++++ .../TransportClearNodesFileCacheAction.java | 110 ++++++++++++++++++ .../node/filecache/clear/package-info.java | 13 +++ .../cluster/node/filecache/package-info.java | 13 +++ .../opensearch/client/ClusterAdminClient.java | 12 ++ .../client/support/AbstractClient.java | 14 +++ .../RestClearNodesFileCacheAction.java | 52 +++++++++ .../ClearNodesFileCacheRequestTests.java | 47 ++++++++ 16 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 rest-api-spec/src/main/resources/rest-api-spec/api/nodes.clear_filecache.json create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodeFileCacheResponse.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheAction.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheRequest.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheResponse.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/TransportClearNodesFileCacheAction.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/package-info.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/package-info.java create mode 100644 server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClearNodesFileCacheAction.java create mode 100644 server/src/test/java/org/opensearch/action/admin/cluster/node/filecache/ClearNodesFileCacheRequestTests.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f5c8fa44f9f0a..c17ed4eb2107f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added - [Extensions] Moving Extensions APIs to protobuf serialization. ([#6960](https://github.com/opensearch-project/OpenSearch/pull/6960)) - Add descending order search optimization through reverse segment read. ([#7244](https://github.com/opensearch-project/OpenSearch/pull/7244)) +- API to clear filecache on search capable nodes ([#7323](https://github.com/opensearch-project/OpenSearch/pull/7323)) ### Dependencies - Bump `jackson` from 2.14.2 to 2.15.0 ([#7286](https://github.com/opensearch-project/OpenSearch/pull/7286) @@ -99,4 +100,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Security [Unreleased 3.0]: https://github.com/opensearch-project/OpenSearch/compare/2.x...HEAD -[Unreleased 2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.5...2.x \ No newline at end of file +[Unreleased 2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.5...2.x diff --git a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java index ddd17a9c3c214..5ff54d0137a5f 100644 --- a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java @@ -870,6 +870,7 @@ public void testApiNamingConventions() throws Exception { "ingest.processor_grok", "nodes.info", "nodes.stats", + "nodes.clear_filecache", "nodes.hot_threads", "nodes.usage", "nodes.reload_secure_settings", diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.clear_filecache.json b/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.clear_filecache.json new file mode 100644 index 0000000000000..86bf126d1240c --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.clear_filecache.json @@ -0,0 +1,19 @@ +{ + "nodes.clear_filecache":{ + "documentation":{ + "url": "https://opensearch.org/docs/latest/opensearch/rest-api/filecache#clear", + "description":"Clears all file caches for one or more search capable nodes." + }, + "stability":"experimental", + "url":{ + "paths":[ + { + "path":"/_filecache/clear", + "methods":[ + "POST" + ] + } + ] + } + } +} diff --git a/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java b/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java index e9021dd8ed9ef..2d5c0ea3c4adb 100644 --- a/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java @@ -7,6 +7,9 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; import com.carrotsearch.randomizedtesting.generators.RandomPicks; import org.hamcrest.MatcherAssert; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodeFileCacheResponse; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheRequest; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheResponse; import org.opensearch.action.admin.cluster.node.stats.NodeStats; import org.opensearch.action.admin.cluster.node.stats.NodesStatsRequest; import org.opensearch.action.admin.cluster.node.stats.NodesStatsResponse; @@ -664,6 +667,41 @@ public void testCacheIndexFilesClearedOnDelete() throws Exception { logger.info("--> validated that the cache file path doesn't exist"); } + /** + * Test scenario that calls the clear filecache API which prunes the file cache + * Ensures that the filecache was pruned on all the search capable nodes. + */ + public void testFileCacheClearAPI() throws Exception { + final int numReplicas = randomIntBetween(1, 4); + final int numShards = numReplicas + 1; + final String indexName = "test-idx"; + final String restoredIndexName = indexName + "-copy"; + final String repoName = "test-repo"; + final String snapshotName = "test-snap"; + final Client client = client(); + + internalCluster().ensureAtLeastNumSearchAndDataNodes(numShards); + createIndexWithDocsAndEnsureGreen(numReplicas, 100, indexName); + createRepositoryWithSettings(null, repoName); + takeSnapshot(client, snapshotName, repoName, indexName); + restoreSnapshotAndEnsureGreen(client, snapshotName, repoName); + assertDocCount(restoredIndexName, 100L); + assertRemoteSnapshotIndexSettings(client, restoredIndexName); + + ClearNodesFileCacheResponse nodesResponse = client.admin().cluster().clearFileCache(new ClearNodesFileCacheRequest()).actionGet(); + int nodesClearedCount = 0; + for (ClearNodeFileCacheResponse nodeResponse : nodesResponse.getNodes()) { + if (nodeResponse.getNode().isSearchNode()) { + nodesClearedCount++; + assertTrue(nodeResponse.isCleared()); + assertTrue(nodeResponse.getCount() >= 0); + } + } + + assertEquals(nodesClearedCount, numShards); + deleteIndicesAndEnsureGreen(client, restoredIndexName); + } + /** * Asserts the cache folder count to match the number of shards and the number of indices within the cache folder * as provided. diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 7346ccc2e3829..fdd785495caee 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -149,6 +149,8 @@ import org.opensearch.action.admin.indices.delete.TransportDeleteIndexAction; import org.opensearch.action.admin.indices.exists.indices.IndicesExistsAction; import org.opensearch.action.admin.indices.exists.indices.TransportIndicesExistsAction; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheAction; +import org.opensearch.action.admin.cluster.node.filecache.clear.TransportClearNodesFileCacheAction; import org.opensearch.action.admin.indices.flush.FlushAction; import org.opensearch.action.admin.indices.flush.TransportFlushAction; import org.opensearch.action.admin.indices.forcemerge.ForceMergeAction; @@ -311,6 +313,7 @@ import org.opensearch.rest.action.admin.cluster.RestAddVotingConfigExclusionAction; import org.opensearch.rest.action.admin.cluster.RestCancelTasksAction; import org.opensearch.rest.action.admin.cluster.RestCleanupRepositoryAction; +import org.opensearch.rest.action.admin.cluster.RestClearNodesFileCacheAction; import org.opensearch.rest.action.admin.cluster.RestClearVotingConfigExclusionsAction; import org.opensearch.rest.action.admin.cluster.RestCloneSnapshotAction; import org.opensearch.rest.action.admin.cluster.RestClusterAllocationExplainAction; @@ -580,6 +583,7 @@ public void reg actions.register(NodesInfoAction.INSTANCE, TransportNodesInfoAction.class); actions.register(RemoteInfoAction.INSTANCE, TransportRemoteInfoAction.class); actions.register(NodesStatsAction.INSTANCE, TransportNodesStatsAction.class); + actions.register(ClearNodesFileCacheAction.INSTANCE, TransportClearNodesFileCacheAction.class); actions.register(NodesUsageAction.INSTANCE, TransportNodesUsageAction.class); actions.register(NodesHotThreadsAction.INSTANCE, TransportNodesHotThreadsAction.class); actions.register(ListTasksAction.INSTANCE, TransportListTasksAction.class); @@ -769,6 +773,7 @@ public void initRestHandlers(Supplier nodesInCluster) { registerHandler.accept(new RestNodesInfoAction(settingsFilter)); registerHandler.accept(new RestRemoteClusterInfoAction()); registerHandler.accept(new RestNodesStatsAction()); + registerHandler.accept(new RestClearNodesFileCacheAction()); registerHandler.accept(new RestNodesUsageAction()); registerHandler.accept(new RestNodesHotThreadsAction()); registerHandler.accept(new RestClusterAllocationExplainAction()); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodeFileCacheResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodeFileCacheResponse.java new file mode 100644 index 0000000000000..5a4ab1c2fa1b2 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodeFileCacheResponse.java @@ -0,0 +1,73 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache.clear; + +import org.opensearch.action.support.nodes.BaseNodeResponse; +import org.opensearch.cluster.node.DiscoveryNode; +import org.opensearch.cluster.node.DiscoveryNodeRole; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +import java.io.IOException; + +/** + * The response of a clear filecache action for a single node. + * + * @opensearch.internal + */ +public class ClearNodeFileCacheResponse extends BaseNodeResponse implements ToXContentFragment { + + boolean cleared; + + long count; + + protected ClearNodeFileCacheResponse(StreamInput in) throws IOException { + super(in); + cleared = in.readBoolean(); + count = in.readLong(); + } + + public ClearNodeFileCacheResponse(DiscoveryNode discoveryNode, boolean cleared, long count) { + super(discoveryNode); + this.cleared = cleared; + this.count = count; + } + + public boolean isCleared() { + return cleared; + } + + public long getCount() { + return count; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeBoolean(cleared); + out.writeLong(count); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("name", getNode().getName()); + + builder.startArray("roles"); + for (DiscoveryNodeRole role : getNode().getRoles()) { + builder.value(role.roleName()); + } + builder.endArray(); + + builder.field("cleared", cleared); + builder.field("item_count", count); + return builder; + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheAction.java new file mode 100644 index 0000000000000..0e4b094200958 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheAction.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache.clear; + +import org.opensearch.action.ActionType; + +/** + * Transport action for clearing filecache on nodes + * + * @opensearch.internal + */ +public class ClearNodesFileCacheAction extends ActionType { + + public static final ClearNodesFileCacheAction INSTANCE = new ClearNodesFileCacheAction(); + public static final String NAME = "cluster:admin/nodes/filecache/clear"; + + private ClearNodesFileCacheAction() { + super(NAME, ClearNodesFileCacheResponse::new); + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheRequest.java new file mode 100644 index 0000000000000..2da314806063c --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheRequest.java @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache.clear; + +import org.opensearch.action.support.nodes.BaseNodesRequest; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +import java.io.IOException; + +/** + * Request object for clearing filecache on nodes + * + * @opensearch.internal + */ +public class ClearNodesFileCacheRequest extends BaseNodesRequest { + + public ClearNodesFileCacheRequest() { + super((String[]) null); + } + + public ClearNodesFileCacheRequest(StreamInput in) throws IOException { + super(in); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheResponse.java new file mode 100644 index 0000000000000..b3b1771ca77fa --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/ClearNodesFileCacheResponse.java @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache.clear; + +import org.opensearch.action.FailedNodeException; +import org.opensearch.action.support.nodes.BaseNodesResponse; +import org.opensearch.cluster.ClusterName; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.List; + +/** + * The response of a clear filecache action aggregated across nodes. + * + * @opensearch.internal + */ +public class ClearNodesFileCacheResponse extends BaseNodesResponse implements ToXContentFragment { + + ClearNodesFileCacheResponse(StreamInput in) throws IOException { + super(in); + } + + ClearNodesFileCacheResponse( + ClusterName clusterName, + List clearNodeFileCachResponses, + List failures + ) { + super(clusterName, clearNodeFileCachResponses, failures); + } + + @Override + protected List readNodesFrom(StreamInput in) throws IOException { + return in.readList(ClearNodeFileCacheResponse::new); + } + + @Override + protected void writeNodesTo(StreamOutput out, List clearNodeFileCacheResponse) throws IOException { + out.writeList(clearNodeFileCacheResponse); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject("nodes"); + for (ClearNodeFileCacheResponse clearNodeFileCacheResponse : getNodes()) { + builder.startObject(clearNodeFileCacheResponse.getNode().getId()); + clearNodeFileCacheResponse.toXContent(builder, params); + builder.endObject(); + } + builder.endObject(); + + return builder; + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/TransportClearNodesFileCacheAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/TransportClearNodesFileCacheAction.java new file mode 100644 index 0000000000000..efb04edfcb5ed --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/TransportClearNodesFileCacheAction.java @@ -0,0 +1,110 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache.clear; + +import org.opensearch.action.FailedNodeException; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.nodes.TransportNodesAction; +import org.opensearch.cluster.node.DiscoveryNode; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.inject.Inject; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.node.Node; +import org.opensearch.threadpool.ThreadPool; +import org.opensearch.transport.TransportRequest; +import org.opensearch.transport.TransportService; + +import java.io.IOException; +import java.util.List; + +/** + * Transport action for clearing filecache on {@link org.opensearch.cluster.node.DiscoveryNodeRole#SEARCH_ROLE} nodes + * + * @opensearch.internal + */ +public class TransportClearNodesFileCacheAction extends TransportNodesAction< + ClearNodesFileCacheRequest, + ClearNodesFileCacheResponse, + TransportClearNodesFileCacheAction.ClearNodeFileCacheRequest, + ClearNodeFileCacheResponse> { + + private final Node node; + + @Inject + public TransportClearNodesFileCacheAction( + ThreadPool threadPool, + ClusterService clusterService, + TransportService transportService, + Node node, + ActionFilters actionFilters + ) { + super( + ClearNodesFileCacheAction.NAME, + threadPool, + clusterService, + transportService, + actionFilters, + ClearNodesFileCacheRequest::new, + ClearNodeFileCacheRequest::new, + ThreadPool.Names.MANAGEMENT, + ClearNodeFileCacheResponse.class + ); + this.node = node; + + } + + @Override + protected ClearNodesFileCacheResponse newResponse( + ClearNodesFileCacheRequest request, + List clearNodeFileCacheResponses, + List failures + ) { + return new ClearNodesFileCacheResponse(clusterService.getClusterName(), clearNodeFileCacheResponses, failures); + } + + @Override + protected ClearNodeFileCacheRequest newNodeRequest(ClearNodesFileCacheRequest request) { + return new ClearNodeFileCacheRequest(request); + } + + @Override + protected ClearNodeFileCacheResponse newNodeResponse(StreamInput in) throws IOException { + return new ClearNodeFileCacheResponse(in); + } + + @Override + protected ClearNodeFileCacheResponse nodeOperation(ClearNodeFileCacheRequest request) { + DiscoveryNode discoveryNode = transportService.getLocalNode(); + if (discoveryNode.isSearchNode()) { + long count = node.fileCache().prune(); + return new ClearNodeFileCacheResponse(transportService.getLocalNode(), true, count); + } + return new ClearNodeFileCacheResponse(transportService.getLocalNode(), false, 0); + } + + public static class ClearNodeFileCacheRequest extends TransportRequest { + ClearNodesFileCacheRequest request; + + public ClearNodeFileCacheRequest(StreamInput in) throws IOException { + super(in); + request = new ClearNodesFileCacheRequest(in); + } + + ClearNodeFileCacheRequest(ClearNodesFileCacheRequest request) { + this.request = request; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + request.writeTo(out); + } + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/package-info.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/package-info.java new file mode 100644 index 0000000000000..2ccd10d0e7241 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/clear/package-info.java @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** + * Handlers utilized to perform the action of clearing filecache on + * {@link org.opensearch.cluster.node.DiscoveryNodeRole#SEARCH_ROLE} nodes. + */ +package org.opensearch.action.admin.cluster.node.filecache.clear; diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/package-info.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/package-info.java new file mode 100644 index 0000000000000..0a2550c8d8db6 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/filecache/package-info.java @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** + * Handlers utilized to perform any required actions for filecache on + * {@link org.opensearch.cluster.node.DiscoveryNodeRole#SEARCH_ROLE} nodes. + */ +package org.opensearch.action.admin.cluster.node.filecache; diff --git a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java index 39aa1ed80d0d7..09dec089ae8d1 100644 --- a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java +++ b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java @@ -49,6 +49,8 @@ import org.opensearch.action.admin.cluster.health.ClusterHealthRequest; import org.opensearch.action.admin.cluster.health.ClusterHealthRequestBuilder; import org.opensearch.action.admin.cluster.health.ClusterHealthResponse; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheRequest; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheResponse; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequest; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequestBuilder; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsResponse; @@ -933,4 +935,14 @@ public interface ClusterAdminClient extends OpenSearchClient { * Deletes a stored search pipeline */ ActionFuture deleteSearchPipeline(DeleteSearchPipelineRequest request); + + /** + * Clears file cache on {@link org.opensearch.cluster.node.DiscoveryNodeRole#SEARCH_ROLE} nodes. + */ + ActionFuture clearFileCache(ClearNodesFileCacheRequest request); + + /** + * Clears file cache on {@link org.opensearch.cluster.node.DiscoveryNodeRole#SEARCH_ROLE} nodes. + */ + void clearFileCache(ClearNodesFileCacheRequest request, ActionListener listener); } diff --git a/server/src/main/java/org/opensearch/client/support/AbstractClient.java b/server/src/main/java/org/opensearch/client/support/AbstractClient.java index 6a38254a03e71..4cb025ff72e59 100644 --- a/server/src/main/java/org/opensearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/opensearch/client/support/AbstractClient.java @@ -59,6 +59,9 @@ import org.opensearch.action.admin.cluster.health.ClusterHealthRequest; import org.opensearch.action.admin.cluster.health.ClusterHealthRequestBuilder; import org.opensearch.action.admin.cluster.health.ClusterHealthResponse; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheAction; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheRequest; +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheResponse; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsAction; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequest; import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequestBuilder; @@ -1489,6 +1492,17 @@ public void deleteSearchPipeline(DeleteSearchPipelineRequest request, ActionList public ActionFuture deleteSearchPipeline(DeleteSearchPipelineRequest request) { return execute(DeleteSearchPipelineAction.INSTANCE, request); } + + @Override + public ActionFuture clearFileCache(ClearNodesFileCacheRequest request) { + ActionFuture responseActionFuture = execute(ClearNodesFileCacheAction.INSTANCE, request); + return responseActionFuture; + } + + @Override + public void clearFileCache(ClearNodesFileCacheRequest request, ActionListener listener) { + execute(ClearNodesFileCacheAction.INSTANCE, request, listener); + } } static class IndicesAdmin implements IndicesAdminClient { diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClearNodesFileCacheAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClearNodesFileCacheAction.java new file mode 100644 index 0000000000000..99a17905b0f0b --- /dev/null +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClearNodesFileCacheAction.java @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.rest.action.admin.cluster; + +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheRequest; +import org.opensearch.client.node.NodeClient; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestActions; + +import java.io.IOException; +import java.util.List; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.POST; + +/** + * Transport action to clear indices cache + * + * @opensearch.api + */ +public class RestClearNodesFileCacheAction extends BaseRestHandler { + + @Override + public List routes() { + return singletonList(new Route(POST, "/_filecache/clear")); + } + + @Override + public String getName() { + return "clear_nodes_filecache_action"; + } + + @Override + public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { + return channel -> client.admin() + .cluster() + .clearFileCache(new ClearNodesFileCacheRequest(), new RestActions.NodesResponseRestListener<>(channel)); + } + + @Override + public boolean canTripCircuitBreaker() { + return false; + } + +} diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/node/filecache/ClearNodesFileCacheRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/node/filecache/ClearNodesFileCacheRequestTests.java new file mode 100644 index 0000000000000..ce352923494a1 --- /dev/null +++ b/server/src/test/java/org/opensearch/action/admin/cluster/node/filecache/ClearNodesFileCacheRequestTests.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.node.filecache; + +import org.opensearch.action.admin.cluster.node.filecache.clear.ClearNodesFileCacheRequest; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.test.OpenSearchTestCase; + +public class ClearNodesFileCacheRequestTests extends OpenSearchTestCase { + + public void testRequest() { + ClearNodesFileCacheRequest clearNodesFileCacheRequest = new ClearNodesFileCacheRequest(); + assertNull(clearNodesFileCacheRequest.nodesIds()); + assertNull(clearNodesFileCacheRequest.concreteNodes()); + assertNull(clearNodesFileCacheRequest.timeout()); + } + + public void testSerialization() throws Exception { + ClearNodesFileCacheRequest clearNodesFileCacheRequest = new ClearNodesFileCacheRequest(); + assertNull(clearNodesFileCacheRequest.nodesIds()); + ClearNodesFileCacheRequest deserializedRequest = roundTripRequest(clearNodesFileCacheRequest); + assertEquals(0, deserializedRequest.nodesIds().length); + assertNull(deserializedRequest.concreteNodes()); + assertNull(deserializedRequest.timeout()); + } + + /** + * Serialize and deserialize a request. + * @param request A request to serialize. + * @return The deserialized, "round-tripped" request. + */ + private static ClearNodesFileCacheRequest roundTripRequest(ClearNodesFileCacheRequest request) throws Exception { + try (BytesStreamOutput out = new BytesStreamOutput()) { + request.writeTo(out); + try (StreamInput in = out.bytes().streamInput()) { + return new ClearNodesFileCacheRequest(in); + } + } + } +}