|
12 | 12 |
|
13 | 13 | import org.apache.lucene.store.Directory;
|
14 | 14 | import org.apache.lucene.store.FilterDirectory;
|
| 15 | +import org.opensearch.action.admin.cluster.node.stats.NodeStats; |
| 16 | +import org.opensearch.action.admin.cluster.node.stats.NodesStatsRequest; |
| 17 | +import org.opensearch.action.admin.cluster.node.stats.NodesStatsResponse; |
15 | 18 | import org.opensearch.action.admin.indices.delete.DeleteIndexRequest;
|
16 | 19 | import org.opensearch.action.admin.indices.get.GetIndexRequest;
|
17 | 20 | import org.opensearch.action.admin.indices.get.GetIndexResponse;
|
|
28 | 31 | import org.opensearch.index.store.CompositeDirectory;
|
29 | 32 | import org.opensearch.index.store.remote.file.CleanerDaemonThreadLeakFilter;
|
30 | 33 | import org.opensearch.index.store.remote.filecache.FileCache;
|
| 34 | +import org.opensearch.index.store.remote.filecache.FileCacheStats; |
| 35 | +import org.opensearch.index.store.remote.filecache.FullFileCacheStats; |
31 | 36 | import org.opensearch.index.store.remote.utils.FileTypeUtils;
|
32 | 37 | import org.opensearch.indices.IndicesService;
|
33 | 38 | import org.opensearch.node.Node;
|
|
36 | 41 |
|
37 | 42 | import java.util.Arrays;
|
38 | 43 | import java.util.HashSet;
|
| 44 | +import java.util.Objects; |
39 | 45 | import java.util.Set;
|
| 46 | +import java.util.concurrent.ExecutionException; |
40 | 47 | import java.util.stream.Collectors;
|
41 | 48 |
|
42 | 49 | import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked;
|
|
49 | 56 | public class WritableWarmIT extends RemoteStoreBaseIntegTestCase {
|
50 | 57 |
|
51 | 58 | protected static final String INDEX_NAME = "test-idx-1";
|
| 59 | + protected static final String INDEX_NAME_2 = "test-idx-2"; |
52 | 60 | protected static final int NUM_DOCS_IN_BULK = 1000;
|
53 | 61 |
|
54 | 62 | /*
|
@@ -168,4 +176,88 @@ public void testWritableWarmBasic() throws Exception {
|
168 | 176 | assertAcked(client().admin().indices().delete(new DeleteIndexRequest(INDEX_NAME)).get());
|
169 | 177 | fileCache.prune();
|
170 | 178 | }
|
| 179 | + |
| 180 | + public void testFullFileAndFileCacheStats() throws ExecutionException, InterruptedException { |
| 181 | + |
| 182 | + InternalTestCluster internalTestCluster = internalCluster(); |
| 183 | + internalTestCluster.startClusterManagerOnlyNode(); |
| 184 | + internalTestCluster.startDataAndSearchNodes(1); |
| 185 | + |
| 186 | + Settings settings = Settings.builder() |
| 187 | + .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) |
| 188 | + .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) |
| 189 | + .put(IndexModule.INDEX_STORE_LOCALITY_SETTING.getKey(), IndexModule.DataLocalityType.PARTIAL.name()) |
| 190 | + .build(); |
| 191 | + |
| 192 | + assertAcked(client().admin().indices().prepareCreate(INDEX_NAME_2).setSettings(settings).get()); |
| 193 | + |
| 194 | + // Verify from the cluster settings if the data locality is partial |
| 195 | + GetIndexResponse getIndexResponse = client().admin() |
| 196 | + .indices() |
| 197 | + .getIndex(new GetIndexRequest().indices(INDEX_NAME_2).includeDefaults(true)) |
| 198 | + .get(); |
| 199 | + |
| 200 | + Settings indexSettings = getIndexResponse.settings().get(INDEX_NAME_2); |
| 201 | + assertEquals(IndexModule.DataLocalityType.PARTIAL.name(), indexSettings.get(IndexModule.INDEX_STORE_LOCALITY_SETTING.getKey())); |
| 202 | + |
| 203 | + // Ingesting docs again before force merge |
| 204 | + indexBulk(INDEX_NAME_2, NUM_DOCS_IN_BULK); |
| 205 | + flushAndRefresh(INDEX_NAME_2); |
| 206 | + |
| 207 | + // ensuring cluster is green |
| 208 | + ensureGreen(); |
| 209 | + |
| 210 | + SearchResponse searchResponse = client().prepareSearch(INDEX_NAME_2).setQuery(QueryBuilders.matchAllQuery()).get(); |
| 211 | + // Asserting that search returns same number of docs as ingested |
| 212 | + assertHitCount(searchResponse, NUM_DOCS_IN_BULK); |
| 213 | + |
| 214 | + // Ingesting docs again before force merge |
| 215 | + indexBulk(INDEX_NAME_2, NUM_DOCS_IN_BULK); |
| 216 | + flushAndRefresh(INDEX_NAME_2); |
| 217 | + |
| 218 | + FileCache fileCache = internalTestCluster.getDataNodeInstance(Node.class).fileCache(); |
| 219 | + |
| 220 | + // TODO: Make these validation more robust, when SwitchableIndexInput is implemented. |
| 221 | + |
| 222 | + NodesStatsResponse nodesStatsResponse = client().admin().cluster().nodesStats(new NodesStatsRequest().all()).actionGet(); |
| 223 | + |
| 224 | + FileCacheStats fileCacheStats = nodesStatsResponse.getNodes() |
| 225 | + .stream() |
| 226 | + .filter(n -> n.getNode().isDataNode()) |
| 227 | + .toList() |
| 228 | + .getFirst() |
| 229 | + .getFileCacheStats(); |
| 230 | + |
| 231 | + if (Objects.isNull(fileCacheStats)) { |
| 232 | + fail("File Cache Stats should not be null"); |
| 233 | + } |
| 234 | + |
| 235 | + FullFileCacheStats fullFileCacheStats = fileCacheStats.fullFileCacheStats(); |
| 236 | + |
| 237 | + if (Objects.isNull(fullFileCacheStats)) { |
| 238 | + fail("Full File Cache Stats should not be null"); |
| 239 | + } |
| 240 | + |
| 241 | + // Deleting the index (so that ref count drops to zero for all the files) and then pruning the cache to clear it to avoid any file |
| 242 | + // leaks |
| 243 | + assertAcked(client().admin().indices().delete(new DeleteIndexRequest(INDEX_NAME_2)).get()); |
| 244 | + fileCache.prune(); |
| 245 | + |
| 246 | + NodesStatsResponse response = client().admin().cluster().nodesStats(new NodesStatsRequest().all()).actionGet(); |
| 247 | + int nonEmptyFileCacheNodes = 0; |
| 248 | + for (NodeStats stats : response.getNodes()) { |
| 249 | + FileCacheStats fcStats = stats.getFileCacheStats(); |
| 250 | + if (Objects.isNull(fcStats) == false) { |
| 251 | + if (isFileCacheEmpty(fcStats) == false) { |
| 252 | + nonEmptyFileCacheNodes++; |
| 253 | + } |
| 254 | + } |
| 255 | + } |
| 256 | + assertEquals(0, nonEmptyFileCacheNodes); |
| 257 | + |
| 258 | + } |
| 259 | + |
| 260 | + private boolean isFileCacheEmpty(FileCacheStats stats) { |
| 261 | + return stats.getUsed().getBytes() == 0L && stats.getActive().getBytes() == 0L; |
| 262 | + } |
171 | 263 | }
|
0 commit comments