You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ng...@apache.org on 2021/09/21 07:39:02 UTC
[jackrabbit-oak] branch trunk updated: OAK-9566 | Improve index
stats (#372)
This is an automated email from the ASF dual-hosted git repository.
ngupta pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new d05c9b9 OAK-9566 | Improve index stats (#372)
d05c9b9 is described below
commit d05c9b9e29f252ede85ec42e3e812b59b08f7c33
Author: nit0906 <ni...@gmail.com>
AuthorDate: Tue Sep 21 13:08:57 2021 +0530
OAK-9566 | Improve index stats (#372)
* OAK-9566 | Improve index stats
-Added support for Json format
-Fixed issue with local index dir size - currently with composite node store - it was just reporting size of read only mount
-Added new stats for indexCreationTimestamp, ReindexCompletionTimestamp, suggestDirSize, If the index has hidden
property index node and if it has a hidden read only libs mount.
---
.../jackrabbit/oak/plugins/index/IndexInfo.java | 32 ++++
.../oak/plugins/index/IndexInfoServiceImpl.java | 25 +++
.../oak/plugins/index/inventory/IndexPrinter.java | 186 ++++++++++++++++-----
.../index/property/PropertyIndexInfoProvider.java | 25 +++
.../plugins/index/inventory/IndexPrinterTest.java | 85 +++++++++-
.../index/lucene/LuceneIndexInfoProvider.java | 84 +++++++++-
.../oak/plugins/index/search/IndexDefinition.java | 11 ++
7 files changed, 397 insertions(+), 51 deletions(-)
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java
index b18619d..d4fcebf 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java
@@ -90,4 +90,36 @@ public interface IndexInfo {
*/
@Nullable
String getIndexDefinitionDiff();
+
+ /**
+ * Determines if a hidden oak libs mount node is present
+ * @return true in case of composite node store with indexed content from read-only part of repository, false otherwise
+ */
+ boolean hasHiddenOakLibsMount();
+
+ /**
+ *Determines if :property-index node is present
+ * @return true if the index is hybrid and has :property-index node, false otherwise.
+ */
+ boolean hasPropertyIndexNode();
+
+ /**
+ * Index suggest data storage size
+ * @return storage size or -1 if unknown
+ */
+ long getSuggestSizeInBytes();
+
+ /**
+ * Time in millis at which index definition was created
+ *
+ * @return time in millis or -1 if unknown
+ */
+ long getCreationTimestamp();
+
+ /**
+ * Time in millis at which index was last re indexed
+ *
+ * @return time in millis or -1 if unknown
+ */
+ long getReindexCompletionTimestamp();
}
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java
index 4ecbc04..a4e501f 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java
@@ -178,5 +178,30 @@ public class IndexInfoServiceImpl implements IndexInfoService{
public String getIndexDefinitionDiff() {
return null;
}
+
+ @Override
+ public boolean hasHiddenOakLibsMount() {
+ return false;
+ }
+
+ @Override
+ public boolean hasPropertyIndexNode() {
+ return false;
+ }
+
+ @Override
+ public long getSuggestSizeInBytes() {
+ return -1;
+ }
+
+ @Override
+ public long getCreationTimestamp() {
+ return -1;
+ }
+
+ @Override
+ public long getReindexCompletionTimestamp() {
+ return -1;
+ }
}
}
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinter.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinter.java
index 8487c2a..332ff85 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinter.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinter.java
@@ -20,8 +20,11 @@
package org.apache.jackrabbit.oak.plugins.index.inventory;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
+import java.util.Date;
import java.util.List;
+import java.util.TimeZone;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
@@ -31,6 +34,7 @@ import org.apache.felix.inventory.Format;
import org.apache.felix.inventory.InventoryPrinter;
import org.apache.jackrabbit.oak.api.jmx.IndexStatsMBean;
import org.apache.jackrabbit.oak.commons.IOUtils;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfo;
import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoService;
import org.apache.jackrabbit.oak.plugins.index.IndexInfo;
@@ -44,9 +48,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Component(
service = InventoryPrinter.class,
property = {
- "felix.inventory.printer.name=oak-index-stats",
- "felix.inventory.printer.title=Oak Index Stats",
- "felix.inventory.printer.format=TEXT"
+ "felix.inventory.printer.name=oak-index-stats",
+ "felix.inventory.printer.title=Oak Index Stats",
+ "felix.inventory.printer.format=TEXT",
+ "felix.inventory.printer.format=JSON"
})
public class IndexPrinter implements InventoryPrinter {
@@ -66,97 +71,200 @@ public class IndexPrinter implements InventoryPrinter {
@Override
public void print(PrintWriter pw, Format format, boolean isZip) {
- //TODO Highlight if failing
- printAsyncIndexInfo(pw);
- printIndexInfo(pw);
+
+ if (format == Format.JSON) {
+ JsopBuilder json = new JsopBuilder();
+ startJsonObject(json);
+ printAsyncIndexInfo(pw, json, format);
+ printIndexInfo(pw, json, format);
+ endJsonObject(json);
+ pw.print(JsopBuilder.prettyPrint(json.toString()));
+ } else {
+ //TODO Highlight if failing
+ printAsyncIndexInfo(pw, null, format);
+ printIndexInfo(pw, null, format);
+ }
}
- private void printAsyncIndexInfo(PrintWriter pw) {
+ private void printAsyncIndexInfo(PrintWriter pw, JsopBuilder json, Format format) {
List<String> asyncLanes = ImmutableList.copyOf(asyncIndexInfoService.getAsyncLanes());
String title = "Async Indexers State";
- printTitle(pw, title);
- pw.printf("Number of async indexer lanes : %d%n", asyncLanes.size());
- pw.println();
+ printTitle(pw, title, format);
+ addJsonKey(json, title);
+ startJsonObject(json);
+ keyValue("Number of async indexer lanes ", asyncLanes.size(), pw, json, format);
+ printWithNewLine(pw, "", format);
+
for (String lane : asyncLanes) {
- pw.println(lane);
+ printWithNewLine(pw, lane, format);
+ addJsonKey(json, lane);
AsyncIndexInfo info = asyncIndexInfoService.getInfo(lane);
+ startJsonObject(json);
if (info != null) {
- pw.printf(" Last indexed to : %s%n", formatTime(info.getLastIndexedTo()));
+ keyValue(" Last indexed to ", formatTime(info.getLastIndexedTo()), pw, json, format);
IndexStatsMBean stats = info.getStatsMBean();
if (stats != null) {
- pw.printf(" Status : %s%n", stats.getStatus());
- pw.printf(" Failing : %s%n", stats.isFailing());
- pw.printf(" Paused : %s%n", stats.isPaused());
+ keyValue(" Status ", stats.getStatus(), pw, json, format);
+ keyValue(" Failing ", stats.isFailing(), pw, json, format);
+ keyValue(" Paused ", stats.isPaused(), pw, json, format);
if (stats.isFailing()) {
- pw.printf(" Failing since : %s%n", stats.getFailingSince());
- pw.printf(" Latest error : %s%n", stats.getLatestError());
+ keyValue(" Failing since ", stats.getFailingSince(), pw, json, format);
+ keyValue(" Latest error ", stats.getLatestError(), pw, json, format);
}
}
- pw.println();
+ printWithNewLine(pw, "", format);
}
+ endJsonObject(json);
}
+ endJsonObject(json);
}
- private static void printTitle(PrintWriter pw, String title) {
- pw.println(title);
- pw.println(Strings.repeat("=", title.length()));
+ private static void printTitle(PrintWriter pw, String title, Format format) {
+ if (format == Format.TEXT) {
+ pw.println(title);
+ pw.println(Strings.repeat("=", title.length()));
+ pw.println();
+ }
}
- private void printIndexInfo(PrintWriter pw) {
+ private static void printWithNewLine(PrintWriter pw, String printLine, Format format) {
+ if (format == Format.TEXT) {
+ pw.println(printLine);
+ }
+ }
+
+ private void printIndexInfo(PrintWriter pw, JsopBuilder json, Format format) {
ListMultimap<String, IndexInfo> infos = ArrayListMultimap.create();
for (IndexInfo info : indexInfoService.getAllIndexInfo()) {
infos.put(info.getType(), info);
}
- pw.printf("Total number of indexes : %d%n", infos.size());
+ keyValue("Total number of indexes ", infos.size(), pw, json, format);
+
for (String type : infos.keySet()){
List<IndexInfo> typedInfo = infos.get(type);
String title = String.format("%s(%d)", type, typedInfo.size());
- printTitle(pw, title);
- pw.println();
+ printTitle(pw, title, format);
+ addJsonKey(json, type);
+ startJsonObject(json);
for (IndexInfo info : typedInfo){
- printIndexInfo(pw, info);
+ printIndexInfo(pw, json, info, format);
}
+ endJsonObject(json);
}
}
- private static void printIndexInfo(PrintWriter pw, IndexInfo info) {
- pw.println(info.getIndexPath());
- pw.printf(" Type : %s%n", info.getType());
+
+ private static void printIndexInfo(PrintWriter pw, JsopBuilder json, IndexInfo info, Format format) {
+ if (format == Format.TEXT) {
+ pw.println(info.getIndexPath());
+ }
+ addJsonKey(json, info.getIndexPath());
+ startJsonObject(json);
+
+ keyValue(" Type ", info.getType(), pw, json, format);
if (info.getAsyncLaneName() != null) {
- pw.printf(" Async : true%n");
- pw.printf(" Async lane name : %s%n", info.getAsyncLaneName());
+ keyValue(" Async ", true, pw, json, format);
+ keyValue(" Async lane name ", info.getAsyncLaneName(), pw, json, format);
}
if (info.getIndexedUpToTime() > 0){
- pw.printf(" Last indexed up to : %s%n", formatTime(info.getIndexedUpToTime()));
+ keyValue(" Last indexed up to ", formatTime(info.getIndexedUpToTime()), pw, json, format);
}
if (info.getLastUpdatedTime() > 0){
- pw.printf(" Last updated time : %s%n", formatTime(info.getLastUpdatedTime()));
+ keyValue(" Last updated time ", formatTime(info.getLastUpdatedTime()), pw, json, format);
+ }
+
+ if (info.getCreationTimestamp() > 0){
+ keyValue(" Creation time ", formatTime(info.getCreationTimestamp()), pw, json, format);
+ }
+
+ if (info.getReindexCompletionTimestamp() > 0){
+ keyValue(" Reindex completion time ", formatTime(info.getReindexCompletionTimestamp()), pw, json, format);
}
if (info.getSizeInBytes() >= 0){
- pw.printf(" Size : %s%n", IOUtils.humanReadableByteCount(info.getSizeInBytes()));
+ keyValue(" Size ", IOUtils.humanReadableByteCount(info.getSizeInBytes()), pw, json, format);
+ keyValue(" Size (in Bytes) ", info.getSizeInBytes(), pw, json, format);
+ }
+
+ if (info.getSuggestSizeInBytes() >= 0){
+ keyValue(" Suggest size ", IOUtils.humanReadableByteCount(info.getSuggestSizeInBytes()), pw, json, format);
+ keyValue(" Suggest size (in Bytes) ", info.getSuggestSizeInBytes(), pw, json, format);
}
if (info.getEstimatedEntryCount() >= 0){
- pw.printf(" Estimated entry count : %d%n", info.getEstimatedEntryCount());
+ keyValue(" Estimated entry count ", info.getEstimatedEntryCount(), pw, json, format);
+ }
+
+ if ("lucene".equals(info.getType())) {
+ // Only valid for lucene type indexes, for others it will simply show false.
+ keyValue(" Has hidden oak mount ", info.hasHiddenOakLibsMount(), pw, json, format);
+ keyValue(" Has property index ", info.hasPropertyIndexNode(), pw, json, format);
}
if (info.hasIndexDefinitionChangedWithoutReindexing()) {
- pw.println(" Index definition changed without reindexing");
String diff = info.getIndexDefinitionDiff();
if (diff != null) {
- pw.println(" "+diff);
+ keyValue(" Index definition changed without reindexing ", diff, pw, json, format);
+ printWithNewLine(pw, "", format);
}
}
- pw.println();
+ endJsonObject(json);
}
private static String formatTime(long time){
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(time);
- return ISO8601.format(cal);
+ Date date = cal.getTime();
+ SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ outputFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return outputFmt.format(date);
+ }
+
+ private static void keyValue(String key, Object value, PrintWriter pw, JsopBuilder json, Format format) {
+ // In case the key is null or an empty String,
+ // throw an IllegalArgumentException.
+ if (key == null || key.equals("")) {
+ throw new IllegalArgumentException("Unsupported key - can't be null/empty");
+ }
+
+ if (format == Format.JSON) {
+ json.key(key.trim());
+ if (value instanceof String) {
+ json.value((String)value);
+ } else if (value instanceof Long) {
+ json.value((Long)value);
+ } else if (value instanceof Boolean) {
+ json.value((Boolean)value);
+ } else if (value instanceof Integer) {
+ json.value((Integer) value);
+ } else {
+ throw new IllegalArgumentException("Unsupported type of value while creating the json output");
+ }
+ } else if (format == Format.TEXT) {
+ pw.printf(key+":%s%n",value);
+ }
+ }
+
+ // Wrappers around JsonBuilder that will result in NOOP if builder is null -
+ // These are just to avoid the multiple if/else check while handling for both TEXT and JSON formats
+ private static void startJsonObject(JsopBuilder json) {
+ if (json != null) {
+ json.object();
+ }
+ }
+
+ private static void endJsonObject(JsopBuilder json) {
+ if (json != null) {
+ json.endObject();
+ }
+ }
+
+ private static void addJsonKey(JsopBuilder json, String key) {
+ if (json != null) {
+ json.key(key);
+ }
}
}
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexInfoProvider.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexInfoProvider.java
index 53a1d29..69da859 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexInfoProvider.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexInfoProvider.java
@@ -145,5 +145,30 @@ public class PropertyIndexInfoProvider implements IndexInfoProvider {
public String getIndexDefinitionDiff() {
return null;
}
+
+ @Override
+ public boolean hasHiddenOakLibsMount() {
+ return false;
+ }
+
+ @Override
+ public boolean hasPropertyIndexNode() {
+ return false;
+ }
+
+ @Override
+ public long getSuggestSizeInBytes() {
+ return -1;
+ }
+
+ @Override
+ public long getCreationTimestamp() {
+ return -1;
+ }
+
+ @Override
+ public long getReindexCompletionTimestamp() {
+ return -1;
+ }
}
}
diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinterTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinterTest.java
index a7225b9..0f19469 100644
--- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinterTest.java
+++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/inventory/IndexPrinterTest.java
@@ -21,8 +21,10 @@ package org.apache.jackrabbit.oak.plugins.index.inventory;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.Map;
import org.apache.felix.inventory.Format;
+import org.apache.jackrabbit.oak.commons.json.JsonObject;
import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfo;
import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoService;
import org.apache.jackrabbit.oak.plugins.index.IndexInfo;
@@ -31,8 +33,11 @@ import org.junit.Test;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -49,12 +54,31 @@ public class IndexPrinterTest {
when(asyncInfo.getInfo("foo-async"))
.thenReturn(new AsyncIndexInfo("foo-async", 0, 0, false, null));
- String output = getPrintOutput();
+ String output = getPrintOutput(Format.TEXT);
assertThat(output, containsString("foo-async"));
}
@Test
+ public void asyncIndexInfoJson() throws Exception {
+ when(indexInfo.getAllIndexInfo()).thenReturn(emptyList());
+ when(asyncInfo.getAsyncLanes()).thenReturn(asList("foo-async", "bar-async"));
+ when(asyncInfo.getInfo("foo-async"))
+ .thenReturn(new AsyncIndexInfo("foo-async", 0, 0, false, null));
+
+ String output = getPrintOutput(Format.JSON);
+
+ JsonObject json = JsonObject.fromJson(output, true);
+ Map<String, JsonObject> jsonMap = json.getChildren();
+ assertTrue(jsonMap.keySet().contains("Async Indexers State"));
+ int size = Integer.parseInt(jsonMap.get("Async Indexers State").getProperties().get("Number of async indexer lanes"));
+ assertEquals(2, size);
+
+ assertTrue(jsonMap.get("Async Indexers State").getChildren().keySet().contains("foo-async"));
+ assertTrue(jsonMap.get("Async Indexers State").getChildren().keySet().contains("bar-async"));
+ }
+
+ @Test
public void indexInfo() throws Exception{
when(asyncInfo.getAsyncLanes()).thenReturn(emptyList());
@@ -64,16 +88,42 @@ public class IndexPrinterTest {
when(indexInfo.getAllIndexInfo()).thenReturn(asList(info1, info2));
- String output = getPrintOutput();
+ String output = getPrintOutput(Format.TEXT);
assertThat(output, containsString("/oak:index/fooIndex"));
assertThat(output, containsString("/oak:index/barIndex"));
assertThat(output, containsString("async"));
}
- private String getPrintOutput() {
+ @Test
+ public void indexInfoJson() throws Exception{
+ when(asyncInfo.getAsyncLanes()).thenReturn(emptyList());
+
+ TestInfo info1 = new TestInfo("/oak:index/fooIndex", "property");
+ TestInfo info2 = new TestInfo("/oak:index/barIndex", "lucene");
+ info2.laneName = "async";
+
+ when(indexInfo.getAllIndexInfo()).thenReturn(asList(info1, info2));
+
+ String output = getPrintOutput(Format.JSON);
+ JsonObject json = JsonObject.fromJson(output, true);
+ Map<String, JsonObject> jsonMap = json.getChildren();
+ assertTrue(jsonMap.keySet().contains("Async Indexers State"));
+
+ assertEquals(0, jsonMap.get("Async Indexers State").getChildren().size());
+
+ assertTrue(jsonMap.keySet().contains("lucene"));
+ assertTrue(jsonMap.keySet().contains("property"));
+ assertTrue(jsonMap.get("lucene").getChildren().keySet().contains("/oak:index/barIndex"));
+ assertFalse(jsonMap.get("lucene").getChildren().keySet().contains("/oak:index/fooIndex"));
+ assertTrue(jsonMap.get("property").getChildren().keySet().contains("/oak:index/fooIndex"));
+ assertFalse(jsonMap.get("property").getChildren().keySet().contains("/oak:index/barIndex"));
+
+ }
+
+ private String getPrintOutput(Format format) {
StringWriter sw = new StringWriter();
- printer.print(new PrintWriter(sw), Format.TEXT, false);
+ printer.print(new PrintWriter(sw), format, false);
return sw.toString();
}
@@ -131,6 +181,31 @@ public class IndexPrinterTest {
public String getIndexDefinitionDiff() {
return null;
}
+
+ @Override
+ public boolean hasHiddenOakLibsMount() {
+ return false;
+ }
+
+ @Override
+ public boolean hasPropertyIndexNode() {
+ return false;
+ }
+
+ @Override
+ public long getSuggestSizeInBytes() {
+ return 0;
+ }
+
+ @Override
+ public long getCreationTimestamp() {
+ return 0;
+ }
+
+ @Override
+ public long getReindexCompletionTimestamp() {
+ return 0;
+ }
}
}
\ No newline at end of file
diff --git a/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProvider.java b/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProvider.java
index 0397d34..3f8cde5 100644
--- a/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProvider.java
+++ b/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProvider.java
@@ -47,6 +47,7 @@ import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.spi.state.ReadOnlyBuilder;
import org.apache.jackrabbit.util.ISO8601;
+import org.apache.lucene.document.Field;
import org.apache.lucene.store.Directory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -85,8 +86,10 @@ public class LuceneIndexInfoProvider implements IndexInfoProvider {
LuceneIndexInfo info = new LuceneIndexInfo(indexPath);
computeSize(idxState, info);
computeIndexDefinitionChange(idxState, info);
- computeLastUpdatedTime(idxState, info);
+ computeStatusNodeInfo(idxState, info);
computeAsyncIndexInfo(idxState, indexPath, info);
+ checkIfHiddenNodesExists(idxState, info);
+ computeCreationTimestamp(idxState, info);
return info;
}
@@ -121,22 +124,59 @@ public class LuceneIndexInfoProvider implements IndexInfoProvider {
private void computeSize(NodeState idxState, LuceneIndexInfo info) throws IOException {
LuceneIndexDefinition defn = LuceneIndexDefinition.newBuilder(nodeStore.getRoot(), idxState, info.indexPath).build();
for (String dirName : idxState.getChildNodeNames()) {
- if (NodeStateUtils.isHidden(dirName) && MultiplexersLucene.isIndexDirName(dirName)) {
- try (Directory dir = new OakDirectory(new ReadOnlyBuilder(idxState), dirName, defn, true)) {
- info.numEntries += DirectoryUtils.getNumDocs(dir);
- info.size = DirectoryUtils.dirSize(dir);
+ if (NodeStateUtils.isHidden(dirName)) {
+ // This is true for both read-write index data dir (:data) and the read-only mount (:oak-libs-mount-index-data)
+ if (MultiplexersLucene.isIndexDirName(dirName)) {
+ try (Directory dir = new OakDirectory(new ReadOnlyBuilder(idxState), dirName, defn, true)) {
+ info.numEntries += DirectoryUtils.getNumDocs(dir);
+ info.size += DirectoryUtils.dirSize(dir);
+ }
+ } else if (MultiplexersLucene.isSuggestIndexDirName(dirName)) {
+ try (Directory dir = new OakDirectory(new ReadOnlyBuilder(idxState), dirName, defn, true)) {
+ info.suggestSize += DirectoryUtils.dirSize(dir);
+ }
}
}
}
}
- private static void computeLastUpdatedTime(NodeState idxState, LuceneIndexInfo info) {
+ private static void computeStatusNodeInfo(NodeState idxState, LuceneIndexInfo info) {
NodeState status = idxState.getChildNode(IndexDefinition.STATUS_NODE);
- if (status.exists()){
+ if (status.exists()) {
PropertyState updatedTime = status.getProperty(IndexDefinition.STATUS_LAST_UPDATED);
if (updatedTime != null) {
info.lastUpdatedTime = ISO8601.parse(updatedTime.getValue(Type.DATE)).getTimeInMillis();
}
+
+ PropertyState reindexCompletionTime = status.getProperty(IndexDefinition.REINDEX_COMPLETION_TIMESTAMP);
+ if (reindexCompletionTime != null) {
+ info.reindexCompletionTimestamp = ISO8601.parse(reindexCompletionTime.getValue(Type.DATE)).getTimeInMillis();
+ }
+ }
+ }
+
+ private static void computeCreationTimestamp(NodeState idxState, LuceneIndexInfo info) {
+ NodeState indexDef = idxState.getChildNode(INDEX_DEFINITION_NODE);
+ if (indexDef.exists()) {
+ PropertyState creationTime = indexDef.getProperty(IndexDefinition.CREATION_TIMESTAMP);
+ if (creationTime != null) {
+ info.creationTimestamp = ISO8601.parse(creationTime.getValue(Type.DATE)).getTimeInMillis();
+ }
+ }
+ }
+
+ private static void checkIfHiddenNodesExists(NodeState idxState, LuceneIndexInfo info) {
+ // Check for hidden oak libs mount node that has indexed content for read only repo in composite store
+ // Also check for hidden property index node :property-index - present in case of hybrid indexes
+ info.hasHiddenOakLibsMount = false;
+ info.hasPropertyIndexNode = false;
+
+ for(String c : idxState.getChildNodeNames()) {
+ if (c.startsWith(IndexDefinition.HIDDEN_OAK_MOUNT_PREFIX)) {
+ info.hasHiddenOakLibsMount = true;
+ } else if (c.equals(IndexDefinition.PROPERTY_INDEX)) {
+ info.hasPropertyIndexNode = true;
+ }
}
}
@@ -160,6 +200,11 @@ public class LuceneIndexInfoProvider implements IndexInfoProvider {
long lastUpdatedTime;
boolean indexDefinitionChanged;
String indexDiff;
+ boolean hasHiddenOakLibsMount;
+ boolean hasPropertyIndexNode;
+ long suggestSize;
+ long creationTimestamp;
+ long reindexCompletionTimestamp;
public LuceneIndexInfo(String indexPath) {
this.indexPath = indexPath;
@@ -209,6 +254,31 @@ public class LuceneIndexInfoProvider implements IndexInfoProvider {
public String getIndexDefinitionDiff() {
return indexDiff;
}
+
+ @Override
+ public boolean hasHiddenOakLibsMount() {
+ return hasHiddenOakLibsMount;
+ }
+
+ @Override
+ public boolean hasPropertyIndexNode() {
+ return hasPropertyIndexNode;
+ }
+
+ @Override
+ public long getSuggestSizeInBytes() {
+ return suggestSize;
+ }
+
+ @Override
+ public long getCreationTimestamp() {
+ return creationTimestamp;
+ }
+
+ @Override
+ public long getReindexCompletionTimestamp() {
+ return reindexCompletionTimestamp;
+ }
}
static class FilteringEqualsDiff extends EqualsDiff {
diff --git a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
index ec6bc80..f49895a 100644
--- a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
+++ b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
@@ -143,6 +143,17 @@ public class IndexDefinition implements Aggregate.AggregateMapper {
public static final String STATUS_NODE = ":status";
/**
+ * Hidden node under index definition that contains indexed data for read only
+ * part of composite node store.
+ */
+ public static final String HIDDEN_OAK_MOUNT_PREFIX = ":oak:mount-";
+
+ /**
+ * Node name under which all property indexes are created
+ */
+ public static final String PROPERTY_INDEX = ":property-index";
+
+ /**
* Property on status node which refers to the date when the index was lastUpdated
* This may not be the same time as when index was closed but the time of checkpoint
* upto which index is upto date (OAK-6194)