bhabegger commented on code in PR #3076:
URL: https://github.com/apache/jackrabbit-oak/pull/3076#discussion_r4059982732


##########
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java:
##########
@@ -135,18 +144,63 @@ Set<IndexStoreStrategy> getStrategies(NodeState 
definition) {
                 definition, INDEX_CONTENT_NODE_NAME);
     }
 
+    /**
+     * Dispatches to {@link #getCostConfigurable} or {@link #getCostLegacy}
+     * based on {@code disableConfigurableCosts}.
+     */
     public double getCost(Filter filter, String propertyName, PropertyValue 
value) {
+        return disableConfigurableCosts
+                ? getCostLegacy(filter, propertyName, value)
+                : getCostConfigurable(filter, propertyName, value);
+    }
+
+    /**
+     * Original cost formula: {@code COST_OVERHEAD + entryCount}. Ignores
+     * {@code costPerEntry}/{@code costPerExecution} even if set on the index
+     * definition.
+     */
+    public double getCostLegacy(Filter filter, String propertyName, 
PropertyValue value) {
+        NodeState indexMeta = getIndexNode(root, propertyName, filter);
+        if (indexMeta == null) {
+            return Double.POSITIVE_INFINITY;
+        }
+        return getCost(indexMeta, filter, value, COST_OVERHEAD, 1.0);
+    }
+
+    /**
+     * {@code cost = costPerExecution + costPerEntry * entryCount}, both
+     * optionally configured on the index definition (OAK-12348). Defaults
+     * ({@code costPerEntry=1.0}, {@code costPerExecution=COST_OVERHEAD})
+     * reproduce {@link #getCostLegacy} exactly.
+     */
+    public double getCostConfigurable(Filter filter, String propertyName, 
PropertyValue value) {
         NodeState indexMeta = getIndexNode(root, propertyName, filter);
         if (indexMeta == null) {
             return Double.POSITIVE_INFINITY;
         }
+        double costPerEntry = IndexUtils.getOptionalValue(indexMeta, 
IndexConstants.COST_PER_ENTRY, 1.0);
+        double costPerExecution = IndexUtils.getOptionalValue(indexMeta, 
IndexConstants.COST_PER_EXECUTION, COST_OVERHEAD);
+        return getCost(indexMeta, filter, value, costPerExecution, 
costPerEntry);
+    }
+
+    // Shared by getCostLegacy/getCostConfigurable, which only differ in
+    // costPerExecution/costPerEntry -- legacy hardcodes them, configurable
+    // reads them from indexMeta (which is why they can't be precomputed
+    // earlier than this: they depend on which property's index definition
+    // this call resolved, and the same PropertyIndexLookup is reused across
+    // different property names, e.g. by NodeTypeIndexLookup).
+    private double getCost(NodeState indexMeta, Filter filter, PropertyValue 
value,
+            double costPerExecution, double costPerEntry) {
         Set<IndexStoreStrategy> strategies = getStrategies(indexMeta);
+        if (strategies.isEmpty()) {
+            return MAX_COST;
+        }
         ValuePattern pattern = new ValuePattern(indexMeta);
-        double cost = strategies.isEmpty() ? MAX_COST : COST_OVERHEAD;
+        double entryCount = 0;
         for (IndexStoreStrategy s : strategies) {
-            cost += s.count(filter, root, indexMeta, encode(value, pattern), 
MAX_COST);
+            entryCount += s.count(filter, root, indexMeta, encode(value, 
pattern), MAX_COST);
         }
-        return cost;
+        return costPerExecution + costPerEntry * entryCount;

Review Comment:
   This is why I renamed all the misnamed `xxxCost` to `xxxCount`. We multiply 
the entry cost per count not per cost. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to