diff --git a/pom.xml b/pom.xml index 4cba67f117..c6a2c45085 100644 --- a/pom.xml +++ b/pom.xml @@ -107,11 +107,11 @@ 3.0.0 4.0.0 1.0.0 - 4.0.5 + 4.0.6 3.0.0 1.0.0 4.0.0 - 3.0.1 + 3.0.2 1.2 2.23.0 8.0.28 diff --git a/warehouse/query-core/src/main/java/datawave/query/function/LimitFields.java b/warehouse/query-core/src/main/java/datawave/query/function/LimitFields.java index c02016fae5..d305150675 100644 --- a/warehouse/query-core/src/main/java/datawave/query/function/LimitFields.java +++ b/warehouse/query-core/src/main/java/datawave/query/function/LimitFields.java @@ -13,6 +13,7 @@ import com.google.common.collect.Multimap; import datawave.data.type.Type; +import datawave.data.type.TypeFactory; import datawave.query.attributes.Attribute; import datawave.query.attributes.Attributes; import datawave.query.attributes.Content; @@ -64,6 +65,10 @@ public class LimitFields implements Function,Entry> matchingFieldSets; + private int typeCacheSize = -1; + private int typeCacheTimeoutMinutes = -1; + private TypeFactory typeFactory; + public LimitFields(Map limitFieldsMap, Set> matchingFieldSets) { this.limitFieldsMap = limitFieldsMap; this.matchingFieldSets = matchingFieldSets; @@ -295,7 +300,7 @@ private boolean isHit(String keyWithGrouping, Attribute attr, Multimap thing = (Type) clazz.newInstance(); + Type thing = getTypeFactory().createType(clazz.getName()); thing.setDelegateFromString(String.valueOf(hitValue)); hitValue = thing; } else { // otherwise, s is not a Type, just compare as string values @@ -396,4 +401,39 @@ public Integer put(String key, Integer value) { } } + /** + * Get the TypeFactory. If no TypeFactory exists one will be created. Configs for cache size and timeout may be configured. + * + * @return the TypeFactory + */ + private TypeFactory getTypeFactory() { + if (typeFactory == null) { + if (typeCacheSize != -1 && typeCacheTimeoutMinutes != -1) { + typeFactory = new TypeFactory(typeCacheSize, typeCacheTimeoutMinutes); + } else { + typeFactory = new TypeFactory(); + } + } + return typeFactory; + } + + /** + * Set the cache size for the TypeFactory + * + * @param typeCacheSize + * the cache size + */ + public void setTypeCacheSize(int typeCacheSize) { + this.typeCacheSize = typeCacheSize; + } + + /** + * Set the timeout for the TypeFactory + * + * @param typeCacheTimeoutMinutes + * the timeout + */ + public void setTypeCacheTimeoutMinutes(int typeCacheTimeoutMinutes) { + this.typeCacheTimeoutMinutes = typeCacheTimeoutMinutes; + } } diff --git a/warehouse/query-core/src/main/java/datawave/query/jexl/functions/EventFieldAggregator.java b/warehouse/query-core/src/main/java/datawave/query/jexl/functions/EventFieldAggregator.java index 81264fb192..34695b62f1 100644 --- a/warehouse/query-core/src/main/java/datawave/query/jexl/functions/EventFieldAggregator.java +++ b/warehouse/query-core/src/main/java/datawave/query/jexl/functions/EventFieldAggregator.java @@ -7,19 +7,14 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import org.apache.accumulo.core.data.ByteSequence; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.iterators.SortedKeyValueIterator; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - import datawave.data.type.Type; +import datawave.data.type.TypeFactory; import datawave.query.attributes.Attribute; import datawave.query.attributes.AttributeFactory; import datawave.query.attributes.Document; @@ -28,18 +23,13 @@ import datawave.query.util.TypeMetadata; public class EventFieldAggregator extends IdentityAggregator { - // speedy cache loading for types, duplicated from AttributeFactory with caching of types rather than classes - protected static final LoadingCache> typeCache = CacheBuilder.newBuilder().maximumSize(128).expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader>() { - @Override - public Type load(String clazz) throws Exception { - Class c = Class.forName(clazz); - return (Type) c.newInstance(); - } - }); - - private TypeMetadata typeMetadata; - private String defaultTypeClass; + + private final TypeMetadata typeMetadata; + private final String defaultTypeClass; + + private int typeCacheSize = -1; + private int typeCacheTimeoutMinutes = -1; + private TypeFactory typeFactory; public EventFieldAggregator(String field, EventDataQueryFilter filter, int maxNextCount, TypeMetadata typeMetadata, String defaultTypeClass) { super(Collections.singleton(field), filter, maxNextCount); @@ -122,16 +112,48 @@ private Set getNormalizedValues(String dataType, String fieldName, Strin // transform the key for each type and add it to the normalized set for (String typeClass : typeClasses) { - try { - Type type = typeCache.get(typeClass); - String normalizedValue = type.normalize(fieldValue); + Type type = getTypeFactory().createType(typeClass); + String normalizedValue = type.normalize(fieldValue); - normalizedValues.add(normalizedValue); - } catch (ExecutionException e) { - throw new RuntimeException("cannot instantiate class '" + typeClass + "'", e); - } + normalizedValues.add(normalizedValue); } return normalizedValues; } + + /** + * Get the TypeFactory. If no TypeFactory exists one will be created. Configs for cache size and timeout may be configured. + * + * @return the TypeFactory + */ + private TypeFactory getTypeFactory() { + if (typeFactory == null) { + if (typeCacheSize != -1 && typeCacheTimeoutMinutes != -1) { + typeFactory = new TypeFactory(typeCacheSize, typeCacheTimeoutMinutes); + } else { + typeFactory = new TypeFactory(); + } + } + return typeFactory; + } + + /** + * Set the cache size for the TypeFactory + * + * @param typeCacheSize + * the cache size + */ + public void setTypeCacheSize(int typeCacheSize) { + this.typeCacheSize = typeCacheSize; + } + + /** + * Set the timeout for the TypeFactory + * + * @param typeCacheTimeoutMinutes + * the timeout + */ + public void setTypeCacheTimeoutMinutes(int typeCacheTimeoutMinutes) { + this.typeCacheTimeoutMinutes = typeCacheTimeoutMinutes; + } } diff --git a/warehouse/query-core/src/test/java/datawave/query/attributes/AttributeFactoryTest.java b/warehouse/query-core/src/test/java/datawave/query/attributes/AttributeFactoryTest.java index c4d9861361..2ce279aaf2 100644 --- a/warehouse/query-core/src/test/java/datawave/query/attributes/AttributeFactoryTest.java +++ b/warehouse/query-core/src/test/java/datawave/query/attributes/AttributeFactoryTest.java @@ -2,6 +2,7 @@ import java.util.Collection; +import org.apache.accumulo.core.data.Key; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Test; @@ -11,6 +12,7 @@ import datawave.data.type.LcNoDiacriticsType; import datawave.data.type.NoOpType; import datawave.data.type.NumberType; +import datawave.query.util.TypeMetadata; /** * @@ -44,7 +46,24 @@ public void testFindersKeepers() { Assert.assertEquals(AttributeFactory.getKeepers(three), expectedThree); Assert.assertEquals(AttributeFactory.getKeepers(four), expectedFour); Assert.assertEquals(AttributeFactory.getKeepers(five), expectedFive); + } + + @Test + public void testTypeFactoryCache() { + TypeMetadata metadata = new TypeMetadata(); + metadata.put("FIELD", "ingest-type", LcNoDiacriticsType.class.getTypeName()); + + AttributeFactory factory = new AttributeFactory(metadata); + + Key key = new Key("row", "ingest-type\0uid"); + Attribute red = factory.create("FIELD", "red", key, true); + Attribute blue = factory.create("FIELD", "blue", key, true); + + TypeAttribute redType = (TypeAttribute) red; + TypeAttribute blueType = (TypeAttribute) blue; + Assert.assertEquals("red", redType.getType().getNormalizedValue()); + Assert.assertEquals("blue", blueType.getType().getNormalizedValue()); } }