diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java index 0ab5829..770f6da 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java @@ -276,9 +276,19 @@ public class IndexUpdate implements Editor, PathSource { rootState.corruptIndexHandler.skippingCorruptIndex(rootState.async, indexPath, ISO8601.parse(corruptSince)); continue; } - - Editor editor = rootState.provider.getIndexEditor(type, definition, rootState.root, + Editor editor = null; + try { + editor = rootState.provider.getIndexEditor(type, definition, rootState.root, rootState.newCallback(indexPath, shouldReindex, getEstimatedCount(definition))); + } catch (IllegalStateException e) { + // This will be caught here in case there is any config related error in the index definition + // where multiple values are assigned to a property that is supposed to be single valued + // We log an error message here and continue - this way the bad index defintion is ignored and doesn't block the async index update + + log.error("Unable to get Index Editor for index at {} . Please correct the index definition " + + "and reindex after correction. Additional Info : {}", indexPath, e.getMessage(), e); + continue; + } if (editor == null) { // if this isn't an async cycle AND definition has "async" property // (and implicitly isIncluded method allows async def in non-async cycle only for nrt/sync defs) 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 b89d4ae..c0ce6bb 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 @@ -342,6 +342,8 @@ public class IndexDefinition implements Aggregate.AggregateMapper { } protected IndexDefinition(NodeState root, NodeState defn, IndexFormatVersion version, String uid, String indexPath) { + + try { this.root = root; this.version = checkNotNull(version); this.uid = uid; @@ -376,7 +378,7 @@ public class IndexDefinition implements Aggregate.AggregateMapper { if (defn.hasProperty(ENTRY_COUNT_PROPERTY_NAME)) { this.entryCountDefined = true; - this.entryCount = defn.getProperty(ENTRY_COUNT_PROPERTY_NAME).getValue(Type.LONG); + this.entryCount = getOptionalValue(defn, ENTRY_COUNT_PROPERTY_NAME, DEFAULT_ENTRY_COUNT); } else { this.entryCountDefined = false; this.entryCount = DEFAULT_ENTRY_COUNT; @@ -421,6 +423,12 @@ public class IndexDefinition implements Aggregate.AggregateMapper { this.syncPropertyIndexes = definedRules.stream().anyMatch(ir -> !ir.syncProps.isEmpty()); this.useIfExists = getOptionalValue(defn, IndexConstants.USE_IF_EXISTS, null); this.deprecated = getOptionalValue(defn, IndexConstants.INDEX_DEPRECATED, false); + + } catch (IllegalStateException e) { + log.error("Config error for index definition at {} . Please correct the index definition " + + "and reindex after correction. Additional Info : {}", indexPath, e.getMessage(), e); + throw new IllegalStateException(e); + } } public NodeState getDefinitionNodeState() { diff --git a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java index 23af20e..20eaebb 100644 --- a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java +++ b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java @@ -36,34 +36,71 @@ import static com.google.common.base.Preconditions.checkArgument; */ public class ConfigUtil { + private static final String ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE = "Multiple values provided for property %s in index definition . Single value was expected"; + public static boolean getOptionalValue(NodeState definition, String propName, boolean defaultVal) { + try { PropertyState ps = definition.getProperty(propName); return ps == null ? defaultVal : ps.getValue(Type.BOOLEAN); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } } public static int getOptionalValue(NodeState definition, String propName, int defaultVal) { + try { PropertyState ps = definition.getProperty(propName); return ps == null ? defaultVal : Ints.checkedCast(ps.getValue(Type.LONG)); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } } public static String getOptionalValue(NodeState definition, String propName, String defaultVal) { + try { PropertyState ps = definition.getProperty(propName); return ps == null ? defaultVal : ps.getValue(Type.STRING); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } } public static float getOptionalValue(NodeState definition, String propName, float defaultVal) { + try { PropertyState ps = definition.getProperty(propName); return ps == null ? defaultVal : ps.getValue(Type.DOUBLE).floatValue(); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } } public static double getOptionalValue(NodeState definition, String propName, double defaultVal) { + try { PropertyState ps = definition.getProperty(propName); return ps == null ? defaultVal : ps.getValue(Type.DOUBLE); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } + + } + + public static long getOptionalValue(NodeState definition, String propName, long defaultVal) { + try { + PropertyState ps = definition.getProperty(propName); + return ps == null ? defaultVal : ps.getValue(Type.LONG); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, propName),e); + } + } public static String getPrimaryTypeName(NodeState nodeState) { + try { PropertyState ps = nodeState.getProperty(JcrConstants.JCR_PRIMARYTYPE); return (ps == null) ? JcrConstants.NT_BASE : ps.getValue(Type.NAME); + } catch (IllegalStateException e) { + throw new IllegalStateException(String.format(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE, JcrConstants.JCR_PRIMARYTYPE),e); + } } public static Iterable getMixinNames(NodeState nodeState) {