Allow inclusion of unloaded segments in stats (#39512)

Today we have no chance to fetch actual segment stats for segments that
are currently unloaded. This is relevant in the case of frozen indices.
This allows to monitor how much memory a frozen index would use if it was
unfrozen.
This commit is contained in:
Simon Willnauer 2019-03-05 14:01:41 +01:00
parent 7ed9d52824
commit d112c89041
15 changed files with 101 additions and 40 deletions

View File

@ -57,6 +57,11 @@
"type": "boolean", "type": "boolean",
"description": "Verbose mode. Display column headers", "description": "Verbose mode. Display column headers",
"default": false "default": false
},
"include_unloaded_segments": {
"type": "boolean",
"description": "If set to true segment stats will include stats for segments that are not currently loaded into memory",
"default": false
} }
} }
}, },

View File

@ -52,6 +52,11 @@
"type": "boolean", "type": "boolean",
"description": "Whether to report the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested)", "description": "Whether to report the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested)",
"default": false "default": false
},
"include_unloaded_segments": {
"type": "boolean",
"description": "If set to true segment stats will include stats for segments that are not currently loaded into memory",
"default": false
} }
} }
}, },

View File

@ -207,7 +207,7 @@ public class CommonStats implements Writeable, ToXContentFragment {
completion = indexShard.completionStats(flags.completionDataFields()); completion = indexShard.completionStats(flags.completionDataFields());
break; break;
case Segments: case Segments:
segments = indexShard.segmentStats(flags.includeSegmentFileSizes()); segments = indexShard.segmentStats(flags.includeSegmentFileSizes(), flags.includeUnloadedSegments());
break; break;
case Translog: case Translog:
translog = indexShard.translogStats(); translog = indexShard.translogStats();

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.stats; package org.elasticsearch.action.admin.indices.stats;
import org.elasticsearch.Version;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.io.stream.Writeable;
@ -38,6 +39,7 @@ public class CommonStatsFlags implements Writeable, Cloneable {
private String[] fieldDataFields = null; private String[] fieldDataFields = null;
private String[] completionDataFields = null; private String[] completionDataFields = null;
private boolean includeSegmentFileSizes = false; private boolean includeSegmentFileSizes = false;
private boolean includeUnloadedSegments = false;
/** /**
* @param flags flags to set. If no flags are supplied, default flags will be set. * @param flags flags to set. If no flags are supplied, default flags will be set.
@ -62,6 +64,9 @@ public class CommonStatsFlags implements Writeable, Cloneable {
fieldDataFields = in.readStringArray(); fieldDataFields = in.readStringArray();
completionDataFields = in.readStringArray(); completionDataFields = in.readStringArray();
includeSegmentFileSizes = in.readBoolean(); includeSegmentFileSizes = in.readBoolean();
if (in.getVersion().onOrAfter(Version.V_8_0_0)) {
includeUnloadedSegments = in.readBoolean();
}
} }
@Override @Override
@ -77,6 +82,9 @@ public class CommonStatsFlags implements Writeable, Cloneable {
out.writeStringArrayNullable(fieldDataFields); out.writeStringArrayNullable(fieldDataFields);
out.writeStringArrayNullable(completionDataFields); out.writeStringArrayNullable(completionDataFields);
out.writeBoolean(includeSegmentFileSizes); out.writeBoolean(includeSegmentFileSizes);
if (out.getVersion().onOrAfter(Version.V_8_0_0)) {
out.writeBoolean(includeUnloadedSegments);
}
} }
/** /**
@ -89,6 +97,7 @@ public class CommonStatsFlags implements Writeable, Cloneable {
fieldDataFields = null; fieldDataFields = null;
completionDataFields = null; completionDataFields = null;
includeSegmentFileSizes = false; includeSegmentFileSizes = false;
includeUnloadedSegments = false;
return this; return this;
} }
@ -102,6 +111,7 @@ public class CommonStatsFlags implements Writeable, Cloneable {
fieldDataFields = null; fieldDataFields = null;
completionDataFields = null; completionDataFields = null;
includeSegmentFileSizes = false; includeSegmentFileSizes = false;
includeUnloadedSegments = false;
return this; return this;
} }
@ -170,6 +180,15 @@ public class CommonStatsFlags implements Writeable, Cloneable {
return this; return this;
} }
public CommonStatsFlags includeUnloadedSegments(boolean includeUnloadedSegments) {
this.includeUnloadedSegments = includeUnloadedSegments;
return this;
}
public boolean includeUnloadedSegments() {
return this.includeUnloadedSegments;
}
public boolean includeSegmentFileSizes() { public boolean includeSegmentFileSizes() {
return this.includeSegmentFileSizes; return this.includeSegmentFileSizes;
} }

View File

@ -821,7 +821,7 @@ public abstract class Engine implements Closeable {
/** /**
* Global stats on segments. * Global stats on segments.
*/ */
public SegmentsStats segmentsStats(boolean includeSegmentFileSizes) { public SegmentsStats segmentsStats(boolean includeSegmentFileSizes, boolean includeUnloadedSegments) {
ensureOpen(); ensureOpen();
Set<String> segmentName = new HashSet<>(); Set<String> segmentName = new HashSet<>();
SegmentsStats stats = new SegmentsStats(); SegmentsStats stats = new SegmentsStats();
@ -845,7 +845,7 @@ public abstract class Engine implements Closeable {
return stats; return stats;
} }
private void fillSegmentStats(SegmentReader segmentReader, boolean includeSegmentFileSizes, SegmentsStats stats) { protected void fillSegmentStats(SegmentReader segmentReader, boolean includeSegmentFileSizes, SegmentsStats stats) {
stats.add(1, segmentReader.ramBytesUsed()); stats.add(1, segmentReader.ramBytesUsed());
stats.addTermsMemoryInBytes(guardedRamBytesUsed(segmentReader.getPostingsReader())); stats.addTermsMemoryInBytes(guardedRamBytesUsed(segmentReader.getPostingsReader()));
stats.addStoredFieldsMemoryInBytes(guardedRamBytesUsed(segmentReader.getFieldsReader())); stats.addStoredFieldsMemoryInBytes(guardedRamBytesUsed(segmentReader.getFieldsReader()));

View File

@ -391,4 +391,8 @@ public class SegmentsStats implements Streamable, ToXContentFragment {
out.writeLong(entry.value.longValue()); out.writeLong(entry.value.longValue());
} }
} }
public void clearFileSizes() {
fileSizes = ImmutableOpenMap.of();
}
} }

View File

@ -999,8 +999,8 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
return engine.getMergeStats(); return engine.getMergeStats();
} }
public SegmentsStats segmentStats(boolean includeSegmentFileSizes) { public SegmentsStats segmentStats(boolean includeSegmentFileSizes, boolean includeUnloadedSegments) {
SegmentsStats segmentsStats = getEngine().segmentsStats(includeSegmentFileSizes); SegmentsStats segmentsStats = getEngine().segmentsStats(includeSegmentFileSizes, includeUnloadedSegments);
segmentsStats.addBitsetMemoryInBytes(shardBitsetFilterCache.getMemorySizeInBytes()); segmentsStats.addBitsetMemoryInBytes(shardBitsetFilterCache.getMemorySizeInBytes());
return segmentsStats; return segmentsStats;
} }

View File

@ -121,6 +121,7 @@ public class RestIndicesStatsAction extends BaseRestHandler {
if (indicesStatsRequest.segments()) { if (indicesStatsRequest.segments()) {
indicesStatsRequest.includeSegmentFileSizes(request.paramAsBoolean("include_segment_file_sizes", false)); indicesStatsRequest.includeSegmentFileSizes(request.paramAsBoolean("include_segment_file_sizes", false));
indicesStatsRequest.includeSegmentFileSizes(request.paramAsBoolean("include_unloaded_segments", false));
} }
return channel -> client.admin().indices().stats(indicesStatsRequest, new RestToXContentListener<>(channel)); return channel -> client.admin().indices().stats(indicesStatsRequest, new RestToXContentListener<>(channel));

View File

@ -116,6 +116,7 @@ public class RestIndicesAction extends AbstractCatAction {
indicesStatsRequest.indices(indices); indicesStatsRequest.indices(indices);
indicesStatsRequest.indicesOptions(strictExpandIndicesOptions); indicesStatsRequest.indicesOptions(strictExpandIndicesOptions);
indicesStatsRequest.all(); indicesStatsRequest.all();
indicesStatsRequest.includeSegmentFileSizes(request.paramAsBoolean("include_unloaded_segments", false));
client.admin().indices().stats(indicesStatsRequest, new RestResponseListener<IndicesStatsResponse>(channel) { client.admin().indices().stats(indicesStatsRequest, new RestResponseListener<IndicesStatsResponse>(channel) {
@Override @Override

View File

@ -272,8 +272,8 @@ public class InternalEngineTests extends EngineTestCase {
InternalEngine engine = createEngine(config(indexSettings, store, createTempDir(), NoMergePolicy.INSTANCE, null))) { InternalEngine engine = createEngine(config(indexSettings, store, createTempDir(), NoMergePolicy.INSTANCE, null))) {
List<Segment> segments = engine.segments(false); List<Segment> segments = engine.segments(false);
assertThat(segments.isEmpty(), equalTo(true)); assertThat(segments.isEmpty(), equalTo(true));
assertThat(engine.segmentsStats(false).getCount(), equalTo(0L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(0L));
assertThat(engine.segmentsStats(false).getMemoryInBytes(), equalTo(0L)); assertThat(engine.segmentsStats(false, false).getMemoryInBytes(), equalTo(0L));
// create two docs and refresh // create two docs and refresh
ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), B_1, null); ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), B_1, null);
@ -287,7 +287,7 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(1)); assertThat(segments.size(), equalTo(1));
SegmentsStats stats = engine.segmentsStats(false); SegmentsStats stats = engine.segmentsStats(false, false);
assertThat(stats.getCount(), equalTo(1L)); assertThat(stats.getCount(), equalTo(1L));
assertThat(stats.getTermsMemoryInBytes(), greaterThan(0L)); assertThat(stats.getTermsMemoryInBytes(), greaterThan(0L));
assertThat(stats.getStoredFieldsMemoryInBytes(), greaterThan(0L)); assertThat(stats.getStoredFieldsMemoryInBytes(), greaterThan(0L));
@ -306,7 +306,7 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(1)); assertThat(segments.size(), equalTo(1));
assertThat(engine.segmentsStats(false).getCount(), equalTo(1L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(1L));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
assertThat(segments.get(0).isSearch(), equalTo(true)); assertThat(segments.get(0).isSearch(), equalTo(true));
assertThat(segments.get(0).getNumDocs(), equalTo(2)); assertThat(segments.get(0).getNumDocs(), equalTo(2));
@ -319,15 +319,15 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(2)); assertThat(segments.size(), equalTo(2));
assertThat(engine.segmentsStats(false).getCount(), equalTo(2L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(2L));
assertThat(engine.segmentsStats(false).getTermsMemoryInBytes(), assertThat(engine.segmentsStats(false, false).getTermsMemoryInBytes(),
greaterThan(stats.getTermsMemoryInBytes())); greaterThan(stats.getTermsMemoryInBytes()));
assertThat(engine.segmentsStats(false).getStoredFieldsMemoryInBytes(), assertThat(engine.segmentsStats(false, false).getStoredFieldsMemoryInBytes(),
greaterThan(stats.getStoredFieldsMemoryInBytes())); greaterThan(stats.getStoredFieldsMemoryInBytes()));
assertThat(engine.segmentsStats(false).getTermVectorsMemoryInBytes(), equalTo(0L)); assertThat(engine.segmentsStats(false, false).getTermVectorsMemoryInBytes(), equalTo(0L));
assertThat(engine.segmentsStats(false).getNormsMemoryInBytes(), assertThat(engine.segmentsStats(false, false).getNormsMemoryInBytes(),
greaterThan(stats.getNormsMemoryInBytes())); greaterThan(stats.getNormsMemoryInBytes()));
assertThat(engine.segmentsStats(false).getDocValuesMemoryInBytes(), assertThat(engine.segmentsStats(false, false).getDocValuesMemoryInBytes(),
greaterThan(stats.getDocValuesMemoryInBytes())); greaterThan(stats.getDocValuesMemoryInBytes()));
assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true)); assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
@ -349,7 +349,7 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(2)); assertThat(segments.size(), equalTo(2));
assertThat(engine.segmentsStats(false).getCount(), equalTo(2L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(2L));
assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true)); assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
assertThat(segments.get(0).isSearch(), equalTo(true)); assertThat(segments.get(0).isSearch(), equalTo(true));
@ -370,7 +370,7 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(3)); assertThat(segments.size(), equalTo(3));
assertThat(engine.segmentsStats(false).getCount(), equalTo(3L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(3L));
assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true)); assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
assertThat(segments.get(0).isSearch(), equalTo(true)); assertThat(segments.get(0).isSearch(), equalTo(true));
@ -397,7 +397,7 @@ public class InternalEngineTests extends EngineTestCase {
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(4)); assertThat(segments.size(), equalTo(4));
assertThat(engine.segmentsStats(false).getCount(), equalTo(4L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(4L));
assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true)); assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
assertThat(segments.get(0).isSearch(), equalTo(true)); assertThat(segments.get(0).isSearch(), equalTo(true));
@ -427,7 +427,7 @@ public class InternalEngineTests extends EngineTestCase {
engine.refresh("test"); engine.refresh("test");
segments = engine.segments(false); segments = engine.segments(false);
assertThat(segments.size(), equalTo(4)); assertThat(segments.size(), equalTo(4));
assertThat(engine.segmentsStats(false).getCount(), equalTo(4L)); assertThat(engine.segmentsStats(false, false).getCount(), equalTo(4L));
assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true)); assertThat(segments.get(0).getGeneration() < segments.get(1).getGeneration(), equalTo(true));
assertThat(segments.get(0).isCommitted(), equalTo(true)); assertThat(segments.get(0).isCommitted(), equalTo(true));
assertThat(segments.get(0).isSearch(), equalTo(true)); assertThat(segments.get(0).isSearch(), equalTo(true));
@ -572,13 +572,13 @@ public class InternalEngineTests extends EngineTestCase {
public void testSegmentsStatsIncludingFileSizes() throws Exception { public void testSegmentsStatsIncludingFileSizes() throws Exception {
try (Store store = createStore(); try (Store store = createStore();
Engine engine = createEngine(defaultSettings, store, createTempDir(), NoMergePolicy.INSTANCE)) { Engine engine = createEngine(defaultSettings, store, createTempDir(), NoMergePolicy.INSTANCE)) {
assertThat(engine.segmentsStats(true).getFileSizes().size(), equalTo(0)); assertThat(engine.segmentsStats(true, false).getFileSizes().size(), equalTo(0));
ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), B_1, null); ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), B_1, null);
engine.index(indexForDoc(doc)); engine.index(indexForDoc(doc));
engine.refresh("test"); engine.refresh("test");
SegmentsStats stats = engine.segmentsStats(true); SegmentsStats stats = engine.segmentsStats(true, false);
assertThat(stats.getFileSizes().size(), greaterThan(0)); assertThat(stats.getFileSizes().size(), greaterThan(0));
assertThat(() -> stats.getFileSizes().valuesIt(), everyItem(greaterThan(0L))); assertThat(() -> stats.getFileSizes().valuesIt(), everyItem(greaterThan(0L)));
@ -588,7 +588,7 @@ public class InternalEngineTests extends EngineTestCase {
engine.index(indexForDoc(doc2)); engine.index(indexForDoc(doc2));
engine.refresh("test"); engine.refresh("test");
assertThat(engine.segmentsStats(true).getFileSizes().get(firstEntry.key), greaterThan(firstEntry.value)); assertThat(engine.segmentsStats(true, false).getFileSizes().get(firstEntry.key), greaterThan(firstEntry.value));
} }
} }
@ -3698,23 +3698,23 @@ public class InternalEngineTests extends EngineTestCase {
NoMergePolicy.INSTANCE, null, null, globalCheckpoint::get); NoMergePolicy.INSTANCE, null, null, globalCheckpoint::get);
try (Store store = createStore(newFSDirectory(storeDir)); Engine engine = createEngine(configSupplier.apply(store))) { try (Store store = createStore(newFSDirectory(storeDir)); Engine engine = createEngine(configSupplier.apply(store))) {
assertEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP, assertEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP,
engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
final ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), final ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(),
new BytesArray("{}".getBytes(Charset.defaultCharset())), null); new BytesArray("{}".getBytes(Charset.defaultCharset())), null);
engine.index(appendOnlyPrimary(doc, true, timestamp1)); engine.index(appendOnlyPrimary(doc, true, timestamp1));
assertEquals(timestamp1, engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); assertEquals(timestamp1, engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
} }
try (Store store = createStore(newFSDirectory(storeDir)); try (Store store = createStore(newFSDirectory(storeDir));
InternalEngine engine = new InternalEngine(configSupplier.apply(store))) { InternalEngine engine = new InternalEngine(configSupplier.apply(store))) {
assertEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP, assertEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP,
engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
engine.initializeMaxSeqNoOfUpdatesOrDeletes(); engine.initializeMaxSeqNoOfUpdatesOrDeletes();
engine.recoverFromTranslog(translogHandler, Long.MAX_VALUE); engine.recoverFromTranslog(translogHandler, Long.MAX_VALUE);
assertEquals(timestamp1, engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); assertEquals(timestamp1, engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
final ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(), final ParsedDocument doc = testParsedDocument("1", null, testDocumentWithTextField(),
new BytesArray("{}".getBytes(Charset.defaultCharset())), null); new BytesArray("{}".getBytes(Charset.defaultCharset())), null);
engine.index(appendOnlyPrimary(doc, true, timestamp2)); engine.index(appendOnlyPrimary(doc, true, timestamp2));
assertEquals(maxTimestamp12, engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); assertEquals(maxTimestamp12, engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
globalCheckpoint.set(1); // make sure flush cleans up commits for later. globalCheckpoint.set(1); // make sure flush cleans up commits for later.
engine.flush(); engine.flush();
} }
@ -3725,7 +3725,7 @@ public class InternalEngineTests extends EngineTestCase {
store.associateIndexWithNewTranslog(translogUUID); store.associateIndexWithNewTranslog(translogUUID);
} }
try (Engine engine = new InternalEngine(configSupplier.apply(store))) { try (Engine engine = new InternalEngine(configSupplier.apply(store))) {
assertEquals(maxTimestamp12, engine.segmentsStats(false).getMaxUnsafeAutoIdTimestamp()); assertEquals(maxTimestamp12, engine.segmentsStats(false, false).getMaxUnsafeAutoIdTimestamp());
} }
} }
} }

View File

@ -229,8 +229,8 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
IndexShard replica = shards.addReplica(); IndexShard replica = shards.addReplica();
shards.recoverReplica(replica); shards.recoverReplica(replica);
SegmentsStats segmentsStats = replica.segmentStats(false); SegmentsStats segmentsStats = replica.segmentStats(false, false);
SegmentsStats primarySegmentStats = shards.getPrimary().segmentStats(false); SegmentsStats primarySegmentStats = shards.getPrimary().segmentStats(false, false);
assertNotEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP, primarySegmentStats.getMaxUnsafeAutoIdTimestamp()); assertNotEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP, primarySegmentStats.getMaxUnsafeAutoIdTimestamp());
assertEquals(primarySegmentStats.getMaxUnsafeAutoIdTimestamp(), segmentsStats.getMaxUnsafeAutoIdTimestamp()); assertEquals(primarySegmentStats.getMaxUnsafeAutoIdTimestamp(), segmentsStats.getMaxUnsafeAutoIdTimestamp());
assertNotEquals(Long.MAX_VALUE, segmentsStats.getMaxUnsafeAutoIdTimestamp()); assertNotEquals(Long.MAX_VALUE, segmentsStats.getMaxUnsafeAutoIdTimestamp());

View File

@ -3314,7 +3314,7 @@ public class IndexShardTests extends IndexShardTestCase {
indexDoc(primary, "_doc", "0", "{\"foo\" : \"foo\"}"); indexDoc(primary, "_doc", "0", "{\"foo\" : \"foo\"}");
primary.refresh("forced refresh"); primary.refresh("forced refresh");
SegmentsStats ss = primary.segmentStats(randomBoolean()); SegmentsStats ss = primary.segmentStats(randomBoolean(), randomBoolean());
CircuitBreaker breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); CircuitBreaker breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
assertThat(ss.getMemoryInBytes(), equalTo(breaker.getUsed())); assertThat(ss.getMemoryInBytes(), equalTo(breaker.getUsed()));
final long preRefreshBytes = ss.getMemoryInBytes(); final long preRefreshBytes = ss.getMemoryInBytes();
@ -3323,13 +3323,13 @@ public class IndexShardTests extends IndexShardTestCase {
indexDoc(primary, "_doc", "2", "{\"foo\" : \"baz\"}"); indexDoc(primary, "_doc", "2", "{\"foo\" : \"baz\"}");
indexDoc(primary, "_doc", "3", "{\"foo\" : \"eggplant\"}"); indexDoc(primary, "_doc", "3", "{\"foo\" : \"eggplant\"}");
ss = primary.segmentStats(randomBoolean()); ss = primary.segmentStats(randomBoolean(), randomBoolean());
breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
assertThat(preRefreshBytes, equalTo(breaker.getUsed())); assertThat(preRefreshBytes, equalTo(breaker.getUsed()));
primary.refresh("refresh"); primary.refresh("refresh");
ss = primary.segmentStats(randomBoolean()); ss = primary.segmentStats(randomBoolean(), randomBoolean());
breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
assertThat(breaker.getUsed(), equalTo(ss.getMemoryInBytes())); assertThat(breaker.getUsed(), equalTo(ss.getMemoryInBytes()));
assertThat(breaker.getUsed(), greaterThan(preRefreshBytes)); assertThat(breaker.getUsed(), greaterThan(preRefreshBytes));
@ -3339,7 +3339,7 @@ public class IndexShardTests extends IndexShardTestCase {
// Forces a refresh with the INTERNAL scope // Forces a refresh with the INTERNAL scope
((InternalEngine) primary.getEngine()).writeIndexingBuffer(); ((InternalEngine) primary.getEngine()).writeIndexingBuffer();
ss = primary.segmentStats(randomBoolean()); ss = primary.segmentStats(randomBoolean(), randomBoolean());
breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
assertThat(breaker.getUsed(), equalTo(ss.getMemoryInBytes())); assertThat(breaker.getUsed(), equalTo(ss.getMemoryInBytes()));
assertThat(breaker.getUsed(), greaterThan(preRefreshBytes)); assertThat(breaker.getUsed(), greaterThan(preRefreshBytes));
@ -3356,7 +3356,7 @@ public class IndexShardTests extends IndexShardTestCase {
} }
primary.refresh("force refresh"); primary.refresh("force refresh");
ss = primary.segmentStats(randomBoolean()); ss = primary.segmentStats(randomBoolean(), randomBoolean());
breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
assertThat(breaker.getUsed(), lessThan(postRefreshBytes)); assertThat(breaker.getUsed(), lessThan(postRefreshBytes));
@ -3447,7 +3447,7 @@ public class IndexShardTests extends IndexShardTestCase {
IOUtils.close(searchers); IOUtils.close(searchers);
primary.refresh("test"); primary.refresh("test");
SegmentsStats ss = primary.segmentStats(randomBoolean()); SegmentsStats ss = primary.segmentStats(randomBoolean(), randomBoolean());
CircuitBreaker breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING); CircuitBreaker breaker = primary.circuitBreakerService.getBreaker(CircuitBreaker.ACCOUNTING);
long segmentMem = ss.getMemoryInBytes(); long segmentMem = ss.getMemoryInBytes();
long breakerMem = breaker.getUsed(); long breakerMem = breaker.getUsed();

View File

@ -454,7 +454,7 @@ public class RecoverySourceHandlerTests extends ESTestCase {
final StartRecoveryRequest request = getStartRecoveryRequest(); final StartRecoveryRequest request = getStartRecoveryRequest();
final IndexShard shard = mock(IndexShard.class); final IndexShard shard = mock(IndexShard.class);
when(shard.seqNoStats()).thenReturn(mock(SeqNoStats.class)); when(shard.seqNoStats()).thenReturn(mock(SeqNoStats.class));
when(shard.segmentStats(anyBoolean())).thenReturn(mock(SegmentsStats.class)); when(shard.segmentStats(anyBoolean(), anyBoolean())).thenReturn(mock(SegmentsStats.class));
when(shard.isRelocatedPrimary()).thenReturn(true); when(shard.isRelocatedPrimary()).thenReturn(true);
when(shard.acquireSafeIndexCommit()).thenReturn(mock(Engine.IndexCommitRef.class)); when(shard.acquireSafeIndexCommit()).thenReturn(mock(Engine.IndexCommitRef.class));
doAnswer(invocation -> { doAnswer(invocation -> {

View File

@ -20,6 +20,7 @@ import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.PointValues; import org.apache.lucene.index.PointValues;
import org.apache.lucene.index.SegmentCommitInfo; import org.apache.lucene.index.SegmentCommitInfo;
import org.apache.lucene.index.SegmentReader;
import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.index.SortedNumericDocValues; import org.apache.lucene.index.SortedNumericDocValues;
import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.index.SortedSetDocValues;
@ -68,6 +69,7 @@ import java.util.function.Function;
public final class FrozenEngine extends ReadOnlyEngine { public final class FrozenEngine extends ReadOnlyEngine {
public static final Setting<Boolean> INDEX_FROZEN = Setting.boolSetting("index.frozen", false, Setting.Property.IndexScope, public static final Setting<Boolean> INDEX_FROZEN = Setting.boolSetting("index.frozen", false, Setting.Property.IndexScope,
Setting.Property.PrivateIndex); Setting.Property.PrivateIndex);
private final SegmentsStats stats;
private volatile DirectoryReader lastOpenedReader; private volatile DirectoryReader lastOpenedReader;
private final DirectoryReader canMatchReader; private final DirectoryReader canMatchReader;
@ -79,6 +81,13 @@ public final class FrozenEngine extends ReadOnlyEngine {
try (DirectoryReader reader = DirectoryReader.open(directory)) { try (DirectoryReader reader = DirectoryReader.open(directory)) {
canMatchReader = ElasticsearchDirectoryReader.wrap(new RewriteCachingDirectoryReader(directory, reader.leaves()), canMatchReader = ElasticsearchDirectoryReader.wrap(new RewriteCachingDirectoryReader(directory, reader.leaves()),
config.getShardId()); config.getShardId());
// we record the segment stats here - that's what the reader needs when it's open and it give the user
// an idea of what it can save when it's closed
this.stats = new SegmentsStats();
for (LeafReaderContext ctx : reader.getContext().leaves()) {
SegmentReader segmentReader = Lucene.segmentReader(ctx.reader());
fillSegmentStats(segmentReader, true, stats);
}
success = true; success = true;
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
@ -585,6 +594,21 @@ public final class FrozenEngine extends ReadOnlyEngine {
} }
} }
@Override
public SegmentsStats segmentsStats(boolean includeSegmentFileSizes, boolean includeUnloadedSegments) {
if (includeUnloadedSegments) {
final SegmentsStats stats = new SegmentsStats();
stats.add(this.stats);
if (includeSegmentFileSizes == false) {
stats.clearFileSizes();
}
return stats;
} else {
return super.segmentsStats(includeSegmentFileSizes, includeUnloadedSegments);
}
}
synchronized boolean isReaderOpen() { synchronized boolean isReaderOpen() {
return lastOpenedReader != null; return lastOpenedReader != null;
} // this is mainly for tests } // this is mainly for tests

View File

@ -117,16 +117,18 @@ public class FrozenEngineTests extends EngineTestCase {
listener.reset(); listener.reset();
try (FrozenEngine frozenEngine = new FrozenEngine(engine.engineConfig)) { try (FrozenEngine frozenEngine = new FrozenEngine(engine.engineConfig)) {
Engine.Searcher searcher = frozenEngine.acquireSearcher("test"); Engine.Searcher searcher = frozenEngine.acquireSearcher("test");
SegmentsStats segmentsStats = frozenEngine.segmentsStats(randomBoolean()); SegmentsStats segmentsStats = frozenEngine.segmentsStats(randomBoolean(), false);
assertEquals(frozenEngine.segments(randomBoolean()).size(), segmentsStats.getCount()); assertEquals(frozenEngine.segments(randomBoolean()).size(), segmentsStats.getCount());
FrozenEngine.unwrapLazyReader(searcher.getDirectoryReader()).release(); FrozenEngine.unwrapLazyReader(searcher.getDirectoryReader()).release();
assertEquals(1, listener.afterRefresh.get()); assertEquals(1, listener.afterRefresh.get());
segmentsStats = frozenEngine.segmentsStats(randomBoolean()); segmentsStats = frozenEngine.segmentsStats(randomBoolean(), false);
assertEquals(0, segmentsStats.getCount()); assertEquals(0, segmentsStats.getCount());
segmentsStats = frozenEngine.segmentsStats(randomBoolean(), true);
assertEquals(frozenEngine.segments(randomBoolean()).size(), segmentsStats.getCount());
assertEquals(1, listener.afterRefresh.get()); assertEquals(1, listener.afterRefresh.get());
assertFalse(frozenEngine.isReaderOpen()); assertFalse(frozenEngine.isReaderOpen());
FrozenEngine.unwrapLazyReader(searcher.getDirectoryReader()).reset(); FrozenEngine.unwrapLazyReader(searcher.getDirectoryReader()).reset();
segmentsStats = frozenEngine.segmentsStats(randomBoolean()); segmentsStats = frozenEngine.segmentsStats(randomBoolean(), false);
assertEquals(frozenEngine.segments(randomBoolean()).size(), segmentsStats.getCount()); assertEquals(frozenEngine.segments(randomBoolean()).size(), segmentsStats.getCount());
searcher.close(); searcher.close();
} }