Skip to content

Commit

Permalink
Split creation of the Set to match unknown properties to avoid Method…
Browse files Browse the repository at this point in the history
…TooLargeException
  • Loading branch information
radcortez committed Nov 22, 2024
1 parent 26db59d commit 1db73a7
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public String getId() {
}

// ConfigMapping
ConfigClass mapping = readResult.getAllMappings().get(entry.getKey());
ConfigClass mapping = readResult.getAllMappingsByClass().get(entry.getKey());
if (mapping != null) {
mappingClasses.put(entry.getValue(), mapping);
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,9 @@ ReadResult run() {
objectsByClass.put(mapping.getKlass(), config.getConfigMapping(mapping.getKlass(), mapping.getPrefix()));
}

Set<PropertyName> buildTimeNames = getMappingsNames(buildTimeMappings);
Set<PropertyName> buildTimeRunTimeNames = getMappingsNames(buildTimeRunTimeMappings);
Set<PropertyName> runTimeNames = getMappingsNames(runTimeMappings);
Set<PropertyName> buildTimeNames = mappingsToNames(buildTimeMappings).keySet();
Set<PropertyName> buildTimeRunTimeNames = mappingsToNames(buildTimeRunTimeMappings).keySet();
Set<PropertyName> runTimeNames = mappingsToNames(runTimeMappings).keySet();
for (String property : allProperties) {
PropertyName name = new PropertyName(property);
if (buildTimeNames.contains(name)) {
Expand Down Expand Up @@ -1222,12 +1222,32 @@ private static void getDefaults(
}
}

private static Set<PropertyName> getMappingsNames(final List<ConfigClass> configMappings) {
private static Map<PropertyName, String> mappingsToNames(final List<ConfigClass> configMappings) {
Set<String> names = new HashSet<>();
for (ConfigClass configMapping : configMappings) {
names.addAll(ConfigMappings.getProperties(configMapping).keySet());
}
return PropertiesUtil.toPropertyNames(names);
Map<PropertyName, String> propertyNames = new HashMap<>();
for (String name : names) {
PropertyName propertyName = new PropertyName(name);
if (propertyNames.containsKey(propertyName)) {
String existing = propertyNames.remove(propertyName);
if (existing.length() < name.length()) {
propertyNames.put(new PropertyName(existing), existing);
} else if (existing.length() > name.length()) {
propertyNames.put(propertyName, name);
} else {
if (existing.indexOf('*') <= name.indexOf('*')) {
propertyNames.put(new PropertyName(existing), existing);
} else {
propertyNames.put(propertyName, name);
}
}
} else {
propertyNames.put(propertyName, name);
}
}
return propertyNames;
}
}

Expand All @@ -1249,7 +1269,9 @@ public static final class ReadResult {
final List<ConfigClass> buildTimeMappings;
final List<ConfigClass> buildTimeRunTimeMappings;
final List<ConfigClass> runTimeMappings;
final Map<Class<?>, ConfigClass> allMappings;
final List<ConfigClass> allMappings;
final Map<Class<?>, ConfigClass> allMappingsByClass;
final Map<PropertyName, String> allMappingsNames;

final Set<String> unknownBuildProperties;
final Set<String> deprecatedRuntimeProperties;
Expand All @@ -1273,7 +1295,9 @@ public ReadResult(final Builder builder) {
this.buildTimeMappings = builder.getBuildTimeMappings();
this.buildTimeRunTimeMappings = builder.getBuildTimeRunTimeMappings();
this.runTimeMappings = builder.getRunTimeMappings();
this.allMappings = mappingsToMap(builder);
this.allMappings = new ArrayList<>(mappingsToMap(builder).values());
this.allMappingsByClass = mappingsToMap(builder);
this.allMappingsNames = ReadOperation.mappingsToNames(allMappings);

this.unknownBuildProperties = builder.getUnknownBuildProperties();
this.deprecatedRuntimeProperties = builder.deprecatedRuntimeProperties;
Expand Down Expand Up @@ -1355,10 +1379,18 @@ public List<ConfigClass> getRunTimeMappings() {
return runTimeMappings;
}

public Map<Class<?>, ConfigClass> getAllMappings() {
public List<ConfigClass> getAllMappings() {
return allMappings;
}

public Map<Class<?>, ConfigClass> getAllMappingsByClass() {
return allMappingsByClass;
}

public Map<PropertyName, String> getAllMappingsNames() {
return allMappingsNames;
}

public Set<String> getUnknownBuildProperties() {
return unknownBuildProperties;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
Expand Down Expand Up @@ -63,6 +64,7 @@
import io.quarkus.runtime.configuration.NameIterator;
import io.quarkus.runtime.configuration.PropertiesUtil;
import io.quarkus.runtime.configuration.QuarkusConfigFactory;
import io.smallrye.config.ConfigMappingInterface;
import io.smallrye.config.ConfigMappings;
import io.smallrye.config.ConfigMappings.ConfigClass;
import io.smallrye.config.Converters;
Expand All @@ -88,9 +90,6 @@ public final class RunTimeConfigurationGenerator {
public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class);

static final FieldDescriptor C_MAPPED_PROPERTIES = FieldDescriptor.of(CONFIG_CLASS_NAME, "mappedProperties", Set.class);
static final MethodDescriptor C_GENERATE_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
"generateMappedProperties", Set.class);
static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class);
static final FieldDescriptor C_UNKNOWN = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknown", Set.class);
static final FieldDescriptor C_UNKNOWN_RUNTIME = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknownRuntime", Set.class);

Expand Down Expand Up @@ -192,9 +191,13 @@ public final class RunTimeConfigurationGenerator {
static final MethodDescriptor PU_IS_PROPERTY_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "isPropertyInRoots",
boolean.class, String.class, Set.class);
static final MethodDescriptor HS_NEW = MethodDescriptor.ofConstructor(HashSet.class);
static final MethodDescriptor HS_NEW_SIZED = MethodDescriptor.ofConstructor(HashSet.class, int.class);
static final MethodDescriptor HS_ADD = MethodDescriptor.ofMethod(HashSet.class, "add", boolean.class, Object.class);
static final MethodDescriptor HS_ADD_ALL = MethodDescriptor.ofMethod(HashSet.class, "addAll", boolean.class,
Collection.class);
static final MethodDescriptor HS_CONTAINS = MethodDescriptor.ofMethod(HashSet.class, "contains", boolean.class,
Object.class);
static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class);

// todo: more space-efficient sorted map impl
static final MethodDescriptor TM_NEW = MethodDescriptor.ofConstructor(TreeMap.class);
Expand Down Expand Up @@ -262,7 +265,6 @@ public static final class GenerateOperation implements AutoCloseable {
roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots());
additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes());
cc = ClassCreator.builder().classOutput(classOutput).className(CONFIG_CLASS_NAME).setFinal(true).build();
generateMappedProperties();
generateEmptyParsers();
// not instantiable
try (MethodCreator mc = cc.getMethodCreator(MethodDescriptor.ofConstructor(CONFIG_CLASS_NAME))) {
Expand All @@ -282,14 +284,17 @@ public static final class GenerateOperation implements AutoCloseable {
clinit.setModifiers(Opcodes.ACC_STATIC);

cc.getFieldCreator(C_MAPPED_PROPERTIES).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.invokeStaticMethod(C_GENERATE_MAPPED_PROPERTIES));
clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.newInstance(HS_NEW_SIZED,
clinit.load((int) ((float) buildTimeConfigResult.getAllMappingsNames().size() / 0.75f + 1.0f))));

cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN, clinit.newInstance(HS_NEW));

cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN_RUNTIME, clinit.newInstance(HS_NEW));

generateMappedProperties();

clinitNameBuilder = clinit.newInstance(SB_NEW);

// the build time config, which is for user use only (not used by us other than for loading converters)
Expand Down Expand Up @@ -1191,26 +1196,32 @@ private FieldDescriptor getOrCreateConverterInstance(Field field, ConverterType
}

private void generateMappedProperties() {
Set<String> names = new HashSet<>();
for (ConfigClass buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) {
names.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet());
}
for (ConfigClass staticConfigMapping : buildTimeConfigResult.getBuildTimeRunTimeMappings()) {
names.addAll(ConfigMappings.getProperties(staticConfigMapping).keySet());
}
for (ConfigClass runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) {
names.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet());
MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "addMappedProperties", void.class);
MethodCreator mc = cc.getMethodCreator(method);
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
for (ConfigClass mapping : buildTimeConfigResult.getAllMappings()) {
mc.invokeStaticMethod(generateMappedProperties(mapping, buildTimeConfigResult.getAllMappingsNames()));
}
Set<PropertyName> propertyNames = PropertiesUtil.toPropertyNames(names);
mc.returnVoid();
mc.close();
clinit.invokeStaticMethod(method);
}

MethodCreator mc = cc.getMethodCreator(C_GENERATE_MAPPED_PROPERTIES);
private MethodDescriptor generateMappedProperties(final ConfigClass mapping,
final Map<PropertyName, String> propertyNames) {
MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
"addMappedProperties$" + mapping.getKlass().getName().replace('.', '$'), void.class);
MethodCreator mc = cc.getMethodCreator(method);
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
ResultHandle set = mc.newInstance(HS_NEW);
for (PropertyName propertyName : propertyNames) {
mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(propertyName.getName())));
Map<String, ConfigMappingInterface.Property> properties = ConfigMappings.getProperties(mapping);
ResultHandle set = mc.readStaticField(C_MAPPED_PROPERTIES);
for (String propertyName : properties.keySet()) {
String name = propertyNames.get(new PropertyName(propertyName));
mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(name)));
}
mc.returnValue(set);
mc.returnVoid();
mc.close();
return method;
}

private void reportUnknown(BytecodeCreator bc, ResultHandle unknownProperty) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package io.quarkus.runtime.configuration;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import io.smallrye.config.PropertyName;

public class PropertiesUtil {
private PropertiesUtil() {
throw new IllegalStateException("Utility class");
Expand Down Expand Up @@ -48,28 +44,4 @@ public static boolean isPropertyInRoot(final String property, final String root)
public static boolean isPropertyQuarkusCompoundName(NameIterator propertyName) {
return propertyName.getName().startsWith("\"quarkus.");
}

public static Set<PropertyName> toPropertyNames(final Set<String> names) {
Map<PropertyName, String> propertyNames = new HashMap<>();
for (String name : names) {
PropertyName propertyName = new PropertyName(name);
if (propertyNames.containsKey(propertyName)) {
String existing = propertyNames.remove(propertyName);
if (existing.length() < name.length()) {
propertyNames.put(new PropertyName(existing), existing);
} else if (existing.length() > name.length()) {
propertyNames.put(propertyName, name);
} else {
if (existing.indexOf('*') <= name.indexOf('*')) {
propertyNames.put(new PropertyName(existing), existing);
} else {
propertyNames.put(propertyName, name);
}
}
} else {
propertyNames.put(propertyName, name);
}
}
return propertyNames.keySet();
}
}

0 comments on commit 1db73a7

Please sign in to comment.