diff options
171 files changed, 1037 insertions, 1093 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java index e3446002888..91514b89b3e 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java @@ -24,6 +24,8 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; +import static com.yahoo.config.provision.NodeResources.Architecture; + /** * Model context containing state provided to model factories. * @@ -118,7 +120,8 @@ public interface ModelContext { @ModelFeatureFlag(owners = {"arnej"}) default boolean avoidRenamingSummaryFeatures() { return false; } @ModelFeatureFlag(owners = {"bjorncs", "baldersheim"}) default boolean mergeGroupingResultInSearchInvoker() { return false; } @ModelFeatureFlag(owners = {"arnej"}) default boolean experimentalSdParsing() { return false; } - @ModelFeatureFlag(owners = {"hmusum"}) default String adminClusterNodeArchitecture() { return "x86_64"; } // TODO: Cluster controllers only for now + @ModelFeatureFlag(owners = {"hmusum"}) default String adminClusterNodeArchitecture() { return adminClusterArchitecture().name(); } // TODO: Remove when 7.564 is oldest version in use + @ModelFeatureFlag(owners = {"hmusum"}) default Architecture adminClusterArchitecture() { return Architecture.getDefault(); } } /** Warning: As elsewhere in this package, do not make backwards incompatible changes that will break old config models! */ diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 575080d3025..3e251a621ab 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import static com.yahoo.config.provision.NodeResources.Architecture; + /** * A test-only Properties class * @@ -81,7 +83,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea private List<String> environmentVariables = List.of(); private boolean avoidRenamingSummaryFeatures = false; private boolean experimentalSdParsing = false; - private String adminClusterNodeResourcesArchitecture = "x86_64"; + private Architecture adminClusterNodeResourcesArchitecture = Architecture.getDefault(); @Override public ModelContext.FeatureFlags featureFlags() { return this; } @Override public boolean multitenant() { return multitenant; } @@ -143,7 +145,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea @Override public List<String> environmentVariables() { return environmentVariables; } @Override public boolean avoidRenamingSummaryFeatures() { return this.avoidRenamingSummaryFeatures; } @Override public boolean experimentalSdParsing() { return this.experimentalSdParsing; } - @Override public String adminClusterNodeArchitecture() { return adminClusterNodeResourcesArchitecture; } + @Override public Architecture adminClusterArchitecture() { return adminClusterNodeResourcesArchitecture; } public TestProperties maxUnCommittedMemory(int maxUnCommittedMemory) { this.maxUnCommittedMemory = maxUnCommittedMemory; @@ -391,8 +393,8 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea return this; } - public TestProperties setAdminClusterNodeResourcesArchitecture(String architectureFunction) { - this.adminClusterNodeResourcesArchitecture = architectureFunction; + public TestProperties setAdminClusterNodeResourcesArchitecture(Architecture architecture) { + this.adminClusterNodeResourcesArchitecture = architecture; return this; } diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java index 8bf6dc7f1d9..a6bcf6b0fd2 100644 --- a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java +++ b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java @@ -36,7 +36,7 @@ import java.util.stream.IntStream; */ public class InMemoryProvisioner implements HostProvisioner { - public static final NodeResources defaultResources = new NodeResources(1, 3, 10, 1); + public static final NodeResources defaultResources = new NodeResources(1, 3, 50, 1); /** * If this is true an exception is thrown when all nodes are used. @@ -153,7 +153,7 @@ public class InMemoryProvisioner implements HostProvisioner { if (alwaysReturnOneNode) nodes = 1; - int groups = requested.groups() > nodes ? nodes : requested.groups(); + int groups = Math.min(requested.groups(), nodes); List<HostSpec> allocation = new ArrayList<>(); if (groups == 1) { diff --git a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java index 65c282e01e2..702ab835dd4 100644 --- a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java +++ b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java @@ -5,7 +5,6 @@ import com.yahoo.document.DataType; import com.yahoo.document.DocumentType; import com.yahoo.document.ReferenceDataType; import com.yahoo.document.StructuredDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.document.datatypes.FieldValue; import com.yahoo.document.datatypes.ReferenceFieldValue; diff --git a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java index dd8edbdde6c..ff5930f8f6a 100644 --- a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java +++ b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java @@ -7,7 +7,6 @@ import com.yahoo.document.Field; import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.document.StructDataType; import com.yahoo.document.StructuredDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.document.annotation.AnnotationType; import com.yahoo.document.annotation.AnnotationTypeRegistry; import com.yahoo.document.datatypes.FieldValue; diff --git a/config-model/src/main/java/com/yahoo/documentmodel/OwnedStructDataType.java b/config-model/src/main/java/com/yahoo/documentmodel/OwnedStructDataType.java new file mode 100644 index 00000000000..761a1f0963c --- /dev/null +++ b/config-model/src/main/java/com/yahoo/documentmodel/OwnedStructDataType.java @@ -0,0 +1,56 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.documentmodel; + +import com.yahoo.document.DocumentType; +import com.yahoo.document.StructDataType; + +/** + * Model for StructDataType declared in a specific document + * + * @author arnej + **/ +public final class OwnedStructDataType extends StructDataType implements OwnedType { + + private final String ownerName; + private final String uniqueName; + private boolean overrideId = false; + + public OwnedStructDataType(String name, DocumentType document) { + this(name, document.getName()); + } + + public OwnedStructDataType(String name, String owner) { + super(name); + this.ownerName = owner; + this.uniqueName = name + "@" + owner; + } + + public void enableOverride() { + this.overrideId = true; + } + + @Override + public String getOwnerName() { + return ownerName; + } + + @Override + public String getUniqueName() { + return uniqueName; + } + + @Override + public String getName() { + return overrideId ? uniqueName : super.getName(); + } + + @Override + public int getId() { + return overrideId ? getUniqueId() : super.getId(); + } + + @Override + public String toString() { + return "{OwnedStructDataType "+uniqueName+" id="+getId()+" uid="+getUniqueId()+" enable override="+overrideId+"}"; + } +} diff --git a/config-model/src/main/java/com/yahoo/documentmodel/OwnedTemporaryType.java b/config-model/src/main/java/com/yahoo/documentmodel/OwnedTemporaryType.java new file mode 100644 index 00000000000..536c10ee242 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/documentmodel/OwnedTemporaryType.java @@ -0,0 +1,41 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.documentmodel; + +import com.yahoo.document.DocumentType; +import com.yahoo.document.StructDataType; + +/** + * Proxy for a struct type declared in a specific document + * + * @author arnej + **/ +public final class OwnedTemporaryType extends StructDataType implements OwnedType { + + private final String ownerName; + private final String uniqueName; + + public OwnedTemporaryType(String name, DocumentType document) { + this(name, document.getName()); + } + + public OwnedTemporaryType(String name, String owner) { + super(name); + this.ownerName = owner; + this.uniqueName = name + "@" + owner; + } + + @Override + public String getOwnerName() { + return ownerName; + } + + @Override + public String getUniqueName() { + return uniqueName; + } + + @Override + public String toString() { + return "{OwnedTemporaryType "+uniqueName+" id="+getId()+" uid="+getUniqueId()+"}"; + } +} diff --git a/config-model/src/main/java/com/yahoo/documentmodel/OwnedType.java b/config-model/src/main/java/com/yahoo/documentmodel/OwnedType.java new file mode 100644 index 00000000000..e3a91692ca8 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/documentmodel/OwnedType.java @@ -0,0 +1,15 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.documentmodel; + +/** + * API for a type declared in a specific document + * + * @author arnej + **/ +public interface OwnedType { + String getOwnerName(); + String getUniqueName(); + default int getUniqueId() { + return getUniqueName().hashCode(); + } +} diff --git a/config-model/src/main/java/com/yahoo/documentmodel/TemporaryUnknownType.java b/config-model/src/main/java/com/yahoo/documentmodel/TemporaryUnknownType.java new file mode 100644 index 00000000000..66f6354b3f5 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/documentmodel/TemporaryUnknownType.java @@ -0,0 +1,21 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.documentmodel; + +import com.yahoo.document.StructDataType; + +/** + * Proxy for an unknown type (must resolve to struct or document) + * + * @author arnej + **/ +public final class TemporaryUnknownType extends StructDataType { + + public TemporaryUnknownType(String name) { + super(name); + } + + @Override + public String toString() { + return "{TemporaryUnknownType "+getName()+" id="+getId()+"}"; + } +} diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java index 4660b81ff72..5b7b23d69d4 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java @@ -7,7 +7,6 @@ import com.yahoo.document.DataType; import com.yahoo.document.DocumentType; import com.yahoo.document.Field; import com.yahoo.document.MapDataType; -import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.document.StructDataType; import com.yahoo.document.StructuredDataType; import com.yahoo.document.TemporaryStructuredDataType; @@ -15,7 +14,11 @@ import com.yahoo.document.WeightedSetDataType; import com.yahoo.document.annotation.AnnotationReferenceDataType; import com.yahoo.document.annotation.AnnotationType; import com.yahoo.documentmodel.DataTypeCollection; +import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.documentmodel.NewDocumentType; +import com.yahoo.documentmodel.OwnedStructDataType; +import com.yahoo.documentmodel.OwnedTemporaryType; +import com.yahoo.documentmodel.TemporaryUnknownType; import com.yahoo.documentmodel.VespaDocumentType; import com.yahoo.searchdefinition.document.Attribute; import com.yahoo.searchdefinition.document.SDDocumentType; @@ -232,13 +235,37 @@ public class DocumentModelBuilder { } DataType original = type; if (type instanceof TemporaryStructuredDataType) { + throw new IllegalArgumentException("Cannot handle temporary: " + type); + } + if (type instanceof TemporaryUnknownType) { + // must be a known struct or document type DataType other = repo.getDataType(type.getId()); if (other == null || other == type) { + // maybe it is the name of a document type: other = getDocumentType(docs, type.getName()); } - if (other != null) { - type = other; + if (other == null) { + throw new IllegalArgumentException("No replacement found for temporary type: " + type); + } + type = other; + } else if (type instanceof OwnedTemporaryType) { + // must be replaced with the real struct type + DataType other = repo.getDataType(type.getId()); + if (other == null || other == type) { + throw new IllegalArgumentException("No replacement found for temporary type: " + type); + } + if (other instanceof OwnedStructDataType) { + var owned = (OwnedTemporaryType) type; + String ownedBy = owned.getOwnerName(); + var otherOwned = (OwnedStructDataType) other; + String otherOwnedBy = otherOwned.getOwnerName(); + if (! ownedBy.equals(otherOwnedBy)) { + throw new IllegalArgumentException("Wrong document for type: " + otherOwnedBy + " but expected " + ownedBy); + } + } else { + throw new IllegalArgumentException("Found wrong sort of type: " + other + " [" + other.getClass() + "]"); } + type = other; } else if (type instanceof DocumentType) { DataType other = getDocumentType(docs, type.getName()); if (other != null) { @@ -364,6 +391,8 @@ public class DocumentModelBuilder { for (SDDocumentType proxy : type.getInheritedTypes()) { var inherited = (StructDataType) targetDt.getDataTypeRecursive(proxy.getName()); var converted = (StructDataType) targetDt.getDataType(type.getName()); + assert(converted instanceof OwnedStructDataType); + assert(inherited instanceof OwnedStructDataType); if (! converted.inherits(inherited)) { converted.inherit(inherited); } @@ -382,15 +411,15 @@ public class DocumentModelBuilder { StructDataType s = handleStruct(sa.getSdDocType()); annotation.setDataType(s); if ((sa.getInherits() != null)) { - structInheritance.put(s, "annotation."+sa.getInherits()); + structInheritance.put(s, "annotation." + sa.getInherits()); } } else if (sa.getInherits() != null) { - StructDataType s = new StructDataType("annotation."+annotation.getName()); + StructDataType s = new OwnedStructDataType("annotation." + annotation.getName(), sdoc.getName()); if (anyParentsHavePayLoad(sa, sdoc)) { annotation.setDataType(s); addType(s); } - structInheritance.put(s, "annotation."+sa.getInherits()); + structInheritance.put(s, "annotation." + sa.getInherits()); } } else { var dt = annotation.getDataType(); @@ -532,16 +561,18 @@ public class DocumentModelBuilder { @SuppressWarnings("deprecation") private StructDataType handleStruct(SDDocumentType type) { + // System.err.println("handle struct " + type + " for doc " + targetDt.getName()); if (type.isStruct()) { var st = type.getStruct(); if (st.getName().equals(type.getName()) && (st instanceof StructDataType) && - ! (st instanceof TemporaryStructuredDataType)) + (! (st instanceof TemporaryUnknownType)) && + (! (st instanceof OwnedTemporaryType))) { return handleStruct((StructDataType) st); } } - StructDataType s = new StructDataType(type.getName()); + StructDataType s = new OwnedStructDataType(type.getName(), targetDt.getName()); for (Field f : type.getDocumentType().contentStruct().getFieldsThisTypeOnly()) { specialHandleAnnotationReference(f); s.addField(f); diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java index c592e4842a9..b466a78c69b 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java @@ -8,7 +8,6 @@ import com.yahoo.document.DocumentType; import com.yahoo.document.PrimitiveDataType; import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.document.StructuredDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.document.TensorDataType; import com.yahoo.document.WeightedSetDataType; import com.yahoo.document.datatypes.BoolFieldValue; diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java index 621e7ce8571..49ae00d0663 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java @@ -7,9 +7,10 @@ import com.yahoo.document.DocumentType; import com.yahoo.document.Field; import com.yahoo.document.MapDataType; import com.yahoo.document.StructDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.document.TensorDataType; import com.yahoo.document.WeightedSetDataType; +import com.yahoo.documentmodel.OwnedTemporaryType; +import com.yahoo.documentmodel.TemporaryUnknownType; import com.yahoo.language.Linguistics; import com.yahoo.language.process.Embedder; import com.yahoo.language.simple.SimpleLinguistics; @@ -307,7 +308,11 @@ public class SDField extends Field implements TypedKey, FieldOperationContainer, return; } SDDocumentType subType = sdoc != null ? sdoc.getType(dataType.getName()) : null; - if (dataType instanceof TemporaryStructuredDataType && subType != null) { + if (dataType instanceof TemporaryUnknownType && subType != null) { + for (Field field : subType.fieldSet()) { + supplyStructField.accept(field.getName(), field.getDataType()); + } + } else if (dataType instanceof OwnedTemporaryType && subType != null) { for (Field field : subType.fieldSet()) { supplyStructField.accept(field.getName(), field.getDataType()); } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedTypes.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedTypes.java index f628db85429..8e27b581769 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedTypes.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedTypes.java @@ -4,11 +4,12 @@ package com.yahoo.searchdefinition.parser; import com.yahoo.document.DataType; import com.yahoo.document.DocumentType; import com.yahoo.document.DocumentTypeManager; -import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.StructDataType; import com.yahoo.document.PositionDataType; +import com.yahoo.document.StructDataType; import com.yahoo.document.WeightedSetDataType; import com.yahoo.document.annotation.AnnotationReferenceDataType; +import com.yahoo.documentmodel.NewDocumentReferenceDataType; +import com.yahoo.documentmodel.OwnedStructDataType; import com.yahoo.searchdefinition.document.annotation.SDAnnotationType; import java.util.ArrayList; @@ -58,7 +59,7 @@ public class ConvertParsedTypes { var doc = schema.getDocument(); for (var struct : doc.getStructs()) { String structId = doc.name() + "->" + struct.name(); - var dt = new StructDataType(struct.name()); + var dt = new OwnedStructDataType(struct.name(), doc.name()); structsFromSchemas.put(structId, dt); } for (var annotation : doc.getAnnotations()) { @@ -72,7 +73,7 @@ public class ConvertParsedTypes { if (withStruct.isPresent()) { ParsedStruct struct = withStruct.get(); String structId = doc.name() + "->" + struct.name(); - var old = structsFromSchemas.put(structId, new StructDataType(struct.name())); + var old = structsFromSchemas.put(structId, new OwnedStructDataType(struct.name(), doc.name())); assert(old == null); } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedBlock.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedBlock.java index 213733f7722..151da352f2f 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedBlock.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedBlock.java @@ -15,6 +15,7 @@ public class ParsedBlock { } public final String name() { return name; } + public final String blockType() { return blockType; } protected void verifyThat(boolean check, String msg, Object ... msgDetails) { if (check) return; @@ -28,5 +29,8 @@ public class ParsedBlock { throw new IllegalArgumentException(buf.toString()); } + public String toString() { + return blockType + " '" + name + "'"; + } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java index ca128a93590..ea138808289 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java @@ -62,8 +62,9 @@ public class ParsedDocument extends ParsedBlock { void inherit(String other) { inherited.add(other); } void addField(ParsedField field) { - String fieldName = field.name(); - verifyThat(! docFields.containsKey(fieldName), "already has field", fieldName); + String fieldName = field.name().toLowerCase(); + verifyThat(! docFields.containsKey(fieldName), + "Duplicate (case insensitively) " + field + " in document type '" + this.name() + "'"); docFields.put(fieldName, field); } @@ -81,8 +82,6 @@ public class ParsedDocument extends ParsedBlock { annotation.tagOwner(this); } - public String toString() { return "document " + name(); } - void resolveInherit(String name, ParsedDocument parsed) { verifyThat(inherited.contains(name), "resolveInherit for non-inherited name", name); verifyThat(name.equals(parsed.name()), "resolveInherit name mismatch for", name); diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedType.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedType.java index d04277706a1..a5f00b1ce45 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedType.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedType.java @@ -32,6 +32,61 @@ class ParsedType { private boolean createIfNonExistent = false; private boolean removeIfZero = false; + public String toString() { + var buf = new StringBuilder(); + buf.append("[type ").append(variant).append("] {"); + switch (variant) { + case NONE: + break; + case BUILTIN: + buf.append(name); + break; + case POSITION: + buf.append(name); + break; + case TENSOR: + buf.append(tensorType.toString()); + break; + case ARRAY: buf + .append(" array<") + .append(valType.toString()) + .append("> "); + break; + case WSET: buf + .append(" weightedset<") + .append(valType.toString()) + .append(">"); + if (createIfNonExistent) buf.append(",createIfNonExistent"); + if (removeIfZero) buf.append(",removeIfZero"); + buf.append(" "); + break; + case MAP: buf + .append(" map<") + .append(keyType.toString()) + .append(",") + .append(valType.toString()) + .append("> "); + break; + case DOC_REFERENCE: buf + .append(" reference<") + .append(valType.toString()) + .append("> "); + break; + case ANN_REFERENCE: buf + .append(" ") + .append(toString()) + .append(" "); + break; + case STRUCT: + case DOCUMENT: + case UNKNOWN: + buf.append(" ").append(name).append(" "); + break; + } + buf.append("}"); + return buf.toString(); + } + private static Variant guessVariant(String name) { switch (name) { case "bool": return Variant.BUILTIN; diff --git a/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentManager.java b/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentManager.java index ff311795089..8867ab63e2b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentManager.java +++ b/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentManager.java @@ -9,6 +9,8 @@ import com.yahoo.document.annotation.AnnotationType; import com.yahoo.documentmodel.DataTypeCollection; import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.documentmodel.NewDocumentType; +import com.yahoo.documentmodel.OwnedTemporaryType; +import com.yahoo.documentmodel.TemporaryUnknownType; import com.yahoo.documentmodel.VespaDocumentType; import com.yahoo.searchdefinition.document.FieldSet; import com.yahoo.vespa.documentmodel.DocumentModel; @@ -83,6 +85,12 @@ public class DocumentManager { if (dataType instanceof TemporaryStructuredDataType) { throw new IllegalArgumentException("Can not create config for temporary data type: " + dataType.getName()); } + if (dataType instanceof TemporaryUnknownType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + dataType.getName()); + } + if (dataType instanceof OwnedTemporaryType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + dataType.getName()); + } if ((dataType.getId() < 0) || (dataType.getId()> DataType.lastPredefinedDataTypeId())) { Datatype.Builder dataTypeBuilder = new Datatype.Builder(); documentConfigBuilder.datatype(dataTypeBuilder); @@ -144,8 +152,6 @@ public class DocumentManager { } buildConfig(dt.getFieldSets(), doc); buildImportedFieldsConfig(dt.getImportedFieldNames(), doc); - } else if (type instanceof TemporaryStructuredDataType) { - throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); } else if (type instanceof StructDataType) { StructDataType structType = (StructDataType) type; Datatype.Structtype.Builder structBuilder = new Datatype.Structtype.Builder(); @@ -348,7 +354,11 @@ public class DocumentManager { indexMap.setDone(type); if (type instanceof TemporaryStructuredDataType) { throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); - } if (type instanceof StructDataType) { + } else if (type instanceof TemporaryUnknownType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); + } else if (type instanceof OwnedTemporaryType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); + } else if (type instanceof StructDataType) { docTypeBuildOneType((StructDataType) type, documentBuilder, indexMap); } else if (type instanceof ArrayDataType) { docTypeBuildOneType((ArrayDataType) type, documentBuilder, indexMap); diff --git a/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentTypes.java b/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentTypes.java index 1240dac8bf1..e1a28c8114f 100644 --- a/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentTypes.java +++ b/config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentTypes.java @@ -8,6 +8,8 @@ import com.yahoo.document.annotation.AnnotationType; import com.yahoo.documentmodel.DataTypeCollection; import com.yahoo.documentmodel.NewDocumentReferenceDataType; import com.yahoo.documentmodel.NewDocumentType; +import com.yahoo.documentmodel.OwnedTemporaryType; +import com.yahoo.documentmodel.TemporaryUnknownType; import com.yahoo.documentmodel.VespaDocumentType; import com.yahoo.searchdefinition.document.FieldSet; import com.yahoo.vespa.documentmodel.DocumentModel; @@ -111,6 +113,12 @@ public class DocumentTypes { built.add(type.getId()); DocumenttypesConfig.Documenttype.Datatype.Builder dataTypeBuilder = new DocumenttypesConfig.Documenttype.Datatype.Builder(); dataTypeBuilder.id(type.getId()); + if (type instanceof TemporaryUnknownType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); + } + if (type instanceof OwnedTemporaryType) { + throw new IllegalArgumentException("Can not create config for temporary data type: " + type.getName()); + } if (type instanceof StructDataType) { buildConfig((StructDataType) type, dataTypeBuilder, documentBuilder, built); } else if (type instanceof ArrayDataType) { diff --git a/config-model/src/main/javacc/SDParser.jj b/config-model/src/main/javacc/SDParser.jj index 018531616fb..ab0cdefc355 100644 --- a/config-model/src/main/javacc/SDParser.jj +++ b/config-model/src/main/javacc/SDParser.jj @@ -826,9 +826,10 @@ SDDocumentType structDefinition(Schema schema, SDDocumentType repo) : // empty } SDDocumentType sdtype = repo.getOwnedType(struct.getDocumentName()); - DataType stype = sdtype != null - ? sdtype.getStruct() - : TemporaryStructuredDataType.create(struct.getName()); + if (sdtype != null) { + throw new ParseException("Struct '" + name + "' is already defined."); + } + DataType stype = new OwnedTemporaryType(name, repo.getName()); struct.setStruct(stype); return struct; } @@ -847,7 +848,6 @@ DataType dataType() : DataType arrayType = null; DataType wsetType = null; TensorType tensorType; - TemporaryStructuredDataType referenceType; String referencedDoc; } { @@ -863,9 +863,9 @@ DataType dataType() : DataType type = VespaDocumentType.INSTANCE.getDataType(typeName); if (type == null) { - // we are basically creating TemporaryStructDataType instances for ANYTHING here!! + // we are basically creating TemporaryUnknownType instances for ANYTHING here!! // we must do this and clean them up later. - type = TemporaryStructuredDataType.create(typeName); + type = new TemporaryUnknownType(typeName); } if (isArrayOldStyle) { diff --git a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java index 91aff3935ab..183ab56d45f 100644 --- a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java +++ b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java @@ -48,6 +48,9 @@ import java.util.function.Function; import java.util.stream.Collectors; import static com.yahoo.config.model.test.TestUtil.joinLines; +import static com.yahoo.config.provision.NodeResources.Architecture; +import static com.yahoo.config.provision.NodeResources.DiskSpeed; +import static com.yahoo.config.provision.NodeResources.StorageType; import static com.yahoo.vespa.defaults.Defaults.getDefaults; import static com.yahoo.vespa.model.search.NodeResourcesTuning.GB; import static com.yahoo.vespa.model.search.NodeResourcesTuning.reservedMemoryGb; @@ -550,7 +553,7 @@ public class ModelProvisioningTest { assertEquals(3, subGroups.get(0).getNodes().size()); assertEquals(0, subGroups.get(0).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/0", subGroups.get(0).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-57", subGroups.get(0).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-57", subGroups.get(0).getNodes().get(0).getHostName()); assertEquals(1, subGroups.get(0).getNodes().get(1).getDistributionKey()); assertEquals("bar/storage/1", subGroups.get(0).getNodes().get(1).getConfigId()); assertEquals(2, subGroups.get(0).getNodes().get(2).getDistributionKey()); @@ -559,13 +562,13 @@ public class ModelProvisioningTest { assertEquals(3, subGroups.get(1).getNodes().size()); assertEquals(3, subGroups.get(1).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/3", subGroups.get(1).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-54", subGroups.get(1).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-54", subGroups.get(1).getNodes().get(0).getHostName()); assertEquals(4, subGroups.get(1).getNodes().get(1).getDistributionKey()); assertEquals("bar/storage/4", subGroups.get(1).getNodes().get(1).getConfigId()); assertEquals(5, subGroups.get(1).getNodes().get(2).getDistributionKey()); assertEquals("bar/storage/5", subGroups.get(1).getNodes().get(2).getConfigId()); // ... - assertEquals("node-1-3-10-51", subGroups.get(2).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-51", subGroups.get(2).getNodes().get(0).getHostName()); // ... assertEquals("8", subGroups.get(8).getIndex()); assertEquals(3, subGroups.get(8).getNodes().size()); @@ -584,14 +587,14 @@ public class ModelProvisioningTest { assertEquals(1, subGroups.get(0).getNodes().size()); assertEquals(0, subGroups.get(0).getNodes().get(0).getDistributionKey()); assertEquals("baz/storage/0", subGroups.get(0).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-27", subGroups.get(0).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-27", subGroups.get(0).getNodes().get(0).getHostName()); assertEquals("1", subGroups.get(1).getIndex()); assertEquals(1, subGroups.get(1).getNodes().size()); assertEquals(1, subGroups.get(1).getNodes().get(0).getDistributionKey()); assertEquals("baz/storage/1", subGroups.get(1).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-26", subGroups.get(1).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-26", subGroups.get(1).getNodes().get(0).getHostName()); // ... - assertEquals("node-1-3-10-25", subGroups.get(2).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-25", subGroups.get(2).getNodes().get(0).getHostName()); // ... assertEquals("26", subGroups.get(26).getIndex()); assertEquals(1, subGroups.get(26).getNodes().size()); @@ -691,7 +694,7 @@ public class ModelProvisioningTest { assertEquals(3, subGroups.get(0).getNodes().size()); assertEquals(0, subGroups.get(0).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/0", subGroups.get(0).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-57", subGroups.get(0).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-57", subGroups.get(0).getNodes().get(0).getHostName()); assertEquals(1, subGroups.get(0).getNodes().get(1).getDistributionKey()); assertEquals("bar/storage/1", subGroups.get(0).getNodes().get(1).getConfigId()); assertEquals(2, subGroups.get(0).getNodes().get(2).getDistributionKey()); @@ -700,13 +703,13 @@ public class ModelProvisioningTest { assertEquals(3, subGroups.get(1).getNodes().size()); assertEquals(3, subGroups.get(1).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/3", subGroups.get(1).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-54", subGroups.get(1).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-54", subGroups.get(1).getNodes().get(0).getHostName()); assertEquals(4, subGroups.get(1).getNodes().get(1).getDistributionKey()); assertEquals("bar/storage/4", subGroups.get(1).getNodes().get(1).getConfigId()); assertEquals(5, subGroups.get(1).getNodes().get(2).getDistributionKey()); assertEquals("bar/storage/5", subGroups.get(1).getNodes().get(2).getConfigId()); // ... - assertEquals("node-1-3-10-51", subGroups.get(2).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-51", subGroups.get(2).getNodes().get(0).getHostName()); // ... assertEquals("8", subGroups.get(8).getIndex()); assertEquals(3, subGroups.get(8).getNodes().size()); @@ -725,14 +728,14 @@ public class ModelProvisioningTest { assertEquals(1, subGroups.get(0).getNodes().size()); assertEquals(0, subGroups.get(0).getNodes().get(0).getDistributionKey()); assertEquals("baz/storage/0", subGroups.get(0).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-27", subGroups.get(0).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-27", subGroups.get(0).getNodes().get(0).getHostName()); assertEquals("1", subGroups.get(1).getIndex()); assertEquals(1, subGroups.get(1).getNodes().size()); assertEquals(1, subGroups.get(1).getNodes().get(0).getDistributionKey()); assertEquals("baz/storage/1", subGroups.get(1).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-26", subGroups.get(1).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-26", subGroups.get(1).getNodes().get(0).getHostName()); // ... - assertEquals("node-1-3-10-25", subGroups.get(2).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-25", subGroups.get(2).getNodes().get(0).getHostName()); // ... assertEquals("26", subGroups.get(26).getIndex()); assertEquals(1, subGroups.get(26).getNodes().size()); @@ -767,9 +770,9 @@ public class ModelProvisioningTest { ClusterControllerContainerCluster clusterControllers = model.getAdmin().getClusterControllers(); assertEquals(3, clusterControllers.getContainers().size()); assertEquals("cluster-controllers", clusterControllers.getName()); - assertEquals("node-1-3-10-03", clusterControllers.getContainers().get(0).getHostName()); - assertEquals("node-1-3-10-02", clusterControllers.getContainers().get(1).getHostName()); - assertEquals("node-1-3-10-01", clusterControllers.getContainers().get(2).getHostName()); + assertEquals("node-1-3-50-03", clusterControllers.getContainers().get(0).getHostName()); + assertEquals("node-1-3-50-02", clusterControllers.getContainers().get(1).getHostName()); + assertEquals("node-1-3-50-01", clusterControllers.getContainers().get(2).getHostName()); // Check content cluster ContentCluster cluster = model.getContentClusters().get("bar"); @@ -782,19 +785,19 @@ public class ModelProvisioningTest { assertEquals(1, subGroups.get(0).getNodes().size()); assertEquals(0, subGroups.get(0).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/0", subGroups.get(0).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-11", subGroups.get(0).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-11", subGroups.get(0).getNodes().get(0).getHostName()); // second group assertEquals("1", subGroups.get(1).getIndex()); assertEquals(1, subGroups.get(1).getNodes().size()); assertEquals(1, subGroups.get(1).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/1", subGroups.get(1).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-10", subGroups.get(1).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-10", subGroups.get(1).getNodes().get(0).getHostName()); // ... last group assertEquals("7", subGroups.get(7).getIndex()); assertEquals(1, subGroups.get(7).getNodes().size()); assertEquals(7, subGroups.get(7).getNodes().get(0).getDistributionKey()); assertEquals("bar/storage/7", subGroups.get(7).getNodes().get(0).getConfigId()); - assertEquals("node-1-3-10-04", subGroups.get(7).getNodes().get(0).getHostName()); + assertEquals("node-1-3-50-04", subGroups.get(7).getNodes().get(0).getHostName()); } @Test @@ -811,15 +814,15 @@ public class ModelProvisioningTest { int numberOfHosts = 11; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, true, "node-1-3-10-09"); + VespaModel model = tester.createModel(services, true, "node-1-3-50-09"); assertEquals(numberOfHosts, model.getRoot().hostSystem().getHosts().size()); // Check slobroks clusters assertEquals("Includes retired node", 1+3, model.getAdmin().getSlobroks().size()); - assertEquals("node-1-3-10-11", model.getAdmin().getSlobroks().get(0).getHostName()); - assertEquals("node-1-3-10-10", model.getAdmin().getSlobroks().get(1).getHostName()); - assertEquals("node-1-3-10-08", model.getAdmin().getSlobroks().get(2).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-09", model.getAdmin().getSlobroks().get(3).getHostName()); + assertEquals("node-1-3-50-11", model.getAdmin().getSlobroks().get(0).getHostName()); + assertEquals("node-1-3-50-10", model.getAdmin().getSlobroks().get(1).getHostName()); + assertEquals("node-1-3-50-08", model.getAdmin().getSlobroks().get(2).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-09", model.getAdmin().getSlobroks().get(3).getHostName()); } @Test @@ -836,16 +839,16 @@ public class ModelProvisioningTest { int numberOfHosts = 12; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, true, "node-1-3-10-03", "node-1-3-10-04"); + VespaModel model = tester.createModel(services, true, "node-1-3-50-03", "node-1-3-50-04"); assertEquals(10+2, model.getRoot().hostSystem().getHosts().size()); // Check slobroks clusters assertEquals("Includes retired node", 3+2, model.getAdmin().getSlobroks().size()); - assertEquals("node-1-3-10-12", model.getAdmin().getSlobroks().get(0).getHostName()); - assertEquals("node-1-3-10-11", model.getAdmin().getSlobroks().get(1).getHostName()); - assertEquals("node-1-3-10-10", model.getAdmin().getSlobroks().get(2).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-04", model.getAdmin().getSlobroks().get(3).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-03", model.getAdmin().getSlobroks().get(4).getHostName()); + assertEquals("node-1-3-50-12", model.getAdmin().getSlobroks().get(0).getHostName()); + assertEquals("node-1-3-50-11", model.getAdmin().getSlobroks().get(1).getHostName()); + assertEquals("node-1-3-50-10", model.getAdmin().getSlobroks().get(2).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-04", model.getAdmin().getSlobroks().get(3).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-03", model.getAdmin().getSlobroks().get(4).getHostName()); } @Test @@ -865,19 +868,19 @@ public class ModelProvisioningTest { int numberOfHosts = 16; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, true, "node-1-3-10-15", "node-1-3-10-05", "node-1-3-10-04"); + VespaModel model = tester.createModel(services, true, "node-1-3-50-15", "node-1-3-50-05", "node-1-3-50-04"); assertEquals(numberOfHosts, model.getRoot().hostSystem().getHosts().size()); // Check slobroks clusters // ... from cluster default assertEquals("Includes retired node", 7, model.getAdmin().getSlobroks().size()); - assertEquals("node-1-3-10-16", model.getAdmin().getSlobroks().get(0).getHostName()); - assertEquals("node-1-3-10-14", model.getAdmin().getSlobroks().get(1).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-15", model.getAdmin().getSlobroks().get(2).getHostName()); + assertEquals("node-1-3-50-16", model.getAdmin().getSlobroks().get(0).getHostName()); + assertEquals("node-1-3-50-14", model.getAdmin().getSlobroks().get(1).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-15", model.getAdmin().getSlobroks().get(2).getHostName()); // ... from cluster bar - assertEquals("node-1-3-10-03", model.getAdmin().getSlobroks().get(3).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-05", model.getAdmin().getSlobroks().get(5).getHostName()); - assertEquals("Included in addition because it is retired", "node-1-3-10-04", model.getAdmin().getSlobroks().get(6).getHostName()); + assertEquals("node-1-3-50-03", model.getAdmin().getSlobroks().get(3).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-05", model.getAdmin().getSlobroks().get(5).getHostName()); + assertEquals("Included in addition because it is retired", "node-1-3-50-04", model.getAdmin().getSlobroks().get(6).getHostName()); } @Test @@ -1104,7 +1107,7 @@ public class ModelProvisioningTest { int numberOfHosts = 3; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, false, "node-1-3-10-03"); + VespaModel model = tester.createModel(services, false, "node-1-3-50-03"); assertEquals(numberOfHosts, model.getRoot().hostSystem().getHosts().size()); ContentCluster cluster = model.getContentClusters().get("bar"); @@ -1133,7 +1136,7 @@ public class ModelProvisioningTest { int numberOfHosts = 5; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, false, "node-1-3-10-05", "node-1-3-10-04", "node-1-3-10-03"); + VespaModel model = tester.createModel(services, false, "node-1-3-50-05", "node-1-3-50-04", "node-1-3-50-03"); assertEquals(numberOfHosts, model.getRoot().hostSystem().getHosts().size()); ContentCluster cluster = model.getContentClusters().get("bar"); @@ -1162,7 +1165,7 @@ public class ModelProvisioningTest { int numberOfHosts = 3; VespaModelTester tester = new VespaModelTester(); tester.addHosts(numberOfHosts); - VespaModel model = tester.createModel(services, false, false, true, "node-1-3-10-03"); + VespaModel model = tester.createModel(services, false, false, true, "node-1-3-50-03"); assertEquals(numberOfHosts, model.getRoot().hostSystem().getHosts().size()); ContentCluster cluster = model.getContentClusters().get("bar"); @@ -1474,10 +1477,12 @@ public class ModelProvisioningTest { } @Test - public void testUseArm64NodesForClusterControllers() { + public void testUseArm64NodesForAdminCluster() { String services = "<?xml version='1.0' encoding='utf-8' ?>" + "<services>" + + " <admin version='4.0'>" + + " </admin>" + " <container version='1.0' id='container'>" + " <nodes count='2'>" + " <resources vcpu='2' memory='8Gb' disk='30Gb'/>" + @@ -1495,25 +1500,34 @@ public class ModelProvisioningTest { VespaModelTester tester = new VespaModelTester(); tester.setHosted(true); - tester.setAdminClusterArchitecture("arm64"); - tester.addHosts(new NodeResources(13.5, 100, 1000, 0.3), 6); - tester.addHosts(new NodeResources(85, 200, 1000_000_000, 0.3), 20); - tester.addHosts(new NodeResources(0.5, 2, 10, 0.3, NodeResources.DiskSpeed.any, NodeResources.StorageType.any, NodeResources.Architecture.arm64), 3); + tester.setAdminClusterArchitecture(Architecture.arm64); + tester.useDedicatedNodeForLogserver(true); + tester.addHosts(new NodeResources(13.5, 100, 1000, 0.3), 4); + tester.addHosts(new NodeResources(0.5, 2, 50, 0.3, DiskSpeed.fast, StorageType.any, Architecture.arm64), 4); // 3 ccs, 1 logserver VespaModel model = tester.createModel(services, true, true); List<HostResource> hosts = model.getRoot().hostSystem().getHosts(); - assertEquals(7, hosts.size()); - Set<HostResource> clusterControllerResources = - hosts.stream() - .filter(host -> host.getHostInfo().getServices().stream() - .anyMatch(service -> service.getServiceType().equals("container-clustercontroller"))) - .collect(Collectors.toSet()); + assertEquals(8, hosts.size()); + + Set<HostResource> clusterControllerResources = getHostResourcesForService(hosts, "container-clustercontroller"); assertEquals(3, clusterControllerResources.size()); - assertTrue(clusterControllerResources.stream().allMatch(host -> host.realResources().architecture().name().equals("arm64"))); + assertTrue(clusterControllerResources.stream().allMatch(host -> host.realResources().architecture() == Architecture.arm64)); - // Other hosts should be x86_64 + Set<HostResource> logserverResources = getHostResourcesForService(hosts, "logserver-container"); + assertEquals(1, logserverResources.size()); + assertTrue(logserverResources.stream().allMatch(host -> host.realResources().architecture() == Architecture.arm64)); + + // Other hosts should be default assertTrue(hosts.stream() .filter(host -> !clusterControllerResources.contains(host)) - .allMatch(host -> host.realResources().architecture().name().equals("x86_64"))); + .filter(host -> !logserverResources.contains(host)) + .allMatch(host -> host.realResources().architecture() == Architecture.getDefault())); + } + + private Set<HostResource> getHostResourcesForService(List<HostResource> hosts, String service) { + return hosts.stream() + .filter(host -> host.getHostInfo().getServices().stream() + .anyMatch(s -> s.getServiceType().equals(service))) + .collect(Collectors.toSet()); } @Test @@ -2132,7 +2146,7 @@ public class ModelProvisioningTest { "</services>"; VespaModelTester tester = new VespaModelTester(); tester.addHosts(4); - VespaModel model = tester.createModel(servicesXml, true, "node-1-3-10-04"); + VespaModel model = tester.createModel(servicesXml, true, "node-1-3-50-04"); ApplicationContainerCluster cluster = model.getContainerClusters().get("zk"); assertEquals(1, cluster.getContainers().stream().filter(Container::isRetired).count()); assertEquals(3, cluster.getContainers().stream().filter(c -> !c.isRetired()).count()); @@ -2161,7 +2175,7 @@ public class ModelProvisioningTest { assertTrue("Initial servers are not joining", config.build().server().stream().noneMatch(ZookeeperServerConfig.Server::joining)); } { - VespaModel nextModel = tester.createModel(Zone.defaultZone(), servicesXml.apply(3), true, false, false, 0, Optional.of(model), new DeployState.Builder(), "node-1-3-10-04", "node-1-3-10-03"); + VespaModel nextModel = tester.createModel(Zone.defaultZone(), servicesXml.apply(3), true, false, false, 0, Optional.of(model), new DeployState.Builder(), "node-1-3-50-04", "node-1-3-50-03"); ApplicationContainerCluster cluster = nextModel.getContainerClusters().get("zk"); ZookeeperServerConfig.Builder config = new ZookeeperServerConfig.Builder(); cluster.getContainers().forEach(c -> c.getConfig(config)); diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentGraphValidatorTest.java b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentGraphValidatorTest.java index 8c8cb59e9d9..5bbb751585b 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentGraphValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentGraphValidatorTest.java @@ -3,7 +3,6 @@ package com.yahoo.searchdefinition; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.searchdefinition.document.SDDocumentType; import com.yahoo.searchdefinition.document.SDField; import com.yahoo.searchdefinition.document.TemporarySDField; diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java index b23ad4eb5b6..fe1b19be64b 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java @@ -4,7 +4,6 @@ package com.yahoo.searchdefinition; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.document.DataType; import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.searchdefinition.document.SDDocumentType; import com.yahoo.searchdefinition.document.SDField; import org.junit.Rule; diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SchemaOrdererTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SchemaOrdererTestCase.java index ed3f5cb0ba6..11e21c7915d 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SchemaOrdererTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SchemaOrdererTestCase.java @@ -3,7 +3,6 @@ package com.yahoo.searchdefinition.derived; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.searchdefinition.DocumentReference; import com.yahoo.searchdefinition.DocumentReferences; import com.yahoo.searchdefinition.Schema; diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/VsmFieldsTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/VsmFieldsTestCase.java index 2d6b3acc4dd..9855ca30ebc 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/VsmFieldsTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/VsmFieldsTestCase.java @@ -5,7 +5,6 @@ import com.yahoo.config.model.application.provider.MockFileRegistry; import com.yahoo.config.model.deploy.TestProperties; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.searchdefinition.Application; import com.yahoo.searchdefinition.Schema; import com.yahoo.searchdefinition.document.SDDocumentType; diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/parser/IntermediateParserTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/parser/IntermediateParserTestCase.java index 8bd04af8c54..36a72381156 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/parser/IntermediateParserTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/parser/IntermediateParserTestCase.java @@ -69,7 +69,7 @@ public class IntermediateParserTestCase { " }", "}"); var e = assertThrows(IllegalArgumentException.class, () -> parseString(input)); - assertEquals("schema 'foo' error: already has document foo so cannot add document foo2", e.getMessage()); + assertEquals("schema 'foo' error: already has document 'foo' so cannot add document 'foo2'", e.getMessage()); } void checkFileParses(String fileName) throws Exception { diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/parser/ParsedDocumentTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/parser/ParsedDocumentTestCase.java index 79d26fab404..9ae7b3aa4b8 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/parser/ParsedDocumentTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/parser/ParsedDocumentTestCase.java @@ -21,7 +21,10 @@ public class ParsedDocumentTestCase { var e = assertThrows(IllegalArgumentException.class, () -> doc.addField(new ParsedField("zap", stringType))); System.err.println("As expected: "+e); - assertEquals("document 'foo' error: already has field zap", e.getMessage()); + assertEquals("document 'foo' error: Duplicate (case insensitively) field 'zap' in document type 'foo'", e.getMessage()); + e = assertThrows(IllegalArgumentException.class, () -> + doc.addField(new ParsedField("ZAP", stringType))); + assertEquals("document 'foo' error: Duplicate (case insensitively) field 'ZAP' in document type 'foo'", e.getMessage()); } } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ParentChildSearchModel.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ParentChildSearchModel.java index 0b615595794..6ddacd066b1 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ParentChildSearchModel.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ParentChildSearchModel.java @@ -7,7 +7,6 @@ import com.yahoo.config.model.deploy.TestProperties; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.document.DataType; import com.yahoo.documentmodel.NewDocumentReferenceDataType; -import com.yahoo.document.TemporaryStructuredDataType; import com.yahoo.searchdefinition.Application; import com.yahoo.searchdefinition.DocumentReference; import com.yahoo.searchdefinition.DocumentReferences; diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java index c00a5f65d08..7bf08461df7 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java @@ -104,7 +104,7 @@ public class MetricsProxyContainerClusterTest { private void assertNodeConfig(MetricsNodesConfig.Node node) { assertTrue(node.role().startsWith("container/foo/0/")); - assertTrue(node.hostname().startsWith("node-1-3-10-")); + assertTrue(node.hostname().startsWith("node-1-3-50-")); assertEquals(MetricsProxyContainer.BASEPORT, node.metricsPort()); assertEquals(MetricsV1Handler.VALUES_PATH, node.metricsPath()); } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerTest.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerTest.java index ad3a163f052..9b1ff54482b 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerTest.java @@ -136,7 +136,7 @@ public class MetricsProxyContainerTest { NodeInfoConfig config = hostedModel.getConfig(NodeInfoConfig.class, metricsV2Handler.getConfigId()); assertTrue(config.role().startsWith("content/my-content/0/")); - assertTrue(config.hostname().startsWith("node-1-3-10-")); + assertTrue(config.hostname().startsWith("node-1-3-50-")); } @Test diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java index b9a5fde9301..41f9b4c7b55 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import static com.yahoo.config.provision.NodeResources.Architecture; import static com.yahoo.vespa.model.test.utils.ApplicationPackageUtils.generateSchemas; /** @@ -53,7 +54,7 @@ public class VespaModelTester { private final Map<NodeResources, Collection<Host>> hostsByResources = new HashMap<>(); private ApplicationId applicationId = ApplicationId.defaultId(); private boolean useDedicatedNodeForLogserver = false; - private String adminClusterArchitecture = "x86_64"; + private Architecture adminClusterArchitecture = Architecture.getDefault();; private HostProvisioner provisioner; public VespaModelTester() { @@ -102,7 +103,9 @@ public class VespaModelTester { public void setHosted(boolean hosted) { this.hosted = hosted; } /** Sets architecture to use for admin clusters. Default: x86_64 */ - public void setAdminClusterArchitecture(String architecture) { this.adminClusterArchitecture = architecture; } + public void setAdminClusterArchitecture(Architecture architecture) { + this.adminClusterArchitecture = architecture; + } /** Sets the tenant, application name, and instance name of the model being built. */ public void setApplicationId(String tenant, String applicationName, String instanceName) { diff --git a/config/src/vespa/config/frt/frtconnectionpool.cpp b/config/src/vespa/config/frt/frtconnectionpool.cpp index 2ae812cd76e..0c11401e052 100644 --- a/config/src/vespa/config/frt/frtconnectionpool.cpp +++ b/config/src/vespa/config/frt/frtconnectionpool.cpp @@ -73,11 +73,13 @@ FRTConnectionPool::getNextRoundRobin() FRTConnection* nextFRTConnection = nullptr; if ( ! ready.empty()) { - int sel = _selectIdx % (int)ready.size(); + unsigned int sel = _selectIdx % (int)ready.size(); + LOG_ASSERT(sel < ready.size()); _selectIdx = sel + 1; nextFRTConnection = ready[sel]; } else if ( ! suspended.empty()) { - int sel = _selectIdx % (int)suspended.size(); + unsigned int sel = _selectIdx % (int)suspended.size(); + LOG_ASSERT(sel < suspended.size()); _selectIdx = sel + 1; nextFRTConnection = suspended[sel]; } @@ -113,10 +115,12 @@ FRTConnectionPool::getNextHashBased() FRTConnection* nextFRTConnection = nullptr; if ( ! ready.empty()) { - int sel = std::abs(hashCode(_hostname) % (int)ready.size()); + unsigned int sel = std::abs(hashCode(_hostname) % (int)ready.size()); + LOG_ASSERT(sel < ready.size()); nextFRTConnection = ready[sel]; } else if ( ! suspended.empty() ){ - int sel = std::abs(hashCode(_hostname) % (int)suspended.size()); + unsigned int sel = std::abs(hashCode(_hostname) % (int)suspended.size()); + LOG_ASSERT(sel < suspended.size()); nextFRTConnection = suspended[sel]; } return nextFRTConnection; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 1cfc7758def..718a25cc225 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -42,6 +42,7 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.function.ToIntFunction; +import static com.yahoo.config.provision.NodeResources.Architecture; import static com.yahoo.vespa.config.server.ConfigServerSpec.fromConfig; import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE; @@ -211,7 +212,7 @@ public class ModelContextImpl implements ModelContext { private final boolean avoidRenamingSummaryFeatures; private final boolean mergeGroupingResultInSearchInvoker; private final boolean experimentalSdParsing; - private final String adminClusterNodeResourcesArchitecture; + private final Architecture adminClusterNodeResourcesArchitecture; public FeatureFlags(FlagSource source, ApplicationId appId, Version version) { this.defaultTermwiseLimit = flagValue(source, appId, version, Flags.DEFAULT_TERM_WISE_LIMIT); @@ -261,7 +262,7 @@ public class ModelContextImpl implements ModelContext { this.avoidRenamingSummaryFeatures = flagValue(source, appId, version, Flags.AVOID_RENAMING_SUMMARY_FEATURES); this.mergeGroupingResultInSearchInvoker = flagValue(source, appId, version, Flags.MERGE_GROUPING_RESULT_IN_SEARCH_INVOKER); this.experimentalSdParsing = flagValue(source, appId, version, Flags.EXPERIMENTAL_SD_PARSING); - this.adminClusterNodeResourcesArchitecture = flagValue(source, appId, version, PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE); + this.adminClusterNodeResourcesArchitecture = Architecture.valueOf(flagValue(source, appId, version, PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE)); } @Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; } @@ -313,7 +314,8 @@ public class ModelContextImpl implements ModelContext { @Override public boolean avoidRenamingSummaryFeatures() { return avoidRenamingSummaryFeatures; } @Override public boolean mergeGroupingResultInSearchInvoker() { return mergeGroupingResultInSearchInvoker; } @Override public boolean experimentalSdParsing() { return experimentalSdParsing; } - @Override public String adminClusterNodeArchitecture() { return adminClusterNodeResourcesArchitecture; } + @Override public String adminClusterNodeArchitecture() { return adminClusterArchitecture().name(); } // TODO: Remove when 7.564 is oldest version in use + @Override public Architecture adminClusterArchitecture() { return adminClusterNodeResourcesArchitecture; } private static <V> V flagValue(FlagSource source, ApplicationId appId, Version vespaVersion, UnboundFlag<? extends V, ?, ?> flag) { return flag.bindTo(source) diff --git a/configutil/src/apps/configstatus/main.cpp b/configutil/src/apps/configstatus/main.cpp index cd0424633d9..3656013cf2e 100644 --- a/configutil/src/apps/configstatus/main.cpp +++ b/configutil/src/apps/configstatus/main.cpp @@ -87,7 +87,7 @@ void Application::usage() { int Application::Main() { parseOpts(); - + fprintf(stderr, "Getting config from: %s\n", _specString.c_str()); config::ServerSpec spec(_specString); config::ConfigUri uri = config::ConfigUri::createFromSpec(_cfgId, spec); ConfigStatus status(_flags, uri); diff --git a/configutil/src/lib/configstatus.cpp b/configutil/src/lib/configstatus.cpp index 841d1604866..98a6bca7ba3 100644 --- a/configutil/src/lib/configstatus.cpp +++ b/configutil/src/lib/configstatus.cpp @@ -109,7 +109,7 @@ public: MyHttpHandler::~MyHttpHandler() = default; -ConfigStatus::ConfigStatus(Flags flags, const config::ConfigUri uri) +ConfigStatus::ConfigStatus(Flags flags, const config::ConfigUri &uri) : _cfg(), _flags(flags), _generation(0) { if (_flags.verbose) { diff --git a/configutil/src/lib/configstatus.h b/configutil/src/lib/configstatus.h index 4d792748419..7d658c9f2c2 100644 --- a/configutil/src/lib/configstatus.h +++ b/configutil/src/lib/configstatus.h @@ -22,7 +22,7 @@ public: {} }; - ConfigStatus(Flags flags, const config::ConfigUri uri); + ConfigStatus(Flags flags, const config::ConfigUri &uri); ~ConfigStatus(); int action(); diff --git a/configutil/src/lib/modelinspect.cpp b/configutil/src/lib/modelinspect.cpp index d840a7d45ca..68544a55df4 100644 --- a/configutil/src/lib/modelinspect.cpp +++ b/configutil/src/lib/modelinspect.cpp @@ -21,7 +21,7 @@ ModelInspect::Flags::Flags(const Flags &) = default; ModelInspect::Flags & ModelInspect::Flags::operator = (const Flags &) = default; ModelInspect::Flags::~Flags() { } -ModelInspect::ModelInspect(Flags flags, const config::ConfigUri uri, std::ostream &out) +ModelInspect::ModelInspect(Flags flags, const config::ConfigUri &uri, std::ostream &out) : _cfg(), _flags(flags), _out(out) { if (_flags.verbose) { diff --git a/configutil/src/lib/modelinspect.h b/configutil/src/lib/modelinspect.h index 33ef94b259b..0c677b9d174 100644 --- a/configutil/src/lib/modelinspect.h +++ b/configutil/src/lib/modelinspect.h @@ -20,7 +20,7 @@ public: ~Flags(); }; - ModelInspect(Flags flags, const config::ConfigUri uri, std::ostream &out); + ModelInspect(Flags flags, const config::ConfigUri &uri, std::ostream &out); virtual ~ModelInspect(); int action(int cnt, char *argv[]); diff --git a/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java b/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java index f0a11626236..d571bf583d6 100644 --- a/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java +++ b/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java @@ -67,7 +67,7 @@ public final class CompoundName { this.name = name; this.lowerCasedName = toLowerCase(name); - if (compounds.size()==1 && compounds.get(0).isEmpty()) + if (compounds.size() == 1 && compounds.get(0).isEmpty()) this.compounds = ImmutableList.of(); else this.compounds = ImmutableList.copyOf(compounds); diff --git a/container-search/abi-spec.json b/container-search/abi-spec.json index 4d559fcb985..5b990ca8758 100644 --- a/container-search/abi-spec.json +++ b/container-search/abi-spec.json @@ -720,6 +720,7 @@ "public static final enum com.yahoo.prelude.query.Item$ItemType WORD", "public static final enum com.yahoo.prelude.query.Item$ItemType INT", "public static final enum com.yahoo.prelude.query.Item$ItemType PHRASE", + "public static final enum com.yahoo.prelude.query.Item$ItemType MULTI_TERM", "public static final enum com.yahoo.prelude.query.Item$ItemType PREFIX", "public static final enum com.yahoo.prelude.query.Item$ItemType SUBSTRING", "public static final enum com.yahoo.prelude.query.Item$ItemType NEAR", @@ -741,7 +742,6 @@ "public static final enum com.yahoo.prelude.query.Item$ItemType GEO_LOCATION_TERM", "public static final enum com.yahoo.prelude.query.Item$ItemType TRUE", "public static final enum com.yahoo.prelude.query.Item$ItemType FALSE", - "public static final enum com.yahoo.prelude.query.Item$ItemType MULTI_TERM", "public final int code" ] }, diff --git a/container-search/src/main/java/com/yahoo/prelude/query/Item.java b/container-search/src/main/java/com/yahoo/prelude/query/Item.java index 06fe07d3895..2e0c3cf8593 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/Item.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/Item.java @@ -26,10 +26,7 @@ import java.util.Objects; */ public abstract class Item implements Cloneable { - /** - * The definitions in Item.ItemType must match the ones in - * searchlib/src/vespa/searchlib/parsequery/parse.h - */ + // These must match the types in searchlib/src/vespa/searchlib/parsequery/parse.h public enum ItemType { OR(0), AND(1), @@ -38,7 +35,7 @@ public abstract class Item implements Cloneable { WORD(4), INT(5), PHRASE(6), - // 7 was PAREN, unused in Vespa 7 + MULTI_TERM(7), PREFIX(8), SUBSTRING(9), NEAR(11), @@ -59,8 +56,7 @@ public abstract class Item implements Cloneable { NEAREST_NEIGHBOR(26), GEO_LOCATION_TERM(27), TRUE(28), - FALSE(29), - MULTI_TERM(30); + FALSE(29); public final int code; @@ -70,10 +66,7 @@ public abstract class Item implements Cloneable { } - /** - * The definitions in Item.ItemCreator must match the ones in - * searchlib/src/searchlib/parsequery/parse.h - */ + // These must match the definitions in searchlib/src/searchlib/parsequery/parse.h public enum ItemCreator { ORIG(0), @@ -266,11 +259,11 @@ public abstract class Item implements Cloneable { } /** - * Returns an integer that contains all feature flags for this item. This must be kept in sync with the flags - * defined in searchlib/parsequery/parse.h. + * Returns an integer that contains all feature flags for this item. * * @return the feature flags */ + // This must be kept in sync with the flags in searchlib/parsequery/parse.h. private byte getFlagsFeature() { byte FLAGS_NORANK = 0x01; byte FLAGS_SPECIALTOKEN = 0x02; @@ -419,7 +412,7 @@ public abstract class Item implements Cloneable { * the back-end to identify specific items for ranking purposes. * * @param label label for this item - **/ + */ public void setLabel(String label) { setHasUniqueID(true); this.label = label; diff --git a/container-search/src/main/java/com/yahoo/search/grouping/request/DocIdNsSpecificValue.java b/container-search/src/main/java/com/yahoo/search/grouping/request/DocIdNsSpecificValue.java index 353e92c723f..b7d8ce9fc77 100644 --- a/container-search/src/main/java/com/yahoo/search/grouping/request/DocIdNsSpecificValue.java +++ b/container-search/src/main/java/com/yahoo/search/grouping/request/DocIdNsSpecificValue.java @@ -10,9 +10,7 @@ package com.yahoo.search.grouping.request; */ public class DocIdNsSpecificValue extends DocumentValue { - /** - * Constructs a new instance of this class. - */ + /** Constructs a new instance of this class. */ public DocIdNsSpecificValue() { this(null, null); } diff --git a/container-search/src/main/java/com/yahoo/search/query/QueryTree.java b/container-search/src/main/java/com/yahoo/search/query/QueryTree.java index 115a2f6dbdc..3dac5648660 100644 --- a/container-search/src/main/java/com/yahoo/search/query/QueryTree.java +++ b/container-search/src/main/java/com/yahoo/search/query/QueryTree.java @@ -48,7 +48,7 @@ public class QueryTree extends CompositeItem { return getRoot().encode(buffer); } - //Lets not pollute toString() by adding "ROOT" + // Let's not pollute toString() by adding "ROOT" protected void appendHeadingString(StringBuilder sb) { } @@ -65,7 +65,7 @@ public class QueryTree extends CompositeItem { if (this.getItemCount() == 0) // initializing super.addItem(root); else - setItem(0,root); // replacing + setItem(0, root); // replacing } @Override @@ -88,7 +88,7 @@ public class QueryTree extends CompositeItem { @Override public void addItem(Item item) { - if (getItemCount()==0) + if (getItemCount() == 0) super.addItem(item); else throw new RuntimeException("Programming error: Cannot add multiple roots"); @@ -96,8 +96,8 @@ public class QueryTree extends CompositeItem { @Override public void addItem(int index, Item item) { - if (getItemCount()==0 && index==0) - super.addItem(index,item); + if (getItemCount() == 0 && index == 0) + super.addItem(index, item); else throw new RuntimeException("Programming error: Cannot add multiple roots, have '" + getRoot() + "'"); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java index 6ee5b5a314f..dc8b22ac32d 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java @@ -100,4 +100,12 @@ public interface IssueHandler { */ boolean issueExists(Issue issue); + /** + * Returns information about project identified by the project key + * + * @param projectKey The project key to find information for + * @return Project info for project + * @throws RuntimeException exception if project not found + */ + ProjectInfo projectInfo(String projectKey); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java index 021f05f4d1f..257d2ff5e67 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java @@ -24,6 +24,7 @@ public class MockIssueHandler implements IssueHandler { private final Clock clock; private final AtomicLong counter = new AtomicLong(); private final Map<IssueId, MockIssue> issues = new HashMap<>(); + private final Map<String, ProjectInfo> projects = new HashMap<>(); @Inject @SuppressWarnings("unused") @@ -112,6 +113,11 @@ public class MockIssueHandler implements IssueHandler { return issues.values().stream().anyMatch(i -> i.issue.summary().equals(issue.summary())); } + @Override + public ProjectInfo projectInfo(String projectKey) { + return projects.get(projectKey); + } + public MockIssueHandler close(IssueId issueId) { issues.get(issueId).open = false; touch(issueId); @@ -137,6 +143,10 @@ public class MockIssueHandler implements IssueHandler { issues.get(issueId).updated = clock.instant(); } + public void addProject(String projectKey, ProjectInfo projectInfo) { + projects.put(projectKey, projectInfo); + } + private static class PropertyInfo { private List<List<User>> contacts = Collections.emptyList(); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/ProjectInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/ProjectInfo.java new file mode 100644 index 00000000000..8bf2ebfd092 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/ProjectInfo.java @@ -0,0 +1,31 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.organization; + +import java.util.Map; + +/** + * @author jvenstad + * @author mortent + */ +public class ProjectInfo { + + private final String id; + private final Map<String, String> componentIds; + + public ProjectInfo(String id, Map<String, String> componentIds) { + this.id = id; + this.componentIds = componentIds; + } + + public boolean hasComponent(String component) { + return componentIds.containsKey(component); + } + + public String id() { + return id; + } + + public Map<String, String> componentIds() { + return componentIds; + } +}
\ No newline at end of file diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 246f3fff17e..d9a38a5b578 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -1883,6 +1883,13 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { private HttpResponse content(String tenantName, String applicationName, String instanceName, String environment, String region, String restPath, HttpRequest request) { DeploymentId deploymentId = new DeploymentId(ApplicationId.from(tenantName, applicationName, instanceName), requireZone(environment, region)); + + String normalizedRestPath = URI.create("content/" + restPath).normalize().toString(); + // Only content/ is allowed + if ( ! normalizedRestPath.startsWith("content/")) { + return ErrorResponse.forbidden("Access denied"); + } + return controller.serviceRegistry().configServer().getApplicationPackageContent(deploymentId, "/" + restPath, request.getUri()); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 8ab43f15c89..f94f87b0f46 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -500,6 +500,9 @@ public class ApplicationApiTest extends ControllerContainerTest { .userIdentity(USER_ID), "INFO - All good"); + // Get content/../foo + tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/instance/default/environment/dev/region/us-east-1/content/%2E%2E%2Ffoo", GET).userIdentity(USER_ID), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"Access denied\"}", 403); // Get content - root tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/instance/default/environment/dev/region/us-east-1/content/", GET).userIdentity(USER_ID), "{\"path\":\"/\"}"); diff --git a/document/src/tests/arrayfieldvaluetest.cpp b/document/src/tests/arrayfieldvaluetest.cpp index 375ce05a4e6..86cd50cf965 100644 --- a/document/src/tests/arrayfieldvaluetest.cpp +++ b/document/src/tests/arrayfieldvaluetest.cpp @@ -105,7 +105,7 @@ TEST(ArrayFieldValueTest, testArray) // Iterating const ArrayFieldValue& constVal(value); for(const FieldValue & fval1 : constVal) { - EXPECT_EQ((uint32_t) IntFieldValue::classId, fval1.getClass().id()); + EXPECT_EQ(FieldValue::Type::INT, fval1.type()); } value2 = value; for(size_t i(0); i < value2.size(); i++) { diff --git a/document/src/tests/documenttestcase.cpp b/document/src/tests/documenttestcase.cpp index c852e219faa..4c97e99459e 100644 --- a/document/src/tests/documenttestcase.cpp +++ b/document/src/tests/documenttestcase.cpp @@ -50,11 +50,11 @@ TEST(DocumentTest, testSizeOf) EXPECT_EQ(32u, sizeof(vespalib::GrowableByteBuffer)); EXPECT_EQ(88ul, sizeof(IdString)); EXPECT_EQ(104ul, sizeof(DocumentId)); - EXPECT_EQ(240ul, sizeof(Document)); + EXPECT_EQ(256ul, sizeof(Document)); EXPECT_EQ(80ul, sizeof(NumericDataType)); EXPECT_EQ(24ul, sizeof(LongFieldValue)); - EXPECT_EQ(96ul, sizeof(StructFieldValue)); - EXPECT_EQ(16ul, sizeof(StructuredFieldValue)); + EXPECT_EQ(104ul, sizeof(StructFieldValue)); + EXPECT_EQ(24ul, sizeof(StructuredFieldValue)); EXPECT_EQ(56ul, sizeof(SerializableArray)); } @@ -931,48 +931,6 @@ TEST(DocumentTest, testCRC32) /// \todo TODO (was warning): Cannot test for in memory representation altered, as there is no syntax for getting internal refs to data from document. Add test when this is added. } -TEST(DocumentTest, testHasChanged) -{ - TestDocRepo test_repo; - Document doc(*test_repo.getDocumentType("testdoctype1"), - DocumentId("id:ns:testdoctype1::crawler:http://www.ntnu.no/")); - // Before deserialization we are changed. - EXPECT_TRUE(doc.hasChanged()); - - doc.setValue(doc.getField("hstringval"), StringFieldValue("bla bla bla bla bla")); - // Still changed after setting a value of course. - EXPECT_TRUE(doc.hasChanged()); - - nbostream buf; - doc.serialize(buf); - // Setting a value in doc tags us changed. - { - buf.rp(0); - Document doc2(test_repo.getTypeRepo(), buf); - EXPECT_TRUE(!doc2.hasChanged()); - - doc2.setValue("headerval", IntFieldValue::make(13)); - EXPECT_TRUE(doc2.hasChanged()); - } - // Overwriting a value in doc tags us changed. - { - buf.rp(0); - Document doc2(test_repo.getTypeRepo(), buf); - - doc2.setValue("hstringval", StringFieldValue::make("bla bla bla bla bla")); - EXPECT_TRUE(doc2.hasChanged()); - } - // Clearing value tags us changed. - { - buf.rp(0); - Document doc2(test_repo.getTypeRepo(), buf); - - doc2.clear(); - EXPECT_TRUE(doc2.hasChanged()); - } - // Add more tests here when we allow non-const refs to internals -} - TEST(DocumentTest, testSliceSerialize) { // Test that document doesn't need its own bytebuffer, such that we diff --git a/document/src/tests/documentupdatetestcase.cpp b/document/src/tests/documentupdatetestcase.cpp index 26819699db4..e1e86bca671 100644 --- a/document/src/tests/documentupdatetestcase.cpp +++ b/document/src/tests/documentupdatetestcase.cpp @@ -495,7 +495,7 @@ TEST(DocumentUpdateTest, testReadSerializedFile) const AddValueUpdate* add = static_cast<const AddValueUpdate*>(serValue); const FieldValue* value = &add->getValue(); - EXPECT_TRUE(value->inherits(FloatFieldValue::classId)); + EXPECT_TRUE(value->isA(FieldValue::Type::FLOAT)); EXPECT_FLOAT_EQ(value->getAsFloat(), 5.00f); serValue = &serField3[1]; @@ -503,7 +503,7 @@ TEST(DocumentUpdateTest, testReadSerializedFile) add = static_cast<const AddValueUpdate*>(serValue); value = &add->getValue(); - EXPECT_TRUE(value->inherits(FloatFieldValue::classId)); + EXPECT_TRUE(value->isA(FieldValue::Type::FLOAT)); EXPECT_FLOAT_EQ(value->getAsFloat(), 4.23f); serValue = &serField3[2]; @@ -511,7 +511,7 @@ TEST(DocumentUpdateTest, testReadSerializedFile) add = static_cast<const AddValueUpdate*>(serValue); value = &add->getValue(); - EXPECT_TRUE(value->inherits(FloatFieldValue::classId)); + EXPECT_TRUE(value->isA(FieldValue::Type::FLOAT)); EXPECT_FLOAT_EQ(value->getAsFloat(), -1.00f); } diff --git a/document/src/tests/fieldvalue/fieldvalue_test.cpp b/document/src/tests/fieldvalue/fieldvalue_test.cpp index d8712768000..d27877f68c3 100644 --- a/document/src/tests/fieldvalue/fieldvalue_test.cpp +++ b/document/src/tests/fieldvalue/fieldvalue_test.cpp @@ -21,7 +21,7 @@ TEST("require that StringFieldValue can be assigned primitives") { } TEST("require that FieldValues does not change their storage size.") { - EXPECT_EQUAL(8u, sizeof(FieldValue)); + EXPECT_EQUAL(16u, sizeof(FieldValue)); EXPECT_EQUAL(16u, sizeof(IntFieldValue)); EXPECT_EQUAL(24u, sizeof(LongFieldValue)); EXPECT_EQUAL(104u, sizeof(StringFieldValue)); diff --git a/document/src/tests/fieldvalue/referencefieldvalue_test.cpp b/document/src/tests/fieldvalue/referencefieldvalue_test.cpp index db380353a55..fccce30aaf8 100644 --- a/document/src/tests/fieldvalue/referencefieldvalue_test.cpp +++ b/document/src/tests/fieldvalue/referencefieldvalue_test.cpp @@ -7,7 +7,6 @@ #include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/exceptions.h> #include <ostream> -#include <sstream> using namespace document; @@ -44,14 +43,6 @@ TEST_F("Reference can be constructed with document ID", Fixture) { EXPECT_EQUAL(DocumentId("id:ns:foo::itsa-me"), fv.getDocumentId()); } -TEST_F("Newly constructed reference is marked as changed", Fixture) { - ReferenceFieldValue fv(f.refType); - EXPECT_TRUE(fv.hasChanged()); - - ReferenceFieldValue fv2(f.refType, DocumentId("id:ns:foo::itsa-me")); - EXPECT_TRUE(fv2.hasChanged()); -} - TEST_F("Exception is thrown if constructor doc ID type does not match referenced document type", Fixture) { EXPECT_EXCEPTION( ReferenceFieldValue(f.refType, DocumentId("id:ns:bar::wario-time")), @@ -78,12 +69,6 @@ TEST_F("Can explicitly assign new document ID to reference", Fixture) { EXPECT_EQUAL(f.refType, *fv.getDataType()); } -TEST_F("Assigning explicit document ID clears changed-flag", Fixture) { - ReferenceFieldValue fv(f.refType); - fv.setDeserializedDocumentId(DocumentId("id:ns:foo::yoshi-eggs")); - EXPECT_FALSE(fv.hasChanged()); -} - TEST_F("Exception is thrown if explicitly assigned doc ID does not have same type as reference target type", Fixture) { ReferenceFieldValue fv(f.refType); @@ -104,19 +89,6 @@ TEST_F("assign()ing another reference field value assigns doc ID and type", Fixt EXPECT_EQUAL(src.getDataType(), dest.getDataType()); } -// Different FieldValue subclasses actually disagree on whether this should be -// the case, e.g. LiteralFieldValue and TensorFieldValue. We go with the -// latter's approach, as that should be the most conservative one. -TEST_F("assign() marks assignee as changed", Fixture) { - ReferenceFieldValue src(f.refType, DocumentId("id:ns:foo::yoshi")); - ReferenceFieldValue dest(f.refType); - - dest.setDeserializedDocumentId(DocumentId("id:ns:foo::yoshi-eggs")); - EXPECT_FALSE(dest.hasChanged()); - - dest.assign(src); - EXPECT_TRUE(dest.hasChanged()); -} TEST_F("clone()ing creates new instance with same ID and type", Fixture) { ReferenceFieldValue src(f.refType, DocumentId("id:ns:foo::yoshi")); @@ -126,7 +98,6 @@ TEST_F("clone()ing creates new instance with same ID and type", Fixture) { ASSERT_TRUE(cloned->hasValidDocumentId()); EXPECT_EQUAL(src.getDocumentId(), cloned->getDocumentId()); EXPECT_EQUAL(src.getDataType(), cloned->getDataType()); - EXPECT_TRUE(cloned->hasChanged()); } TEST_F("Can clone() value without document ID", Fixture) { @@ -136,7 +107,6 @@ TEST_F("Can clone() value without document ID", Fixture) { ASSERT_TRUE(cloned); EXPECT_FALSE(cloned->hasValidDocumentId()); EXPECT_EQUAL(src.getDataType(), cloned->getDataType()); - EXPECT_TRUE(cloned->hasChanged()); } TEST_F("compare() orders first on type ID, then on document ID", Fixture) { diff --git a/document/src/tests/serialization/vespadocumentserializer_test.cpp b/document/src/tests/serialization/vespadocumentserializer_test.cpp index 33e8c521e09..3db001e1732 100644 --- a/document/src/tests/serialization/vespadocumentserializer_test.cpp +++ b/document/src/tests/serialization/vespadocumentserializer_test.cpp @@ -986,22 +986,6 @@ TEST_F("ReferenceFieldValue with ID can be roundtrip serialized", RefFixture) { serializeAndDeserialize(ref_with_id, stream, f.fixed_repo); } -TEST_F("Empty ReferenceFieldValue has changed-flag cleared after deserialization", RefFixture) { - ReferenceFieldValue src(f.ref_type()); - ReferenceFieldValue dest(f.ref_type()); - f.roundtrip_serialize(src, dest); - - EXPECT_FALSE(dest.hasChanged()); -} - -TEST_F("ReferenceFieldValue with ID has changed-flag cleared after deserialization", RefFixture) { - ReferenceFieldValue src(f.ref_type(), DocumentId("id:ns:" + doc_name + "::foo")); - ReferenceFieldValue dest(f.ref_type()); - f.roundtrip_serialize(src, dest); - - EXPECT_FALSE(dest.hasChanged()); -} - TEST_F("Empty ReferenceFieldValue serialization matches Java", RefFixture) { ReferenceFieldValue value(f.ref_type()); f.verify_cross_language_serialization("empty_reference", value); diff --git a/document/src/tests/weightedsetfieldvaluetest.cpp b/document/src/tests/weightedsetfieldvaluetest.cpp index 61f727120d1..4cc897f22d7 100644 --- a/document/src/tests/weightedsetfieldvaluetest.cpp +++ b/document/src/tests/weightedsetfieldvaluetest.cpp @@ -141,8 +141,7 @@ TEST(WeightedSetFieldValueTest, testWeightedSet) { const FieldValue& fval1(*it->first); (void) fval1; - EXPECT_EQ((uint32_t) IntFieldValue::classId, - it->first->getClass().id()); + EXPECT_TRUE(it->first->isA(FieldValue::Type::INT)); const IntFieldValue& val = dynamic_cast<const IntFieldValue&>(*it->second); (void) val; } diff --git a/document/src/vespa/document/base/fieldpath.cpp b/document/src/vespa/document/base/fieldpath.cpp index 5da64272364..fcac59847cb 100644 --- a/document/src/vespa/document/base/fieldpath.cpp +++ b/document/src/vespa/document/base/fieldpath.cpp @@ -5,7 +5,6 @@ #include <vespa/document/datatype/mapdatatype.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/document/fieldvalue/fieldvalue.h> -#include <vespa/vespalib/objects/visit.hpp> using vespalib::IllegalArgumentException; using vespalib::make_string; @@ -127,17 +126,6 @@ FieldPathEntry::stealFieldValueToSet() const return FieldValue::UP(_fillInVal.release()); } -void -FieldPathEntry::visitMembers(vespalib::ObjectVisitor &visitor) const -{ - visit(visitor, "type", _type); - visit(visitor, "name", _name); - visit(visitor, "lookupIndex", _lookupIndex); - visit(visitor, "lookupKey", _lookupKey); - visit(visitor, "variableName", _variableName); - visit(visitor, "fillInVal", _fillInVal); -} - vespalib::string FieldPathEntry::parseKey(vespalib::stringref & key) { @@ -191,7 +179,8 @@ FieldPath::FieldPath(const FieldPath &) = default; FieldPath & FieldPath::operator=(const FieldPath &) = default; FieldPath::~FieldPath() = default; -FieldPath::iterator FieldPath::insert(iterator pos, std::unique_ptr<FieldPathEntry> entry) { +FieldPath::iterator +FieldPath::insert(iterator pos, std::unique_ptr<FieldPathEntry> entry) { return _path.insert(pos, vespalib::CloneablePtr<FieldPathEntry>(entry.release())); } void FieldPath::push_back(std::unique_ptr<FieldPathEntry> entry) { _path.emplace_back(entry.release()); } @@ -199,13 +188,4 @@ void FieldPath::pop_back() { _path.pop_back(); } void FieldPath::clear() { _path.clear(); } void FieldPath::reserve(size_t sz) { _path.reserve(sz); } -void -FieldPath::visitMembers(vespalib::ObjectVisitor& visitor) const -{ - (void) visitor; - for (uint32_t i = 0; i < _path.size(); ++i) { -// visit(visitor, vespalib::make_string("[%u]", i), _path[i]); - } -} - } diff --git a/document/src/vespa/document/base/fieldpath.h b/document/src/vespa/document/base/fieldpath.h index 679fd0885dd..a79e4595a61 100644 --- a/document/src/vespa/document/base/fieldpath.h +++ b/document/src/vespa/document/base/fieldpath.h @@ -2,10 +2,7 @@ #pragma once #include "field.h" -#include <vespa/document/util/identifiableid.h> -#include <vector> - -namespace vespalib { class ObjectVisitor; } +#include <vespa/vespalib/util/memory.h> namespace document { @@ -80,7 +77,6 @@ public: FieldValue * getFieldValueToSetPtr() const { return _fillInVal.get(); } FieldValue & getFieldValueToSet() const { return *_fillInVal; } std::unique_ptr<FieldValue> stealFieldValueToSet() const; - void visitMembers(vespalib::ObjectVisitor &visitor) const; /** * Parses a string of the format {["]escaped string["]} to its unescaped value. * @param key is the incoming value, and contains what is left when done. @@ -115,8 +111,8 @@ public: FieldPath(); FieldPath(const FieldPath &); FieldPath & operator=(const FieldPath &); - FieldPath(FieldPath &&) = default; - FieldPath & operator=(FieldPath &&) = default; + FieldPath(FieldPath &&) noexcept = default; + FieldPath & operator=(FieldPath &&) noexcept = default; ~FieldPath(); template <typename InputIterator> @@ -151,8 +147,6 @@ public: const FieldPathEntry & operator[](Container::size_type i) const { return *_path[i]; } - void visitMembers(vespalib::ObjectVisitor &visitor) const; - template <typename IT> class Range { public: diff --git a/document/src/vespa/document/datatype/datatype.cpp b/document/src/vespa/document/datatype/datatype.cpp index 87464a197ee..3cc7034e336 100644 --- a/document/src/vespa/document/datatype/datatype.cpp +++ b/document/src/vespa/document/datatype/datatype.cpp @@ -51,32 +51,32 @@ class DataType2FieldValueId { public: DataType2FieldValueId(); - unsigned int getFieldValueId(unsigned int id) const { + FieldValue::Type getFieldValueId(unsigned int id) const { return id < sizeof(_type2FieldValueId)/sizeof(_type2FieldValueId[0]) ? _type2FieldValueId[id] - : 0; + : FieldValue::Type::NONE; } private: - unsigned int _type2FieldValueId[DataType::MAX]; + FieldValue::Type _type2FieldValueId[DataType::MAX]; }; DataType2FieldValueId::DataType2FieldValueId() { for (size_t i(0); i < sizeof(_type2FieldValueId)/sizeof(_type2FieldValueId[0]); i++) { - _type2FieldValueId[i] = 0; + _type2FieldValueId[i] = FieldValue::Type::NONE; } - _type2FieldValueId[DataType::T_BYTE] = ByteFieldValue::classId; - _type2FieldValueId[DataType::T_SHORT] = ShortFieldValue::classId; - _type2FieldValueId[DataType::T_INT] = IntFieldValue::classId; - _type2FieldValueId[DataType::T_LONG] = LongFieldValue::classId; - _type2FieldValueId[DataType::T_FLOAT] = FloatFieldValue::classId; - _type2FieldValueId[DataType::T_DOUBLE] = DoubleFieldValue::classId; - _type2FieldValueId[DataType::T_BOOL] = BoolFieldValue::classId; - _type2FieldValueId[DataType::T_STRING] = StringFieldValue::classId; - _type2FieldValueId[DataType::T_RAW] = RawFieldValue::classId; - _type2FieldValueId[DataType::T_URI] = StringFieldValue::classId; - _type2FieldValueId[DataType::T_PREDICATE] = PredicateFieldValue::classId; - _type2FieldValueId[DataType::T_TENSOR] = TensorFieldValue::classId; + _type2FieldValueId[DataType::T_BYTE] = FieldValue::Type::BYTE; + _type2FieldValueId[DataType::T_SHORT] = FieldValue::Type::SHORT; + _type2FieldValueId[DataType::T_INT] = FieldValue::Type::INT; + _type2FieldValueId[DataType::T_LONG] = FieldValue::Type::LONG; + _type2FieldValueId[DataType::T_FLOAT] = FieldValue::Type::FLOAT; + _type2FieldValueId[DataType::T_DOUBLE] = FieldValue::Type::DOUBLE; + _type2FieldValueId[DataType::T_BOOL] = FieldValue::Type::BOOL; + _type2FieldValueId[DataType::T_STRING] = FieldValue::Type::STRING; + _type2FieldValueId[DataType::T_RAW] = FieldValue::Type::RAW; + _type2FieldValueId[DataType::T_URI] = FieldValue::Type::STRING; + _type2FieldValueId[DataType::T_PREDICATE] = FieldValue::Type::PREDICATE; + _type2FieldValueId[DataType::T_TENSOR] = FieldValue::Type::TENSOR; } DataType2FieldValueId _G_type2FieldValueId; @@ -86,9 +86,8 @@ DataType2FieldValueId _G_type2FieldValueId; bool DataType::isValueType(const FieldValue & fv) const { if ((_dataTypeId >= 0) && _dataTypeId < MAX) { - const uint32_t cid(_G_type2FieldValueId.getFieldValueId(_dataTypeId)); - if (cid != 0) { - return cid == fv.getClass().id(); + if (fv.isA(_G_type2FieldValueId.getFieldValueId(_dataTypeId))) { + return true; } } return _dataTypeId == fv.getDataType()->getId(); diff --git a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp index e26f0f15759..130e68a9f54 100644 --- a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp @@ -9,12 +9,6 @@ using std::string; namespace document { -AnnotationReferenceFieldValue::AnnotationReferenceFieldValue( - const DataType &type, int32_t annotation_index) - : _type(&type), - _annotation_index(annotation_index) { -} - int AnnotationReferenceFieldValue::compare(const FieldValue &other) const { if (getDataType()->equals(*other.getDataType())) { const AnnotationReferenceFieldValue &val(static_cast<const AnnotationReferenceFieldValue &>(other)); @@ -35,8 +29,4 @@ void AnnotationReferenceFieldValue::printXml(XmlOutputStream &out) const { out << _annotation_index; } -bool AnnotationReferenceFieldValue::hasChanged() const { - return false; -} - } // namespace document diff --git a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.h b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.h index 6fc85bf384f..732be94c5c8 100644 --- a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.h +++ b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.h @@ -9,15 +9,17 @@ namespace document { class Annotation; class AnnotationReferenceDataType; -class AnnotationReferenceFieldValue : public FieldValue { +class AnnotationReferenceFieldValue final : public FieldValue { const DataType *_type; int32_t _annotation_index; public: AnnotationReferenceFieldValue(const DataType &type) - : _type(&type), _annotation_index(0) {} - AnnotationReferenceFieldValue(const DataType &type, - int32_t annotation_index); + : AnnotationReferenceFieldValue(type, 0) {} + AnnotationReferenceFieldValue(const DataType &type, int32_t annotation_index) + : FieldValue(Type::ANNOTATION_REFERENCE), _type(&type), _annotation_index(annotation_index) + {} + void setAnnotationIndex(int32_t index) { _annotation_index = index; } void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } @@ -30,7 +32,6 @@ public: AnnotationReferenceFieldValue *clone() const override; const DataType *getDataType() const override { return _type; } void printXml(XmlOutputStream &out) const override; - bool hasChanged() const override; }; } // namespace document diff --git a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp index 07f731a9ea7..51bc42d2cee 100644 --- a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp @@ -23,10 +23,8 @@ using fieldvalue::ModificationStatus; using fieldvalue::IteratorHandler; using fieldvalue::VariableMap; -IMPLEMENT_IDENTIFIABLE_ABSTRACT(ArrayFieldValue, CollectionFieldValue); - ArrayFieldValue::ArrayFieldValue(const DataType &type) - : CollectionFieldValue(type), + : CollectionFieldValue(Type::ARRAY, type), _array() { _array.reset(static_cast<IArray *>(createArray(getNestedType()).release())); @@ -170,15 +168,6 @@ ArrayFieldValue::print(std::ostream& out, bool verbose, out << "\n" << indent << ")"; } -bool -ArrayFieldValue::hasChanged() const -{ - for (uint32_t i=0, n=_array->size(); i<n; ++i) { - if (array()[i].hasChanged()) return true; - } - return false; -} - fieldvalue::ModificationStatus ArrayFieldValue::iterateSubset(int startPos, int endPos, vespalib::stringref variable, diff --git a/document/src/vespa/document/fieldvalue/arrayfieldvalue.h b/document/src/vespa/document/fieldvalue/arrayfieldvalue.h index c4f879f7348..ae6aea47c2c 100644 --- a/document/src/vespa/document/fieldvalue/arrayfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/arrayfieldvalue.h @@ -18,7 +18,7 @@ namespace document { -class ArrayFieldValue : public CollectionFieldValue { +class ArrayFieldValue final : public CollectionFieldValue { private: using IArray = vespalib::IArrayT<FieldValue>; std::unique_ptr<IArray> _array; @@ -68,14 +68,12 @@ public: int compare(const FieldValue&) const override; void printXml(XmlOutputStream& out) const override; void print(std::ostream& out, bool verbose, const std::string& indent) const override; - bool hasChanged() const override; void swap(ArrayFieldValue & other) { _array.swap(other._array); } // Iterator functionality const_iterator begin() const { return array().begin(); } const_iterator end() const { return array().end(); } - DECLARE_IDENTIFIABLE_ABSTRACT(ArrayFieldValue); private: iterator begin() { return array().begin(); } iterator end() { return array().end(); } diff --git a/document/src/vespa/document/fieldvalue/boolfieldvalue.cpp b/document/src/vespa/document/fieldvalue/boolfieldvalue.cpp index 1c5261877fd..bbd40623267 100644 --- a/document/src/vespa/document/fieldvalue/boolfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/boolfieldvalue.cpp @@ -9,36 +9,37 @@ using namespace vespalib::xml; namespace document { -IMPLEMENT_IDENTIFIABLE(BoolFieldValue, FieldValue); - BoolFieldValue::BoolFieldValue(bool value) - : _value(value), _altered(false) { + : FieldValue(Type::BOOL), _value(value) { } BoolFieldValue::~BoolFieldValue() = default; -FieldValue &BoolFieldValue::assign(const FieldValue &rhs) { - if (rhs.inherits(BoolFieldValue::classId)) { +FieldValue & +BoolFieldValue::assign(const FieldValue &rhs) { + if (rhs.isA(Type::BOOL)) { operator=(static_cast<const BoolFieldValue &>(rhs)); return *this; } else { - _altered = true; return FieldValue::assign(rhs); } } -int BoolFieldValue::compare(const FieldValue&rhs) const { +int +BoolFieldValue::compare(const FieldValue&rhs) const { int diff = FieldValue::compare(rhs); if (diff != 0) return diff; const BoolFieldValue &o = static_cast<const BoolFieldValue &>(rhs); return (_value == o._value) ? 0 : _value ? 1 : -1; } -void BoolFieldValue::printXml(XmlOutputStream& out) const { +void +BoolFieldValue::printXml(XmlOutputStream& out) const { out << XmlContent(getAsString()); } -void BoolFieldValue::print(std::ostream& out, bool, const std::string&) const { +void +BoolFieldValue::print(std::ostream& out, bool, const std::string&) const { out << (_value ? "true" : "false") << "\n"; } @@ -47,11 +48,6 @@ BoolFieldValue::getDataType() const { return DataType::BOOL; } -bool -BoolFieldValue::hasChanged() const { - return _altered; -} - FieldValue * BoolFieldValue::clone() const { return new BoolFieldValue(*this); diff --git a/document/src/vespa/document/fieldvalue/boolfieldvalue.h b/document/src/vespa/document/fieldvalue/boolfieldvalue.h index 01cfcf2cd48..0265205665d 100644 --- a/document/src/vespa/document/fieldvalue/boolfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/boolfieldvalue.h @@ -9,9 +9,8 @@ namespace document { /** * Represent the value in a field of type 'bool' which can be either true or false. **/ -class BoolFieldValue : public FieldValue { +class BoolFieldValue final : public FieldValue { bool _value; - bool _altered; public: BoolFieldValue(bool value=false); @@ -27,7 +26,6 @@ public: void print(std::ostream &out, bool verbose, const std::string &indent) const override; const DataType *getDataType() const override; - bool hasChanged() const override; bool getValue() const { return _value; } void setValue(bool v) { _value = v; } @@ -42,7 +40,6 @@ public: vespalib::string getAsString() const override; BoolFieldValue& operator=(vespalib::stringref) override; - DECLARE_IDENTIFIABLE(BoolFieldValue); static std::unique_ptr<BoolFieldValue> make(bool value=false) { return std::make_unique<BoolFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/bytefieldvalue.cpp b/document/src/vespa/document/fieldvalue/bytefieldvalue.cpp index 5d514352302..fff07d9de4e 100644 --- a/document/src/vespa/document/fieldvalue/bytefieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/bytefieldvalue.cpp @@ -5,6 +5,4 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(ByteFieldValue, NumericFieldValueBase); - } // document diff --git a/document/src/vespa/document/fieldvalue/bytefieldvalue.h b/document/src/vespa/document/fieldvalue/bytefieldvalue.h index 2cccf483c84..1b810828c53 100644 --- a/document/src/vespa/document/fieldvalue/bytefieldvalue.h +++ b/document/src/vespa/document/fieldvalue/bytefieldvalue.h @@ -12,12 +12,12 @@ namespace document { -class ByteFieldValue : public NumericFieldValue<int8_t> { +class ByteFieldValue final : public NumericFieldValue<int8_t> { public: typedef int8_t Number; ByteFieldValue(Number value = 0) - : NumericFieldValue<Number>(value) {} + : NumericFieldValue<Number>(Type::BYTE, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -25,7 +25,6 @@ public: ByteFieldValue* clone() const override { return new ByteFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(ByteFieldValue); static std::unique_ptr<ByteFieldValue> make(Number value=0) { return std::make_unique<ByteFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/collectionfieldvalue.cpp b/document/src/vespa/document/fieldvalue/collectionfieldvalue.cpp index 4c960502b71..b9400a1e663 100644 --- a/document/src/vespa/document/fieldvalue/collectionfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/collectionfieldvalue.cpp @@ -5,7 +5,6 @@ namespace document { -IMPLEMENT_IDENTIFIABLE_ABSTRACT(CollectionFieldValue, FieldValue); CollectionFieldValue::CollectionFieldValue(const CollectionFieldValue& other) : FieldValue(other), diff --git a/document/src/vespa/document/fieldvalue/collectionfieldvalue.h b/document/src/vespa/document/fieldvalue/collectionfieldvalue.h index 9efd3b91bc6..d4a1367bee2 100644 --- a/document/src/vespa/document/fieldvalue/collectionfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/collectionfieldvalue.h @@ -27,9 +27,9 @@ protected: void verifyType(const CollectionFieldValue& other) const; public: - CollectionFieldValue(const DataType &type) - : FieldValue(), - _type(&type) + CollectionFieldValue(Type type, const DataType &dataType) + : FieldValue(type), + _type(&dataType) {} CollectionFieldValue(const CollectionFieldValue& other); @@ -61,8 +61,6 @@ public: virtual bool isEmpty() const = 0; virtual size_t size() const = 0; virtual void clear() = 0; - - DECLARE_IDENTIFIABLE_ABSTRACT(CollectionFieldValue); }; } diff --git a/document/src/vespa/document/fieldvalue/document.cpp b/document/src/vespa/document/fieldvalue/document.cpp index 57787738502..0cd1faa5d62 100644 --- a/document/src/vespa/document/fieldvalue/document.cpp +++ b/document/src/vespa/document/fieldvalue/document.cpp @@ -65,10 +65,8 @@ Document::setType(const DataType & type) { _fields.setType(getType().getFieldsType()); } -IMPLEMENT_IDENTIFIABLE_ABSTRACT(Document, StructuredFieldValue); - Document::Document() - : StructuredFieldValue(*DataType::DOCUMENT), + : StructuredFieldValue(Type::DOCUMENT, *DataType::DOCUMENT), _id(), _fields(getType().getFieldsType()), _backingBuffer(), @@ -86,7 +84,7 @@ Document::Document(const Document& rhs) {} Document::Document(const DataType &type, DocumentId documentId) - : StructuredFieldValue(verifyDocumentType(&type)), + : StructuredFieldValue(Type::DOCUMENT, verifyDocumentType(&type)), _id(std::move(documentId)), _fields(getType().getFieldsType()), _backingBuffer(), @@ -104,7 +102,7 @@ void Document::setRepo(const DocumentTypeRepo& repo) } Document::Document(const DocumentTypeRepo& repo, vespalib::nbostream & is) - : StructuredFieldValue(*DataType::DOCUMENT), + : StructuredFieldValue(Type::DOCUMENT, *DataType::DOCUMENT), _id(), _fields(static_cast<const DocumentType &>(getType()).getFieldsType()), _backingBuffer(), @@ -114,7 +112,7 @@ Document::Document(const DocumentTypeRepo& repo, vespalib::nbostream & is) } Document::Document(const DocumentTypeRepo& repo, vespalib::DataBuffer && backingBuffer) - : StructuredFieldValue(*DataType::DOCUMENT), + : StructuredFieldValue(Type::DOCUMENT, *DataType::DOCUMENT), _id(), _fields(static_cast<const DocumentType &>(getType()).getFieldsType()), _backingBuffer(), @@ -173,12 +171,6 @@ Document::setFieldValue(const Field& field, FieldValue::UP data) _fields.setFieldValue(field, std::move(data)); } -bool -Document::hasChanged() const -{ - return _fields.hasChanged(); -} - FieldValue& Document::assign(const FieldValue& value) { diff --git a/document/src/vespa/document/fieldvalue/document.h b/document/src/vespa/document/fieldvalue/document.h index da6bcca777c..610b2fcbd1b 100644 --- a/document/src/vespa/document/fieldvalue/document.h +++ b/document/src/vespa/document/fieldvalue/document.h @@ -24,7 +24,7 @@ namespace document { class TransactionGuard; -class Document : public StructuredFieldValue +class Document final : public StructuredFieldValue { private: DocumentId _id; @@ -86,8 +86,6 @@ public: void clear() override; - bool hasChanged() const override; - // FieldValue implementation. FieldValue& assign(const FieldValue&) override; int compare(const FieldValue& other) const override; @@ -109,9 +107,6 @@ public: bool empty() const override { return _fields.empty(); } uint32_t calculateChecksum() const; - - DECLARE_IDENTIFIABLE_ABSTRACT(Document); - void setFieldValue(const Field& field, FieldValue::UP data) override; private: friend TransactionGuard; diff --git a/document/src/vespa/document/fieldvalue/doublefieldvalue.cpp b/document/src/vespa/document/fieldvalue/doublefieldvalue.cpp index 943255e5ffc..3ab255be8db 100644 --- a/document/src/vespa/document/fieldvalue/doublefieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/doublefieldvalue.cpp @@ -5,6 +5,5 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(DoubleFieldValue, NumericFieldValueBase); } // document diff --git a/document/src/vespa/document/fieldvalue/doublefieldvalue.h b/document/src/vespa/document/fieldvalue/doublefieldvalue.h index b9b20bbd24a..56ba6e334e9 100644 --- a/document/src/vespa/document/fieldvalue/doublefieldvalue.h +++ b/document/src/vespa/document/fieldvalue/doublefieldvalue.h @@ -12,11 +12,11 @@ namespace document { -class DoubleFieldValue : public NumericFieldValue<double> { +class DoubleFieldValue final : public NumericFieldValue<double> { public: typedef double Number; - DoubleFieldValue(Number value = 0) : NumericFieldValue<Number>(value) {} + DoubleFieldValue(Number value = 0) : NumericFieldValue<Number>(Type::DOUBLE, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -25,7 +25,6 @@ public: DoubleFieldValue* clone() const override { return new DoubleFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(DoubleFieldValue); static std::unique_ptr<DoubleFieldValue> make(Number value=0) { return std::make_unique<DoubleFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/fieldvalue.cpp b/document/src/vespa/document/fieldvalue/fieldvalue.cpp index cc55775d54c..79cc2daafce 100644 --- a/document/src/vespa/document/fieldvalue/fieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/fieldvalue.cpp @@ -26,8 +26,50 @@ namespace document { using namespace fieldvalue; -IMPLEMENT_IDENTIFIABLE_ABSTRACT(FieldValue, vespalib::Identifiable); - +const char * +FieldValue::className() const noexcept { + switch (type()) { + case Type::BOOL: + return "BoolFieldValue"; + case Type::BYTE: + return "ByteFieldValue"; + case Type::SHORT: + return "ShortFieldValue"; + case Type::INT: + return "IntFieldValue"; + case Type::LONG: + return "LongFieldValue"; + case Type::FLOAT: + return "FloatFieldValue"; + case Type::DOUBLE: + return "DoubleFieldValue"; + case Type::STRING: + return "StringFieldValue"; + case Type::RAW: + return "RawFieldValue"; + case Type::PREDICATE: + return "PredicateFieldValue"; + case Type::TENSOR: + return "TensorFieldValue"; + case Type::ANNOTATION_REFERENCE: + return "AnnotationReferenceFieldValue"; + case Type::REFERENCE: + return "ReferenceFieldValue"; + case Type::ARRAY: + return "ArrayFieldValue"; + case Type::WSET: + return "WSetFieldValue"; + case Type::MAP: + return "MapFieldValue"; + case Type::STRUCT: + return "StructFieldValue"; + case Type::DOCUMENT: + return "DocumentFieldValue"; + case Type::NONE: + default: + abort(); + } +} void FieldValue::serialize(nbostream &stream) const { VespaDocumentSerializer serializer(stream); serializer.write(*this); diff --git a/document/src/vespa/document/fieldvalue/fieldvalue.h b/document/src/vespa/document/fieldvalue/fieldvalue.h index 5eadb3307b5..a45e42539ee 100644 --- a/document/src/vespa/document/fieldvalue/fieldvalue.h +++ b/document/src/vespa/document/fieldvalue/fieldvalue.h @@ -13,38 +13,35 @@ #include "fieldvaluevisitor.h" #include "modificationstatus.h" -#include <vespa/document/util/xmlserializable.h> +#include <vespa/document/util/identifiableid.h> #include <vespa/document/base/fieldpath.h> #include <vespa/vespalib/objects/identifiable.h> #include <vespa/vespalib/util/polymorphicarraybase.h> namespace vespalib { class nbostream; } +namespace vespalib::xml { class XmlOutputStream; } -namespace document { +namespace document::fieldvalue { class IteratorHandler; } -namespace fieldvalue { class IteratorHandler; } +namespace document { class DataType; -class FieldValue : public vespalib::Identifiable +class FieldValue { -protected: - FieldValue(const FieldValue&) = default; - FieldValue& operator=(const FieldValue&) = default; - FieldValue(FieldValue &&) = default; - FieldValue& operator=(FieldValue &&) = default; - static std::unique_ptr<vespalib::IArrayBase> createArray(const DataType & baseType); - public: + enum class Type : uint8_t { + NONE, BOOL, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, + STRING, RAW, PREDICATE, TENSOR, ANNOTATION_REFERENCE, + REFERENCE, ARRAY, WSET, MAP, STRUCT, DOCUMENT + }; using PathRange = FieldPath::Range<FieldPath::const_iterator>; using UP = std::unique_ptr<FieldValue>; using SP = std::shared_ptr<FieldValue>; using CP = vespalib::CloneablePtr<FieldValue>; + using XmlOutputStream = vespalib::xml::XmlOutputStream; - DECLARE_IDENTIFIABLE_ABSTRACT(FieldValue); - - FieldValue() = default; - + virtual ~FieldValue() = default; /** * Visit this fieldvalue for double dispatch. */ @@ -82,13 +79,6 @@ public: */ virtual int fastCompare(const FieldValue& other) const; - /** - * Returns true if this object have been altered since last - * serialization/deserialization. If hasChanged() is false, then cached - * information from last serialization effort is still valid. - */ - virtual bool hasChanged() const = 0; - /** Cloneable implementation */ virtual FieldValue* clone() const = 0; @@ -174,6 +164,27 @@ public: // Utility functions to set commonly used value types. virtual FieldValue& operator=(vespalib::stringref); + + Type type() const noexcept { return _type; } + bool isA(Type type) const noexcept { return type == _type; } + bool isCollection() const noexcept { return (_type == Type::WSET) || (_type == Type::ARRAY); } + bool isStructured() const noexcept { return (_type == Type::DOCUMENT) || (_type == Type::STRUCT); } + bool isLiteral() const noexcept { return (_type == Type::STRING) || (_type == Type::RAW); } + bool isNumeric() const noexcept { + return (_type == Type::BYTE) || (_type == Type::SHORT) || + (_type == Type::INT) || (_type == Type::LONG) || (_type == Type::FLOAT) || (_type == Type::DOUBLE); + } + bool isFixedSizeSingleValue() const noexcept { + return (_type == Type::BOOL) || isNumeric(); + } + const char * className() const noexcept; +protected: + FieldValue(Type type) noexcept : _type(type) { } + FieldValue(const FieldValue&) = default; + FieldValue& operator=(const FieldValue&) = default; + FieldValue(FieldValue &&) noexcept = default; + FieldValue& operator=(FieldValue &&) noexcept = default; + static std::unique_ptr<vespalib::IArrayBase> createArray(const DataType & baseType); private: fieldvalue::ModificationStatus iterateNested(FieldPath::const_iterator start, FieldPath::const_iterator end, fieldvalue::IteratorHandler & handler) const { @@ -181,10 +192,12 @@ private: } virtual FieldValue::UP onGetNestedFieldValue(PathRange nested) const; virtual fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const; + + Type _type; }; std::ostream& operator<<(std::ostream& out, const FieldValue & p); -XmlOutputStream & operator<<(XmlOutputStream & out, const FieldValue & p); +vespalib::xml::XmlOutputStream & operator<<(vespalib::xml::XmlOutputStream & out, const FieldValue & p); } // document diff --git a/document/src/vespa/document/fieldvalue/floatfieldvalue.cpp b/document/src/vespa/document/fieldvalue/floatfieldvalue.cpp index e44f36295c4..b3698841667 100644 --- a/document/src/vespa/document/fieldvalue/floatfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/floatfieldvalue.cpp @@ -5,6 +5,4 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(FloatFieldValue, NumericFieldValueBase); - } // document diff --git a/document/src/vespa/document/fieldvalue/floatfieldvalue.h b/document/src/vespa/document/fieldvalue/floatfieldvalue.h index f662c400633..783459dec64 100644 --- a/document/src/vespa/document/fieldvalue/floatfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/floatfieldvalue.h @@ -12,11 +12,11 @@ namespace document { -class FloatFieldValue : public NumericFieldValue<float> { +class FloatFieldValue final : public NumericFieldValue<float> { public: typedef float Number; - FloatFieldValue(Number value = 0) : NumericFieldValue<Number>(value) {} + FloatFieldValue(Number value = 0) : NumericFieldValue<Number>(Type::FLOAT, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -25,7 +25,6 @@ public: FloatFieldValue* clone() const override { return new FloatFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(FloatFieldValue); static std::unique_ptr<FloatFieldValue> make(Number value = 0) { return std::make_unique<FloatFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/intfieldvalue.cpp b/document/src/vespa/document/fieldvalue/intfieldvalue.cpp index 06edafcf374..42884c9fc8b 100644 --- a/document/src/vespa/document/fieldvalue/intfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/intfieldvalue.cpp @@ -5,6 +5,5 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(IntFieldValue, NumericFieldValueBase); } // document diff --git a/document/src/vespa/document/fieldvalue/intfieldvalue.h b/document/src/vespa/document/fieldvalue/intfieldvalue.h index d365e34779e..521aced292c 100644 --- a/document/src/vespa/document/fieldvalue/intfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/intfieldvalue.h @@ -12,11 +12,11 @@ namespace document { -class IntFieldValue : public NumericFieldValue<int32_t> { +class IntFieldValue final : public NumericFieldValue<int32_t> { public: typedef int32_t Number; - IntFieldValue(Number value = 0) : NumericFieldValue<Number>(value) {} + IntFieldValue(Number value = 0) : NumericFieldValue<Number>(Type::INT, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -25,7 +25,6 @@ public: IntFieldValue* clone() const override { return new IntFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(IntFieldValue); static std::unique_ptr<IntFieldValue> make(Number value=0) { return std::make_unique<IntFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp b/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp index 7ba537d9cc2..02ad759fb8c 100644 --- a/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp @@ -8,13 +8,10 @@ using namespace vespalib::xml; namespace document { -IMPLEMENT_IDENTIFIABLE_ABSTRACT(LiteralFieldValueB, FieldValue); - -LiteralFieldValueB::LiteralFieldValueB() : - FieldValue(), +LiteralFieldValueB::LiteralFieldValueB(Type type) : + FieldValue(type), _value(), - _backing(), - _altered(true) + _backing() { _value = _backing; } @@ -24,17 +21,15 @@ LiteralFieldValueB::~LiteralFieldValueB() = default; LiteralFieldValueB::LiteralFieldValueB(const LiteralFieldValueB& other) : FieldValue(other), _value(), - _backing(other.getValueRef()), - _altered(other._altered) + _backing(other.getValueRef()) { _value = _backing; } -LiteralFieldValueB::LiteralFieldValueB(const stringref & value) - : FieldValue(), +LiteralFieldValueB::LiteralFieldValueB(Type type, const stringref & value) + : FieldValue(type), _value(), - _backing(value), - _altered(true) + _backing(value) { _value = _backing; } @@ -45,7 +40,6 @@ LiteralFieldValueB::operator=(const LiteralFieldValueB& other) FieldValue::operator=(other); _backing = other.getValueRef(); _value = _backing; - _altered = other._altered; return *this; } @@ -115,7 +109,7 @@ LiteralFieldValueB::syncBacking() const _value = _backing; } -template class LiteralFieldValue<RawFieldValue, DataType::T_RAW, false>; -template class LiteralFieldValue<StringFieldValue, DataType::T_STRING, true>; +template class LiteralFieldValue<RawFieldValue, DataType::T_RAW>; +template class LiteralFieldValue<StringFieldValue, DataType::T_STRING>; } // namespace document diff --git a/document/src/vespa/document/fieldvalue/literalfieldvalue.h b/document/src/vespa/document/fieldvalue/literalfieldvalue.h index 6e3f0223b20..89f2f6afd74 100644 --- a/document/src/vespa/document/fieldvalue/literalfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/literalfieldvalue.h @@ -24,15 +24,14 @@ class LiteralFieldValueB : public FieldValue { public: typedef vespalib::string string; typedef vespalib::stringref stringref; - DECLARE_IDENTIFIABLE_ABSTRACT(LiteralFieldValueB); typedef std::unique_ptr<LiteralFieldValueB> UP; typedef string value_type; - LiteralFieldValueB(); + explicit LiteralFieldValueB(Type type); ~LiteralFieldValueB(); LiteralFieldValueB(const LiteralFieldValueB &); - LiteralFieldValueB(const stringref & value); + LiteralFieldValueB(Type type, const stringref & value); const value_type & getValue() const { sync(); return _backing; } /** @@ -46,13 +45,11 @@ public: void setValueRef(stringref value) { _value = value; - _altered = true; } void setValue(stringref value) { _backing = value; _value = _backing; - _altered = true; } size_t hash() const override final { return vespalib::hashValue(_value.data(), _value.size()); } void setValue(const char* val, size_t size) { setValue(stringref(val, size)); } @@ -66,7 +63,6 @@ public: void printXml(XmlOutputStream& out) const override; void print(std::ostream& out, bool verbose, const std::string& indent) const override; FieldValue& assign(const FieldValue&) override; - bool hasChanged() const override{ return _altered; } FieldValue& operator=(vespalib::stringref) override; protected: @@ -78,25 +74,18 @@ protected: } mutable stringref _value; mutable string _backing; // Lazily set when needed - mutable bool _altered; // Set if altered after deserialization -private: - virtual bool getAddZeroTerm() const = 0; }; -template<typename SubClass, int type, bool addZeroTerm> +template<typename SubClass, int dataType> class LiteralFieldValue : public LiteralFieldValueB { -private: - bool getAddZeroTerm() const override{ return addZeroTerm; } public: - typedef std::unique_ptr<SubClass> UP; - - LiteralFieldValue() : LiteralFieldValueB() { } - LiteralFieldValue(const stringref& value) : LiteralFieldValueB(value) { } + explicit LiteralFieldValue(Type type) : LiteralFieldValueB(type) { } + LiteralFieldValue(Type type, const stringref& value) : LiteralFieldValueB(type, value) { } const DataType *getDataType() const override; }; -extern template class LiteralFieldValue<RawFieldValue, DataType::T_RAW, false>; -extern template class LiteralFieldValue<StringFieldValue, DataType::T_STRING, true>; +extern template class LiteralFieldValue<RawFieldValue, DataType::T_RAW>; +extern template class LiteralFieldValue<StringFieldValue, DataType::T_STRING>; } // document diff --git a/document/src/vespa/document/fieldvalue/literalfieldvalue.hpp b/document/src/vespa/document/fieldvalue/literalfieldvalue.hpp index c5b30bc5ff1..91364de29fa 100644 --- a/document/src/vespa/document/fieldvalue/literalfieldvalue.hpp +++ b/document/src/vespa/document/fieldvalue/literalfieldvalue.hpp @@ -6,17 +6,17 @@ namespace document { -template<typename SubClass, int type, bool addZeroTerm> +template<typename SubClass, int dataType> const DataType * -LiteralFieldValue<SubClass, type, addZeroTerm>::getDataType() const +LiteralFieldValue<SubClass, dataType>::getDataType() const { - switch (type) { + switch (dataType) { case DataType::T_URI: return DataType::URI; case DataType::T_STRING: return DataType::STRING; case DataType::T_RAW: return DataType::RAW; default: throw vespalib::IllegalStateException(vespalib::make_string( - "Illegal literal type id %i", type), VESPA_STRLOC); + "Illegal literal type id %i", dataType), VESPA_STRLOC); } } diff --git a/document/src/vespa/document/fieldvalue/longfieldvalue.cpp b/document/src/vespa/document/fieldvalue/longfieldvalue.cpp index f2f6cdb52b5..04f39f64beb 100644 --- a/document/src/vespa/document/fieldvalue/longfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/longfieldvalue.cpp @@ -4,6 +4,4 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(LongFieldValue, NumericFieldValueBase); - } // document diff --git a/document/src/vespa/document/fieldvalue/longfieldvalue.h b/document/src/vespa/document/fieldvalue/longfieldvalue.h index 64ab4332cef..4b73ef0c2ea 100644 --- a/document/src/vespa/document/fieldvalue/longfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/longfieldvalue.h @@ -12,11 +12,11 @@ namespace document { -class LongFieldValue : public NumericFieldValue<int64_t> { +class LongFieldValue final : public NumericFieldValue<int64_t> { public: typedef int64_t Number; - LongFieldValue(Number value = 0) : NumericFieldValue<Number>(value) {} + LongFieldValue(Number value = 0) : NumericFieldValue<Number>(Type::LONG, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -25,7 +25,6 @@ public: LongFieldValue* clone() const override { return new LongFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(LongFieldValue); static std::unique_ptr<LongFieldValue> make(Number value=0) { return std::make_unique<LongFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp index 872185e7523..33ce4357f03 100644 --- a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp @@ -25,8 +25,6 @@ namespace document { using namespace fieldvalue; -IMPLEMENT_IDENTIFIABLE_ABSTRACT(MapFieldValue, FieldValue); - namespace { const MapDataType *verifyMapType(const DataType& type) { const MapDataType *ptr(dynamic_cast<const MapDataType *>(&type)); @@ -75,14 +73,13 @@ public: } MapFieldValue::MapFieldValue(const DataType &mapType) - : FieldValue(), + : FieldValue(Type::MAP), _type(verifyMapType(mapType)), _count(0), _keys(static_cast<IArray *>(createArray(getMapType().getKeyType()).release())), _values(static_cast<IArray *>(createArray(getMapType().getValueType()).release())), _present(), - _lookupMap(), - _altered(true) + _lookupMap() { } @@ -95,8 +92,7 @@ MapFieldValue::MapFieldValue(const MapFieldValue & rhs) : _keys(rhs._keys ? rhs._keys->clone() : nullptr), _values(rhs._values ? rhs._values->clone() : nullptr), _present(rhs._present), - _lookupMap(), - _altered(rhs._altered) + _lookupMap() { } @@ -118,7 +114,6 @@ MapFieldValue::swap(MapFieldValue & rhs) { std::swap(_values, rhs._values); std::swap(_present, rhs._present); std::swap(_lookupMap, rhs._lookupMap); - std::swap(_altered, rhs._altered); } void MapFieldValue::verifyKey(const FieldValue & fv) const @@ -146,7 +141,6 @@ MapFieldValue::insertVerify(const FieldValue& key, const FieldValue& value) bool result(false); if (found != end()) { if (!(value == *found->second)) { - _altered = true; found->second->assign(value); } } else { @@ -166,8 +160,6 @@ MapFieldValue::push_back(const FieldValue& key, const FieldValue& value) if (_lookupMap) { _lookupMap->insert(_present.size() - 1); } - - _altered = true; } @@ -181,7 +173,6 @@ MapFieldValue::push_back(FieldValue::UP key, FieldValue::UP value) if (_lookupMap) { _lookupMap->insert(_present.size() - 1); } - _altered = true; } bool @@ -255,7 +246,6 @@ MapFieldValue::erase(const FieldValue& key) _count--; _present[found.offset()] = false; _lookupMap->erase(found.offset()); - _altered = true; } return result; } @@ -331,13 +321,6 @@ MapFieldValue::printXml(XmlOutputStream& xos) const } } -bool -MapFieldValue::hasChanged() const -{ - // Keys are not allowed to change in a map, so the keys should not be - // referred to externally, and should thus not need to be checked. - return _altered; -} const DataType * MapFieldValue::getDataType() const { return _type; @@ -369,7 +352,7 @@ MapFieldValue::buildLookupMap() const { MapFieldValue::const_iterator MapFieldValue::find(const FieldValue& key) const { - if ((size() > 0) && (key.getClass().id() == (*_keys)[0].getClass().id())) { + if ((size() > 0) && (key.type() == (*_keys)[0].type())) { ssize_t index = findIndex(key); if (index >= 0) { return const_iterator(*this, index); @@ -381,7 +364,7 @@ MapFieldValue::find(const FieldValue& key) const MapFieldValue::iterator MapFieldValue::find(const FieldValue& key) { - if ((size() > 0) && (key.getClass().id() == (*_keys)[0].getClass().id())) { + if ((size() > 0) && (key.type() == (*_keys)[0].type())) { ssize_t index = findIndex(key); if (index >= 0) { return iterator(*this, index); @@ -393,7 +376,7 @@ MapFieldValue::find(const FieldValue& key) ssize_t MapFieldValue::findIndex(const FieldValue& key) const { - if ((size() > 0) && (key.getClass().id() == (*_keys)[0].getClass().id())) { + if ((size() > 0) && (key.type() == (*_keys)[0].type())) { ensureLookupMap(); auto found = _lookupMap->find(key); if (found != _lookupMap->end()) { @@ -428,7 +411,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested, IteratorHandler::CollectionScope autoScope(handler, complexFieldValue); std::vector<const FieldValue*> keysToRemove; bool wasModified = false; - const bool isWSet(complexFieldValue.inherits(WeightedSetFieldValue::classId)); + const bool isWSet(complexFieldValue.isA(FieldValue::Type::WSET)); uint32_t index(0); if ( ! nested.atEnd() ) { diff --git a/document/src/vespa/document/fieldvalue/mapfieldvalue.h b/document/src/vespa/document/fieldvalue/mapfieldvalue.h index 5e8de6f3ed8..551543684f0 100644 --- a/document/src/vespa/document/fieldvalue/mapfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/mapfieldvalue.h @@ -18,7 +18,7 @@ namespace document { namespace mapfieldvalue { class HashMap; } -class MapFieldValue : public FieldValue +class MapFieldValue final : public FieldValue { public: using IArray=vespalib::IArrayT<FieldValue>; @@ -134,7 +134,6 @@ public: MapFieldValue* clone() const override { return new MapFieldValue(*this); } int compare(const FieldValue&) const override; void print(std::ostream& out, bool verbose, const std::string& indent) const override; - bool hasChanged() const override; const DataType *getDataType() const override; void printXml(XmlOutputStream& out) const override; @@ -162,8 +161,6 @@ public: } FieldValue::UP createValue() const; - - DECLARE_IDENTIFIABLE_ABSTRACT(MapFieldValue); }; } // namespace document diff --git a/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp b/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp index 7d02054f668..6247e815d73 100644 --- a/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp @@ -6,8 +6,6 @@ namespace document { -IMPLEMENT_IDENTIFIABLE_ABSTRACT(NumericFieldValueBase, FieldValue); - void NumericFieldValueBase::printXml(XmlOutputStream& out) const { diff --git a/document/src/vespa/document/fieldvalue/numericfieldvalue.h b/document/src/vespa/document/fieldvalue/numericfieldvalue.h index 28981fc5286..a19456f0e4a 100644 --- a/document/src/vespa/document/fieldvalue/numericfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/numericfieldvalue.h @@ -18,21 +18,19 @@ namespace document { class NumericFieldValueBase : public FieldValue { public: - DECLARE_IDENTIFIABLE_ABSTRACT(NumericFieldValueBase); void printXml(XmlOutputStream& out) const override; +protected: + NumericFieldValueBase(Type type) : FieldValue(type) {} }; template<typename Number> class NumericFieldValue : public NumericFieldValueBase { protected: + explicit NumericFieldValue(Type type, Number value=0) : NumericFieldValueBase(type), _value(value) { } Number _value; - bool _altered; - public: typedef Number value_type; - explicit NumericFieldValue(Number value=0) : NumericFieldValueBase(), _value(value), _altered(false) { } - value_type getValue() const { return _value; } void setValue(Number newValue) { _value = newValue; } @@ -51,7 +49,6 @@ public: vespalib::string getAsString() const override; void print(std::ostream& out, bool verbose, const std::string& indent) const override; - bool hasChanged() const override final { return _altered; } }; extern template class NumericFieldValue<float>; diff --git a/document/src/vespa/document/fieldvalue/numericfieldvalue.hpp b/document/src/vespa/document/fieldvalue/numericfieldvalue.hpp index f1bbce5450d..0c214a97aec 100644 --- a/document/src/vespa/document/fieldvalue/numericfieldvalue.hpp +++ b/document/src/vespa/document/fieldvalue/numericfieldvalue.hpp @@ -17,22 +17,21 @@ template<typename Number> FieldValue& NumericFieldValue<Number>::assign(const FieldValue& value) { - if (value.getClass().id() == IDENTIFIABLE_CLASSID(ByteFieldValue)) { + if (value.isA(FieldValue::Type::BYTE)) { _value = static_cast<Number>(value.getAsByte()); - } else if (value.getClass().id() == IDENTIFIABLE_CLASSID(ShortFieldValue)) { + } else if (value.isA(FieldValue::Type::SHORT)) { _value = static_cast<Number>(value.getAsInt()); - } else if (value.getClass().id() == IDENTIFIABLE_CLASSID(IntFieldValue)) { + } else if (value.isA(FieldValue::Type::INT)) { _value = static_cast<Number>(value.getAsInt()); - } else if (value.getClass().id() == IDENTIFIABLE_CLASSID(LongFieldValue)) { + } else if (value.isA(FieldValue::Type::LONG)) { _value = static_cast<Number>(value.getAsLong()); - } else if (value.getClass().id() == IDENTIFIABLE_CLASSID(FloatFieldValue)) { + } else if (value.isA(FieldValue::Type::FLOAT)) { _value = static_cast<Number>(value.getAsFloat()); - } else if (value.getClass().id() == IDENTIFIABLE_CLASSID(DoubleFieldValue)) { + } else if (value.isA(FieldValue::Type::DOUBLE)) { _value = static_cast<Number>(value.getAsDouble()); } else { return FieldValue::assign(value); } - _altered = true; return *this; } @@ -91,7 +90,6 @@ NumericFieldValue<Number>::operator=(vespalib::stringref value) // Allow numbers to be specified in range max signed to max // unsigned. These become negative numbers. _value = static_cast<Number>(val); - _altered = true; return *this; } } @@ -118,7 +116,6 @@ NumericFieldValue<Number>::operator=(vespalib::stringref value) } } } - _altered = true; return *this; } diff --git a/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp b/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp index 3a62eb5060c..b474db2ab6e 100644 --- a/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp @@ -14,22 +14,19 @@ using namespace vespalib::xml; namespace document { -IMPLEMENT_IDENTIFIABLE(PredicateFieldValue, FieldValue); - PredicateFieldValue::PredicateFieldValue() - : _slime(std::make_unique<Slime>()), _altered(false) { -} + : FieldValue(Type::PREDICATE), + _slime(std::make_unique<Slime>()) +{ } PredicateFieldValue::PredicateFieldValue(vespalib::Slime::UP s) - : FieldValue(), - _slime(std::move(s)), - _altered(false) + : FieldValue(Type::PREDICATE), + _slime(std::move(s)) { } PredicateFieldValue::PredicateFieldValue(const PredicateFieldValue &rhs) : FieldValue(rhs), - _slime(new Slime), - _altered(rhs._altered) + _slime(new Slime) { inject(rhs._slime->get(), SlimeInserter(*_slime)); } @@ -38,11 +35,10 @@ PredicateFieldValue::~PredicateFieldValue() = default; FieldValue & PredicateFieldValue::assign(const FieldValue &rhs) { - if (rhs.inherits(PredicateFieldValue::classId)) { + if (rhs.isA(Type::PREDICATE)) { operator=(static_cast<const PredicateFieldValue &>(rhs)); } else { _slime.reset(); - _altered = true; } return *this; } @@ -52,7 +48,6 @@ PredicateFieldValue::operator=(const PredicateFieldValue &rhs) { _slime = std::make_unique<Slime>(); inject(rhs._slime->get(), SlimeInserter(*_slime)); - _altered = true; return *this; } @@ -79,11 +74,6 @@ PredicateFieldValue::getDataType() const { return DataType::PREDICATE; } -bool -PredicateFieldValue::hasChanged() const { - return _altered; -} - FieldValue * PredicateFieldValue::clone() const { return new PredicateFieldValue(*this); diff --git a/document/src/vespa/document/fieldvalue/predicatefieldvalue.h b/document/src/vespa/document/fieldvalue/predicatefieldvalue.h index 5f7db35f953..c99a82a59e2 100644 --- a/document/src/vespa/document/fieldvalue/predicatefieldvalue.h +++ b/document/src/vespa/document/fieldvalue/predicatefieldvalue.h @@ -9,9 +9,8 @@ namespace vespalib { } namespace document { -class PredicateFieldValue : public FieldValue { +class PredicateFieldValue final : public FieldValue { std::unique_ptr<vespalib::Slime> _slime; - bool _altered; PredicateFieldValue & operator=(const PredicateFieldValue &rhs); public: @@ -33,13 +32,10 @@ public: void print(std::ostream &out, bool verbose, const std::string &indent) const override; const DataType *getDataType() const override; - bool hasChanged() const override; const vespalib::Slime &getSlime() const { return *_slime; } FieldValue &assign(const FieldValue &rhs) override; - - DECLARE_IDENTIFIABLE(PredicateFieldValue); }; } diff --git a/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp b/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp index 95f066b86ed..ab17a879dfa 100644 --- a/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp @@ -9,8 +9,6 @@ using namespace vespalib::xml; namespace document { -IMPLEMENT_IDENTIFIABLE(RawFieldValue, LiteralFieldValueB); - void RawFieldValue::printXml(XmlOutputStream& out) const { diff --git a/document/src/vespa/document/fieldvalue/rawfieldvalue.h b/document/src/vespa/document/fieldvalue/rawfieldvalue.h index 98110816a9d..b946ecd0038 100644 --- a/document/src/vespa/document/fieldvalue/rawfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/rawfieldvalue.h @@ -12,20 +12,19 @@ namespace document { -class RawFieldValue - : public LiteralFieldValue<RawFieldValue, DataType::T_RAW, false> +class RawFieldValue final : public LiteralFieldValue<RawFieldValue, DataType::T_RAW> { public: - typedef LiteralFieldValue<RawFieldValue, DataType::T_RAW, false> Parent; + typedef LiteralFieldValue<RawFieldValue, DataType::T_RAW> Parent; RawFieldValue() - : Parent() { } + : Parent(Type::RAW) { } RawFieldValue(const string& value) - : Parent(value) {} + : Parent(Type::RAW, value) {} RawFieldValue(const char* rawVal, int len) - : Parent(string(rawVal, len)) + : Parent(Type::RAW, string(rawVal, len)) { } @@ -37,8 +36,6 @@ public: void print(std::ostream& out, bool verbose, const std::string& indent) const override; RawFieldValue& operator=(const string& value) { setValue(value); return *this; } - - DECLARE_IDENTIFIABLE(RawFieldValue); }; } // document diff --git a/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp b/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp index 328e5b67151..cade633fb00 100644 --- a/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp @@ -11,28 +11,24 @@ using vespalib::make_string; namespace document { -IMPLEMENT_IDENTIFIABLE(ReferenceFieldValue, FieldValue); - ReferenceFieldValue::ReferenceFieldValue() - : _dataType(nullptr), - _documentId(), - _altered(true) + : FieldValue(Type::REFERENCE), + _dataType(nullptr), + _documentId() { } ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType) - : _dataType(&dataType), - _documentId(), - _altered(true) + : FieldValue(Type::REFERENCE), + _dataType(&dataType), + _documentId() { } -ReferenceFieldValue::ReferenceFieldValue( - const ReferenceDataType& dataType, - const DocumentId& documentId) - : _dataType(&dataType), - _documentId(documentId), - _altered(true) +ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType, const DocumentId& documentId) + : FieldValue(Type::REFERENCE), + _dataType(&dataType), + _documentId(documentId) { requireIdOfMatchingType(_documentId, _dataType->getTargetType()); } @@ -67,7 +63,6 @@ FieldValue& ReferenceFieldValue::assign(const FieldValue& rhs) { } _documentId = refValueRhs->_documentId; _dataType = refValueRhs->_dataType; - _altered = true; return *this; } @@ -77,7 +72,6 @@ void ReferenceFieldValue::setDeserializedDocumentId(const DocumentId& id) { _documentId = id; // Pre-cache GID to ensure it's not attempted lazily initialized later in a racing manner. (void) _documentId.getGlobalId(); - _altered = false; } ReferenceFieldValue* ReferenceFieldValue::clone() const { @@ -109,10 +103,6 @@ void ReferenceFieldValue::print(std::ostream& os, bool verbose, const std::strin os << indent << "ReferenceFieldValue(" << *_dataType << ", DocumentId(" << _documentId << "))"; } -bool ReferenceFieldValue::hasChanged() const { - return _altered; -} - void ReferenceFieldValue::accept(FieldValueVisitor& visitor) { visitor.visit(*this); } diff --git a/document/src/vespa/document/fieldvalue/referencefieldvalue.h b/document/src/vespa/document/fieldvalue/referencefieldvalue.h index d8160353b5f..c8adb49102a 100644 --- a/document/src/vespa/document/fieldvalue/referencefieldvalue.h +++ b/document/src/vespa/document/fieldvalue/referencefieldvalue.h @@ -22,11 +22,10 @@ namespace document { * document type "foo" inheriting "bar", you cannot have a reference<bar> field * containing a document ID for a "foo" document. */ -class ReferenceFieldValue : public FieldValue { +class ReferenceFieldValue final : public FieldValue { const ReferenceDataType* _dataType; // TODO wrap in std::optional once available. DocumentId _documentId; - bool _altered; public: // Empty constructor required for Identifiable. ReferenceFieldValue(); @@ -53,9 +52,6 @@ public: // Should only be called by deserializer code, as it will clear hasChanged. // `id` must be a valid document ID and cannot be empty. void setDeserializedDocumentId(const DocumentId& id); - void clearChanged() { - _altered = false; - } const DataType* getDataType() const override { return _dataType; } FieldValue& assign(const FieldValue&) override; @@ -63,16 +59,12 @@ public: int compare(const FieldValue&) const override; void printXml(XmlOutputStream&) const override { /* Not implemented */ } void print(std::ostream&, bool, const std::string&) const override; - bool hasChanged() const override; void accept(FieldValueVisitor&) override; void accept(ConstFieldValueVisitor&) const override; - - DECLARE_IDENTIFIABLE(ReferenceFieldValue); private: // Throws vespalib::IllegalArgumentException if doc type of `id` does not // match the name of `type`. - static void requireIdOfMatchingType( - const DocumentId& id, const DocumentType& type); + static void requireIdOfMatchingType(const DocumentId& id, const DocumentType& type); }; } // document diff --git a/document/src/vespa/document/fieldvalue/shortfieldvalue.cpp b/document/src/vespa/document/fieldvalue/shortfieldvalue.cpp index 9f0334a12ae..02fa8fb30a2 100644 --- a/document/src/vespa/document/fieldvalue/shortfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/shortfieldvalue.cpp @@ -5,6 +5,4 @@ namespace document { -IMPLEMENT_IDENTIFIABLE(ShortFieldValue, NumericFieldValueBase); - } // document diff --git a/document/src/vespa/document/fieldvalue/shortfieldvalue.h b/document/src/vespa/document/fieldvalue/shortfieldvalue.h index fa61c37c4eb..e135f2a4f54 100644 --- a/document/src/vespa/document/fieldvalue/shortfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/shortfieldvalue.h @@ -12,13 +12,13 @@ namespace document { -class ShortFieldValue : public NumericFieldValue<int16_t> { +class ShortFieldValue final : public NumericFieldValue<int16_t> { public: typedef std::unique_ptr<ShortFieldValue> UP; typedef int16_t Number; ShortFieldValue(Number value = 0) - : NumericFieldValue<Number>(value) {} + : NumericFieldValue<Number>(Type::SHORT, value) {} void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -27,7 +27,6 @@ public: ShortFieldValue* clone() const override { return new ShortFieldValue(*this); } using NumericFieldValue<Number>::operator=; - DECLARE_IDENTIFIABLE(ShortFieldValue); static std::unique_ptr<ShortFieldValue> make(int16_t value = 0) { return std::make_unique<ShortFieldValue>(value); } }; diff --git a/document/src/vespa/document/fieldvalue/stringfieldvalue.cpp b/document/src/vespa/document/fieldvalue/stringfieldvalue.cpp index 0a46a11bddf..47e96b4f4e4 100644 --- a/document/src/vespa/document/fieldvalue/stringfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/stringfieldvalue.cpp @@ -19,17 +19,16 @@ using vespalib::stringref; namespace document { -IMPLEMENT_IDENTIFIABLE(StringFieldValue, LiteralFieldValueB); - -StringFieldValue::StringFieldValue(const StringFieldValue & rhs) : - Parent(rhs), - _annotationData(rhs.copyAnnotationData()) +StringFieldValue::StringFieldValue(const StringFieldValue & rhs) + : Parent(rhs), + _annotationData(rhs.copyAnnotationData()) { } -StringFieldValue::~StringFieldValue() {} +StringFieldValue::~StringFieldValue() = default; -StringFieldValue & StringFieldValue::operator=(const StringFieldValue & rhs) +StringFieldValue & +StringFieldValue::operator=(const StringFieldValue & rhs) { if (&rhs != this) { Parent::operator=(rhs); @@ -38,8 +37,9 @@ StringFieldValue & StringFieldValue::operator=(const StringFieldValue & rhs) return *this; } -int StringFieldValue::compare(const FieldValue& other) const { - if (other.inherits(StringFieldValue::classId)) { +int +StringFieldValue::compare(const FieldValue& other) const { + if (other.isA(Type::STRING)) { const StringFieldValue &other_s(static_cast<const StringFieldValue &>(other)); return _value.compare(other_s._value); } else { @@ -47,7 +47,8 @@ int StringFieldValue::compare(const FieldValue& other) const { } } -void StringFieldValue::print(std::ostream& out, bool verbose, const std::string& indent) const { +void +StringFieldValue::print(std::ostream& out, bool verbose, const std::string& indent) const { if ( ! hasSpanTrees()) { Parent::print(out, verbose, indent); } else { @@ -88,7 +89,8 @@ StringFieldValue::doClearSpanTrees() { _annotationData.reset(); } -const SpanTree * StringFieldValue::findTree(const SpanTrees & trees, stringref name) +const SpanTree * +StringFieldValue::findTree(const SpanTrees & trees, stringref name) { for(const auto & tree : trees) { if (tree->getName() == name) { @@ -98,16 +100,18 @@ const SpanTree * StringFieldValue::findTree(const SpanTrees & trees, stringref n return nullptr; } -StringFieldValue &StringFieldValue::operator=(stringref value) +StringFieldValue & +StringFieldValue::operator=(stringref value) { setValue(value); _annotationData.reset(); return *this; } -FieldValue & StringFieldValue::assign(const FieldValue & rhs) +FieldValue & +StringFieldValue::assign(const FieldValue & rhs) { - if (rhs.inherits(StringFieldValue::classId)) { + if (rhs.isA(Type::STRING)) { *this = static_cast<const StringFieldValue &>(rhs); } else { *this = rhs.getAsString().operator stringref(); diff --git a/document/src/vespa/document/fieldvalue/stringfieldvalue.h b/document/src/vespa/document/fieldvalue/stringfieldvalue.h index 07e9e578692..95cd9c6190c 100644 --- a/document/src/vespa/document/fieldvalue/stringfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/stringfieldvalue.h @@ -17,14 +17,14 @@ namespace document { class FixedTypeRepo; class DocumentTypeRepo; -class StringFieldValue : public LiteralFieldValue<StringFieldValue, DataType::T_STRING, true> { +class StringFieldValue final : public LiteralFieldValue<StringFieldValue, DataType::T_STRING> { public: - typedef LiteralFieldValue<StringFieldValue, DataType::T_STRING, true> Parent; + typedef LiteralFieldValue<StringFieldValue, DataType::T_STRING> Parent; typedef std::vector<SpanTree::UP> SpanTrees; - StringFieldValue() : Parent(), _annotationData() { } + StringFieldValue() : Parent(Type::STRING), _annotationData() { } StringFieldValue(const vespalib::stringref &value) - : Parent(value), _annotationData() { } + : Parent(Type::STRING, value), _annotationData() { } StringFieldValue(const StringFieldValue &rhs); @@ -55,7 +55,6 @@ public: } using LiteralFieldValueB::operator=; - DECLARE_IDENTIFIABLE(StringFieldValue); static std::unique_ptr<StringFieldValue> make(vespalib::stringref value) { return std::make_unique<StringFieldValue>(value); } static std::unique_ptr<StringFieldValue> make() { return StringFieldValue::make(""); } private: diff --git a/document/src/vespa/document/fieldvalue/structfieldvalue.cpp b/document/src/vespa/document/fieldvalue/structfieldvalue.cpp index fbe6dadb320..529e608533e 100644 --- a/document/src/vespa/document/fieldvalue/structfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/structfieldvalue.cpp @@ -27,10 +27,8 @@ using namespace vespalib::xml; namespace document { -IMPLEMENT_IDENTIFIABLE_ABSTRACT(StructFieldValue, StructuredFieldValue); - StructFieldValue::StructFieldValue(const DataType &type) - : StructuredFieldValue(type), + : StructuredFieldValue(Type::STRUCT, type), _fields(), _repo(nullptr), _doc_type(nullptr), diff --git a/document/src/vespa/document/fieldvalue/structfieldvalue.h b/document/src/vespa/document/fieldvalue/structfieldvalue.h index 24e143ddc27..564c48273e6 100644 --- a/document/src/vespa/document/fieldvalue/structfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/structfieldvalue.h @@ -22,7 +22,7 @@ class FixedTypeRepo; class FieldSet; class StructDataType; -class StructFieldValue : public StructuredFieldValue +class StructFieldValue final : public StructuredFieldValue { private: SerializableArray _fields; @@ -76,7 +76,12 @@ public: bool empty() const override; - bool hasChanged() const override { return _hasChanged; } + /** + * Returns true if this object have been altered since last + * serialization/deserialization. If hasChanged() is false, then cached + * information from last serialization effort is still valid. + */ + bool hasChanged() const { return _hasChanged; } uint32_t calculateChecksum() const; @@ -85,9 +90,6 @@ public: * has no content. This clears content and sets changed to false. */ void reset(); - - DECLARE_IDENTIFIABLE_ABSTRACT(StructFieldValue); - private: void setFieldValue(const Field&, FieldValue::UP value) override; FieldValue::UP getFieldValue(const Field&) const override; diff --git a/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp b/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp index 53f75cb2e73..53a5fa14fee 100644 --- a/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp @@ -16,8 +16,6 @@ namespace document { using namespace fieldvalue; -IMPLEMENT_IDENTIFIABLE_ABSTRACT(StructuredFieldValue, FieldValue); - StructuredFieldValue::Iterator::Iterator() : _iterator(), _field(nullptr) diff --git a/document/src/vespa/document/fieldvalue/structuredfieldvalue.h b/document/src/vespa/document/fieldvalue/structuredfieldvalue.h index 9d79b6279a4..fdc4ecf7765 100644 --- a/document/src/vespa/document/fieldvalue/structuredfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/structuredfieldvalue.h @@ -44,7 +44,7 @@ class StructuredFieldValue : public FieldValue virtual StructuredCache * getCache() const { return nullptr; } protected: - StructuredFieldValue(const DataType &type) : FieldValue(), _type(&type) {} + StructuredFieldValue(Type type, const DataType &dataType) : FieldValue(type), _type(&dataType) {} /** Called from Document when deserializing alters type. */ virtual void setType(const DataType& type) { _type = &type; } @@ -106,8 +106,6 @@ protected: fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const override; public: - DECLARE_IDENTIFIABLE_ABSTRACT(StructuredFieldValue); - StructuredFieldValue* clone() const override = 0; const DataType *getDataType() const override { return _type; } diff --git a/document/src/vespa/document/fieldvalue/structuredfieldvalue.hpp b/document/src/vespa/document/fieldvalue/structuredfieldvalue.hpp index 4b347d7cc07..c142fd9b6eb 100644 --- a/document/src/vespa/document/fieldvalue/structuredfieldvalue.hpp +++ b/document/src/vespa/document/fieldvalue/structuredfieldvalue.hpp @@ -12,7 +12,7 @@ template <typename T> std::unique_ptr<T> StructuredFieldValue::getAs(const Field &field) const { FieldValue::UP val = getValue(field); - T *t = Identifiable::cast<T *>(val.get()); + T *t = dynamic_cast<T *>(val.get()); if (val.get() && !t) { throw vespalib::IllegalStateException("Field " + field.toString() + " has unexpected type.", VESPA_STRLOC); } diff --git a/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp b/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp index 42f4080d6b6..d9a56f9fa56 100644 --- a/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp @@ -36,18 +36,16 @@ TensorFieldValue::TensorFieldValue() } TensorFieldValue::TensorFieldValue(const TensorDataType &dataType) - : FieldValue(), + : FieldValue(Type::TENSOR), _dataType(dataType), - _tensor(), - _altered(true) + _tensor() { } TensorFieldValue::TensorFieldValue(const TensorFieldValue &rhs) - : FieldValue(), + : FieldValue(Type::TENSOR), _dataType(rhs._dataType), - _tensor(), - _altered(true) + _tensor() { if (rhs._tensor) { _tensor = FastValueBuilderFactory::get().copy(*rhs._tensor); @@ -56,10 +54,9 @@ TensorFieldValue::TensorFieldValue(const TensorFieldValue &rhs) TensorFieldValue::TensorFieldValue(TensorFieldValue &&rhs) - : FieldValue(), + : FieldValue(Type::TENSOR), _dataType(rhs._dataType), - _tensor(), - _altered(true) + _tensor() { _tensor = std::move(rhs._tensor); } @@ -81,7 +78,6 @@ TensorFieldValue::operator=(const TensorFieldValue &rhs) } else { _tensor.reset(); } - _altered = true; } else { throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs._tensor->type()), VESPA_STRLOC); } @@ -95,7 +91,6 @@ TensorFieldValue::operator=(std::unique_ptr<vespalib::eval::Value> rhs) { if (!rhs || _dataType.isAssignableType(rhs->type())) { _tensor = std::move(rhs); - _altered = true; } else { throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC); } @@ -133,14 +128,6 @@ TensorFieldValue::getDataType() const return &_dataType; } - -bool -TensorFieldValue::hasChanged() const -{ - return _altered; -} - - TensorFieldValue* TensorFieldValue::clone() const { @@ -173,9 +160,8 @@ TensorFieldValue::printXml(XmlOutputStream& out) const FieldValue & TensorFieldValue::assign(const FieldValue &value) { - const TensorFieldValue *rhs = - Identifiable::cast<const TensorFieldValue *>(&value); - if (rhs != nullptr) { + if (value.isA(Type::TENSOR)) { + const auto * rhs = static_cast<const TensorFieldValue *>(&value); *this = *rhs; } else { return FieldValue::assign(value); @@ -189,7 +175,6 @@ TensorFieldValue::assignDeserialized(std::unique_ptr<vespalib::eval::Value> rhs) { if (!rhs || _dataType.isAssignableType(rhs->type())) { _tensor = std::move(rhs); - _altered = false; // Serialized form already exists } else { throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC); } @@ -232,6 +217,4 @@ TensorFieldValue::compare(const FieldValue &other) const return lhs_spec.compare(rhs_spec); } -IMPLEMENT_IDENTIFIABLE(TensorFieldValue, FieldValue); - } // document diff --git a/document/src/vespa/document/fieldvalue/tensorfieldvalue.h b/document/src/vespa/document/fieldvalue/tensorfieldvalue.h index 6cb2ff08c2e..52b27346ff8 100644 --- a/document/src/vespa/document/fieldvalue/tensorfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/tensorfieldvalue.h @@ -13,39 +13,34 @@ class TensorDataType; /** * Field value representing a tensor. */ -class TensorFieldValue : public FieldValue { +class TensorFieldValue final : public FieldValue { private: const TensorDataType &_dataType; std::unique_ptr<vespalib::eval::Value> _tensor; - bool _altered; public: TensorFieldValue(); explicit TensorFieldValue(const TensorDataType &dataType); TensorFieldValue(const TensorFieldValue &rhs); TensorFieldValue(TensorFieldValue &&rhs); - ~TensorFieldValue(); + ~TensorFieldValue() override; TensorFieldValue &operator=(const TensorFieldValue &rhs); TensorFieldValue &operator=(std::unique_ptr<vespalib::eval::Value> rhs); void make_empty_if_not_existing(); - virtual void accept(FieldValueVisitor &visitor) override; - virtual void accept(ConstFieldValueVisitor &visitor) const override; - virtual const DataType *getDataType() const override; - virtual bool hasChanged() const override; - virtual TensorFieldValue* clone() const override; - virtual void print(std::ostream& out, bool verbose, - const std::string& indent) const override; - virtual void printXml(XmlOutputStream& out) const override; - virtual FieldValue &assign(const FieldValue &value) override; + void accept(FieldValueVisitor &visitor) override; + void accept(ConstFieldValueVisitor &visitor) const override; + const DataType *getDataType() const override; + TensorFieldValue* clone() const override; + void print(std::ostream& out, bool verbose, const std::string& indent) const override; + void printXml(XmlOutputStream& out) const override; + FieldValue &assign(const FieldValue &value) override; const vespalib::eval::Value *getAsTensorPtr() const { return _tensor.get(); } void assignDeserialized(std::unique_ptr<vespalib::eval::Value> rhs); - virtual int compare(const FieldValue& other) const override; - - DECLARE_IDENTIFIABLE(TensorFieldValue); + int compare(const FieldValue& other) const override; }; } // document diff --git a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp index 2a3726095df..fd26deab15a 100644 --- a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp +++ b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp @@ -18,8 +18,6 @@ namespace document { using namespace fieldvalue; -IMPLEMENT_IDENTIFIABLE_ABSTRACT(WeightedSetFieldValue, CollectionFieldValue); - namespace { const DataType &getKeyType(const DataType &type) { const WeightedSetDataType *wtype = dynamic_cast<const WeightedSetDataType *>(&type); @@ -32,10 +30,9 @@ const DataType &getKeyType(const DataType &type) { } // namespace WeightedSetFieldValue::WeightedSetFieldValue(const DataType &type) - : CollectionFieldValue(type), + : CollectionFieldValue(Type::WSET, type), _map_type(std::make_shared<MapDataType>(getKeyType(type), *DataType::INT)), - _map(*_map_type), - _altered(true) + _map(*_map_type) { } WeightedSetFieldValue::WeightedSetFieldValue(const WeightedSetFieldValue &) = default; @@ -54,7 +51,6 @@ WeightedSetFieldValue::add(const FieldValue& key, int weight) { verifyKey(key); const WeightedSetDataType & wdt(static_cast<const WeightedSetDataType&>(*_type)); - _altered = true; if (wdt.removeIfZero() && (weight == 0)) { _map.erase(key); return false; @@ -66,14 +62,12 @@ bool WeightedSetFieldValue::addIgnoreZeroWeight(const FieldValue& key, int32_t weight) { verifyKey(key); - _altered = true; return _map.insert(FieldValue::UP(key.clone()), IntFieldValue::make(weight)); } void WeightedSetFieldValue::push_back(FieldValue::UP key, int weight) { - _altered = true; _map.push_back(std::move(key), IntFieldValue::make(weight)); } @@ -103,7 +97,6 @@ WeightedSetFieldValue::increment(const FieldValue& key, int val) _map.erase(key); } } - _altered = true; } int32_t @@ -125,7 +118,6 @@ bool WeightedSetFieldValue::removeValue(const FieldValue& key) { bool result = _map.erase(key); - _altered |= result; return result; } @@ -179,14 +171,6 @@ WeightedSetFieldValue::print(std::ostream& out, bool verbose, const std::string& out << ")"; } -bool -WeightedSetFieldValue::hasChanged() const -{ - // Keys are not allowed to change in a map, so the keys should not be - // referred to externally, and should thus not need to be checked. - return _altered; -} - WeightedSetFieldValue::const_iterator WeightedSetFieldValue::find(const FieldValue& key) const { diff --git a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h index d58819607b4..b2183efef42 100644 --- a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h +++ b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h @@ -14,7 +14,7 @@ namespace document { -class WeightedSetFieldValue : public CollectionFieldValue +class WeightedSetFieldValue final : public CollectionFieldValue { public: struct FieldValuePtrOrder { @@ -26,7 +26,6 @@ public: private: std::shared_ptr<const MapDataType> _map_type; WeightedFieldValueMap _map; - bool _altered; void verifyKey(const FieldValue & key); bool addValue(const FieldValue& fval) override { return add(fval, 1); } @@ -46,7 +45,7 @@ public: WeightedSetFieldValue & operator = (const WeightedSetFieldValue &); WeightedSetFieldValue(WeightedSetFieldValue &&) = default; WeightedSetFieldValue & operator = (WeightedSetFieldValue &&) = default; - ~WeightedSetFieldValue(); + ~WeightedSetFieldValue() override; void accept(FieldValueVisitor &visitor) override { visitor.visit(*this); } void accept(ConstFieldValueVisitor &visitor) const override { visitor.visit(*this); } @@ -78,7 +77,6 @@ public: int compare(const FieldValue&) const override; void printXml(XmlOutputStream& out) const override; void print(std::ostream& out, bool verbose, const std::string& indent) const override; - bool hasChanged() const override; // Implements iterating through internal content. typedef WeightedFieldValueMap::const_iterator const_iterator; @@ -92,8 +90,6 @@ public: const_iterator find(const FieldValue& fv) const; iterator find(const FieldValue& fv); - - DECLARE_IDENTIFIABLE_ABSTRACT(WeightedSetFieldValue); }; } // document diff --git a/document/src/vespa/document/select/valuenodes.cpp b/document/src/vespa/document/select/valuenodes.cpp index 52e6b2e4223..f34b2e83b08 100644 --- a/document/src/vespa/document/select/valuenodes.cpp +++ b/document/src/vespa/document/select/valuenodes.cpp @@ -11,7 +11,6 @@ #include <vespa/vespalib/util/md5.h> #include <vespa/document/util/stringutil.h> #include <vespa/vespalib/text/lowercase.h> -#include <regex> #include <iomanip> #include <sys/time.h> @@ -272,43 +271,43 @@ IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) { std::unique_ptr<Value> IteratorHandler::getInternalValue(const FieldValue& fval) const { - switch(fval.getClass().id()) { - case document::BoolFieldValue::classId: + switch(fval.type()) { + case FieldValue::Type::BOOL: { const auto& val(dynamic_cast<const BoolFieldValue&>(fval)); return std::make_unique<IntegerValue>(val.getAsInt(), false); } - case document::IntFieldValue::classId: + case FieldValue::Type::INT: { const auto& val(dynamic_cast<const IntFieldValue&>(fval)); return std::make_unique<IntegerValue>(val.getAsInt(), false); } - case document::ByteFieldValue::classId: + case FieldValue::Type::BYTE: { const auto& val(dynamic_cast<const ByteFieldValue&>(fval)); return std::make_unique<IntegerValue>(val.getAsByte(), false); } - case LongFieldValue::classId: + case FieldValue::Type::LONG: { const auto& val(dynamic_cast<const LongFieldValue&>(fval)); return std::make_unique<IntegerValue>(val.getAsLong(), false); } - case FloatFieldValue::classId: + case FieldValue::Type::FLOAT: { const auto& val(dynamic_cast<const FloatFieldValue&>(fval)); return std::make_unique<FloatValue>(val.getAsFloat()); } - case DoubleFieldValue::classId: + case FieldValue::Type::DOUBLE: { const auto& val(dynamic_cast<const DoubleFieldValue&>(fval)); return std::make_unique<FloatValue>(val.getAsDouble()); } - case StringFieldValue::classId: + case FieldValue::Type::STRING: { const auto& val(dynamic_cast<const StringFieldValue&>(fval)); return std::make_unique<StringValue>(val.getAsString()); } - case ReferenceFieldValue::classId: + case FieldValue::Type::REFERENCE: { const auto& val(dynamic_cast<const ReferenceFieldValue&>(fval)); if (val.hasValidDocumentId()) { @@ -317,7 +316,7 @@ IteratorHandler::getInternalValue(const FieldValue& fval) const return std::make_unique<InvalidValue>(); } } - case ArrayFieldValue::classId: + case FieldValue::Type::ARRAY: { const auto& val(dynamic_cast<const ArrayFieldValue&>(fval)); if (val.size() == 0) { @@ -328,7 +327,7 @@ IteratorHandler::getInternalValue(const FieldValue& fval) const return std::make_unique<ArrayValue>(values); } } - case StructFieldValue::classId: + case FieldValue::Type::STRUCT: { const auto& val(dynamic_cast<const StructFieldValue&>(fval)); if (val.empty()) { @@ -342,7 +341,7 @@ IteratorHandler::getInternalValue(const FieldValue& fval) const return std::make_unique<StructValue>(values); } } - case MapFieldValue::classId: + case FieldValue::Type::MAP: { const auto& val(static_cast<const MapFieldValue&>(fval)); if (val.isEmpty()) { @@ -353,6 +352,8 @@ IteratorHandler::getInternalValue(const FieldValue& fval) const return std::make_unique<ArrayValue>(values); } } + default: + break; } LOG(warning, "Tried to use unsupported datatype %s in field comparison", fval.getDataType()->toString().c_str()); diff --git a/document/src/vespa/document/serialization/annotationdeserializer.cpp b/document/src/vespa/document/serialization/annotationdeserializer.cpp index e3192459574..9e7a35cfdcb 100644 --- a/document/src/vespa/document/serialization/annotationdeserializer.cpp +++ b/document/src/vespa/document/serialization/annotationdeserializer.cpp @@ -119,9 +119,10 @@ void AnnotationDeserializer::readAnnotation(Annotation & annotation) { if (features & 2) { // has value uint32_t data_type_id = readValue<uint32_t>(_stream); - const DataType *data_type = _repo.getDataType(data_type_id); + const DataType *data_type = type->getDataType(); if (!data_type) { - LOG(warning, "Unknown data type %d", data_type_id); + LOG(warning, "Skipping payload (data type %d) for annotation type %s", + data_type_id, type->getName().c_str()); _stream.adjustReadPos(size - sizeof(uint32_t)); } else { FieldValue::UP value(data_type->createFieldValue()); diff --git a/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp b/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp index 747dfbbcee6..55ea4988fc4 100644 --- a/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp +++ b/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp @@ -447,8 +447,6 @@ VespaDocumentDeserializer::read(ReferenceFieldValue& value) { DocumentId id; read(id); value.setDeserializedDocumentId(id); - } else { - value.clearChanged(); } } diff --git a/document/src/vespa/document/update/addfieldpathupdate.cpp b/document/src/vespa/document/update/addfieldpathupdate.cpp index 227ac34d78b..bd06451759e 100644 --- a/document/src/vespa/document/update/addfieldpathupdate.cpp +++ b/document/src/vespa/document/update/addfieldpathupdate.cpp @@ -31,7 +31,7 @@ AddFieldPathUpdate::AddFieldPathUpdate() : FieldPathUpdate(), _values() { } -AddFieldPathUpdate::~AddFieldPathUpdate() { } +AddFieldPathUpdate::~AddFieldPathUpdate() = default; FieldPathUpdate* AddFieldPathUpdate::clone() const { @@ -53,13 +53,13 @@ private: ModificationStatus AddIteratorHandler::doModify(FieldValue &fv) { - if (fv.inherits(CollectionFieldValue::classId)) { + if (fv.isCollection()) { CollectionFieldValue &cf = static_cast<CollectionFieldValue &>(fv); for (std::size_t i = 0; i < _values.size(); ++i) { cf.add(_values[i]); } } else { - vespalib::string err = make_string("Unable to add a value to a \"%s\" field value.", fv.getClass().name()); + vespalib::string err = make_string("Unable to add a value to a \"%s\" field value.", fv.className()); throw vespalib::IllegalArgumentException(err, VESPA_STRLOC); } return ModificationStatus::MODIFIED; diff --git a/document/src/vespa/document/update/addvalueupdate.cpp b/document/src/vespa/document/update/addvalueupdate.cpp index e12afd8fa63..6f6c9a93738 100644 --- a/document/src/vespa/document/update/addvalueupdate.cpp +++ b/document/src/vespa/document/update/addvalueupdate.cpp @@ -63,14 +63,14 @@ AddValueUpdate::print(std::ostream& out, bool, const std::string& indent) const bool AddValueUpdate::applyTo(FieldValue& value) const { - if (value.inherits(ArrayFieldValue::classId)) { + if (value.isA(FieldValue::Type::ARRAY)) { ArrayFieldValue& doc(static_cast<ArrayFieldValue&>(value)); doc.add(*_value); - } else if (value.inherits(WeightedSetFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::WSET)) { WeightedSetFieldValue& doc(static_cast<WeightedSetFieldValue&>(value)); doc.add(*_value, _weight); } else { - std::string err = make_string("Unable to add a value to a \"%s\" field value.", value.getClass().name()); + vespalib::string err = make_string("Unable to add a value to a \"%s\" field value.", value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; diff --git a/document/src/vespa/document/update/arithmeticvalueupdate.cpp b/document/src/vespa/document/update/arithmeticvalueupdate.cpp index b33312d8e65..e5fb5aee8af 100644 --- a/document/src/vespa/document/update/arithmeticvalueupdate.cpp +++ b/document/src/vespa/document/update/arithmeticvalueupdate.cpp @@ -2,7 +2,6 @@ #include "arithmeticvalueupdate.h" #include <vespa/document/base/field.h> #include <vespa/document/fieldvalue/fieldvalues.h> -#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/vespalib/util/xmlstream.h> #include <ostream> @@ -44,25 +43,25 @@ ArithmeticValueUpdate::checkCompatibility(const Field& field) const bool ArithmeticValueUpdate::applyTo(FieldValue& value) const { - if (value.inherits(ByteFieldValue::classId)) { + if (value.isA(FieldValue::Type::BYTE)) { ByteFieldValue& bValue = static_cast<ByteFieldValue&>(value); bValue.setValue((int)applyTo(static_cast<int64_t>(bValue.getAsInt()))); - } else if (value.inherits(DoubleFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::DOUBLE)) { DoubleFieldValue& dValue = static_cast<DoubleFieldValue&>(value); dValue.setValue(applyTo(dValue.getAsDouble())); - } else if (value.inherits(FloatFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::FLOAT)) { FloatFieldValue& fValue = static_cast<FloatFieldValue&>(value); fValue.setValue((float)applyTo(fValue.getAsFloat())); - } else if (value.inherits(IntFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::INT)) { IntFieldValue& iValue = static_cast<IntFieldValue&>(value); iValue.setValue((int)applyTo(static_cast<int64_t>(iValue.getAsInt()))); - } else if (value.inherits(LongFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::LONG)) { LongFieldValue& lValue = static_cast<LongFieldValue&>(value); lValue.setValue(applyTo(lValue.getAsLong())); } else { - std::string err = vespalib::make_string( + vespalib::string err = vespalib::make_string( "Unable to perform an arithmetic update on a \"%s\" field " - "value.", value.getClass().name()); + "value.", value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; diff --git a/document/src/vespa/document/update/assignfieldpathupdate.cpp b/document/src/vespa/document/update/assignfieldpathupdate.cpp index 9fa5f4fa441..d4cbff2aae9 100644 --- a/document/src/vespa/document/update/assignfieldpathupdate.cpp +++ b/document/src/vespa/document/update/assignfieldpathupdate.cpp @@ -3,7 +3,6 @@ #include "assignfieldpathupdate.h" #include <vespa/document/fieldvalue/fieldvalues.h> #include <vespa/document/fieldvalue/iteratorhandler.h> -#include <vespa/document/select/parser.h> #include <vespa/document/select/variablemap.h> #include <vespa/document/serialization/vespadocumentdeserializer.h> #include <vespa/vespalib/objects/nbostream.h> @@ -118,12 +117,11 @@ AssignValueIteratorHandler::doModify(FieldValue& fv) { if (!(*fv.getDataType() == *_newValue.getDataType())) { vespalib::string err = vespalib::make_string( "Trying to assign \"%s\" of type %s to an instance of type %s", - _newValue.toString().c_str(), _newValue.getClass().name(), - fv.getClass().name()); + _newValue.toString().c_str(), _newValue.className(), fv.className()); throw vespalib::IllegalArgumentException(err, VESPA_STRLOC); } if (_removeIfZero - && _newValue.inherits(NumericFieldValueBase::classId) + && _newValue.isNumeric() && static_cast<const NumericFieldValueBase&>(_newValue).getAsLong() == 0) { return ModificationStatus::REMOVED; @@ -135,13 +133,13 @@ AssignValueIteratorHandler::doModify(FieldValue& fv) { ModificationStatus AssignExpressionIteratorHandler::doModify(FieldValue& fv) { LOG(spam, "fv = %s", fv.toString().c_str()); - if (fv.inherits(NumericFieldValueBase::classId)) { + if (fv.isNumeric()) { std::unique_ptr<select::VariableMap> varHolder = std::make_unique<select::VariableMap>(); select::VariableMap & vars = *varHolder; for (VariableMap::const_iterator i(getVariables().begin()), e(getVariables().end()); i != e; ++i) { - if (i->second.key.get() && i->second.key->inherits(NumericFieldValueBase::classId)) { + if (i->second.key.get() && i->second.key->isNumeric()) { vars[i->first] = i->second.key->getAsDouble(); } else { vars[i->first] = i->second.index; diff --git a/document/src/vespa/document/update/assignvalueupdate.cpp b/document/src/vespa/document/update/assignvalueupdate.cpp index d6eb0b501d3..cf2321dbf56 100644 --- a/document/src/vespa/document/update/assignvalueupdate.cpp +++ b/document/src/vespa/document/update/assignvalueupdate.cpp @@ -71,7 +71,7 @@ AssignValueUpdate::applyTo(FieldValue& value) const !value.getDataType()->isValueType(*_value))) { vespalib::string err = vespalib::make_string( "Unable to assign a \"%s\" value to a \"%s\" field value.", - _value->getClass().name(), value.getClass().name()); + _value->className(), value.className()); throw IllegalStateException(err, VESPA_STRLOC); } if (_value) { diff --git a/document/src/vespa/document/update/documentupdate.h b/document/src/vespa/document/update/documentupdate.h index 69f22237c8f..c7ebe913d79 100644 --- a/document/src/vespa/document/update/documentupdate.h +++ b/document/src/vespa/document/update/documentupdate.h @@ -40,13 +40,14 @@ class VespaDocumentSerializer; * path updates was added, and a new serialization format was * introduced while keeping the old one. */ -class DocumentUpdate final : public Printable, public XmlSerializable +class DocumentUpdate final : public Printable, public vespalib::xml::XmlSerializable { public: - typedef std::unique_ptr<DocumentUpdate> UP; - typedef std::shared_ptr<DocumentUpdate> SP; - typedef std::vector<FieldUpdate> FieldUpdateV; - typedef std::vector<FieldPathUpdate::CP> FieldPathUpdateV; + using UP = std::unique_ptr<DocumentUpdate>; + using SP = std::shared_ptr<DocumentUpdate>; + using FieldUpdateV = std::vector<FieldUpdate>; + using FieldPathUpdateV = std::vector<FieldPathUpdate::CP>; + using XmlOutputStream = vespalib::xml::XmlOutputStream; /** * Create new style document update, possibly with field path updates. diff --git a/document/src/vespa/document/update/fieldpathupdate.h b/document/src/vespa/document/update/fieldpathupdate.h index 5283f0da455..28faad722d4 100644 --- a/document/src/vespa/document/update/fieldpathupdate.h +++ b/document/src/vespa/document/update/fieldpathupdate.h @@ -4,6 +4,7 @@ #include "updatevisitor.h" #include <vespa/document/base/fieldpath.h> #include <vespa/document/util/printable.h> +#include <vespa/document/util/identifiableid.h> namespace document { diff --git a/document/src/vespa/document/update/fieldupdate.h b/document/src/vespa/document/update/fieldupdate.h index 1e4137b9531..e364e5db5fd 100644 --- a/document/src/vespa/document/update/fieldupdate.h +++ b/document/src/vespa/document/update/fieldupdate.h @@ -23,7 +23,7 @@ class DocumentType; class FieldUpdate : public vespalib::Identifiable, public Printable, - public XmlSerializable + public vespalib::xml::XmlSerializable { Field _field; std::vector<ValueUpdate::CP> _updates; @@ -31,6 +31,7 @@ class FieldUpdate : public vespalib::Identifiable, public: typedef vespalib::CloneablePtr<FieldUpdate> CP; + using XmlOutputStream = vespalib::xml::XmlOutputStream; FieldUpdate(const Field& field); FieldUpdate(const FieldUpdate &); diff --git a/document/src/vespa/document/update/mapvalueupdate.cpp b/document/src/vespa/document/update/mapvalueupdate.cpp index 18f2c013b7f..48e52a9d2cc 100644 --- a/document/src/vespa/document/update/mapvalueupdate.cpp +++ b/document/src/vespa/document/update/mapvalueupdate.cpp @@ -44,7 +44,7 @@ MapValueUpdate::checkCompatibility(const Field& field) const { // Check compatibility of nested types. if (field.getDataType().isArray()) { - if (_key->getClass().id() != IntFieldValue::classId) { + if ( !_key->isA(FieldValue::Type::INT)) { throw IllegalArgumentException(vespalib::make_string( "Key for field '%s' is of wrong type (expected '%s', was '%s').", field.getName().data(), DataType::INT->toString().c_str(), @@ -60,7 +60,7 @@ MapValueUpdate::checkCompatibility(const Field& field) const } } else { throw IllegalArgumentException("MapValueUpdate does not support " - "datatype " + field.getDataType().toString() + ".", VESPA_STRLOC); + "datatype " + field.getDataType().toString() + ".", VESPA_STRLOC); } } diff --git a/document/src/vespa/document/update/removevalueupdate.cpp b/document/src/vespa/document/update/removevalueupdate.cpp index d35d8db84a2..a61553da4d1 100644 --- a/document/src/vespa/document/update/removevalueupdate.cpp +++ b/document/src/vespa/document/update/removevalueupdate.cpp @@ -56,14 +56,14 @@ RemoveValueUpdate::checkCompatibility(const Field& field) const bool RemoveValueUpdate::applyTo(FieldValue& value) const { - if (value.inherits(ArrayFieldValue::classId)) { + if (value.isA(FieldValue::Type::ARRAY)) { ArrayFieldValue& doc(static_cast<ArrayFieldValue&>(value)); doc.remove(*_key); - } else if (value.inherits(WeightedSetFieldValue::classId)) { + } else if (value.isA(FieldValue::Type::WSET)) { WeightedSetFieldValue& doc(static_cast<WeightedSetFieldValue&>(value)); doc.remove(*_key); } else { - std::string err = vespalib::make_string("Unable to remove a value from a \"%s\" field value.", value.getClass().name()); + std::string err = vespalib::make_string("Unable to remove a value from a \"%s\" field value.", value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; diff --git a/document/src/vespa/document/update/tensor_add_update.cpp b/document/src/vespa/document/update/tensor_add_update.cpp index 3b442b7b1d5..1f8aed2d8b4 100644 --- a/document/src/vespa/document/update/tensor_add_update.cpp +++ b/document/src/vespa/document/update/tensor_add_update.cpp @@ -8,10 +8,8 @@ #include <vespa/document/fieldvalue/document.h> #include <vespa/document/fieldvalue/tensorfieldvalue.h> #include <vespa/document/serialization/vespadocumentdeserializer.h> -#include <vespa/document/util/serializableexceptions.h> #include <vespa/eval/eval/value.h> #include <vespa/eval/eval/fast_value.h> -#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/stllike/asciistream.h> #include <vespa/vespalib/util/stringfmt.h> #include <vespa/vespalib/util/xmlstream.h> @@ -99,7 +97,7 @@ TensorAddUpdate::apply_to(const Value &old_tensor, bool TensorAddUpdate::applyTo(FieldValue& value) const { - if (value.inherits(TensorFieldValue::classId)) { + if (value.isA(FieldValue::Type::TENSOR)) { TensorFieldValue &tensorFieldValue = static_cast<TensorFieldValue &>(value); tensorFieldValue.make_empty_if_not_existing(); auto oldTensor = tensorFieldValue.getAsTensorPtr(); @@ -110,7 +108,7 @@ TensorAddUpdate::applyTo(FieldValue& value) const } } else { vespalib::string err = make_string("Unable to perform a tensor add update on a '%s' field value", - value.getClass().name()); + value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; @@ -136,11 +134,11 @@ void TensorAddUpdate::deserialize(const DocumentTypeRepo &repo, const DataType &type, nbostream & stream) { auto tensor = type.createFieldValue(); - if (tensor->inherits(TensorFieldValue::classId)) { + if (tensor->isA(FieldValue::Type::TENSOR)) { _tensor.reset(static_cast<TensorFieldValue *>(tensor.release())); } else { vespalib::string err = make_string("Expected tensor field value, got a '%s' field value", - tensor->getClass().name()); + tensor->className()); throw IllegalStateException(err, VESPA_STRLOC); } VespaDocumentDeserializer deserializer(repo, stream, Document::getNewestSerializationVersion()); diff --git a/document/src/vespa/document/update/tensor_modify_update.cpp b/document/src/vespa/document/update/tensor_modify_update.cpp index 91ac6f4c754..49ea57f28c1 100644 --- a/document/src/vespa/document/update/tensor_modify_update.cpp +++ b/document/src/vespa/document/update/tensor_modify_update.cpp @@ -94,7 +94,7 @@ TensorModifyUpdate::TensorModifyUpdate() TensorModifyUpdate::TensorModifyUpdate(const TensorModifyUpdate &rhs) : _operation(rhs._operation), _tensorType(std::make_unique<TensorDataType>(*rhs._tensorType)), - _tensor(Identifiable::cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) + _tensor(static_cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) { *_tensor = *rhs._tensor; } @@ -102,7 +102,7 @@ TensorModifyUpdate::TensorModifyUpdate(const TensorModifyUpdate &rhs) TensorModifyUpdate::TensorModifyUpdate(Operation operation, std::unique_ptr<TensorFieldValue> tensor) : _operation(operation), _tensorType(std::make_unique<TensorDataType>(dynamic_cast<const TensorDataType &>(*tensor->getDataType()))), - _tensor(Identifiable::cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) + _tensor(static_cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) { *_tensor = *tensor; } @@ -116,7 +116,7 @@ TensorModifyUpdate::operator=(const TensorModifyUpdate &rhs) _operation = rhs._operation; _tensor.reset(); _tensorType = std::make_unique<TensorDataType>(*rhs._tensorType); - _tensor.reset(Identifiable::cast<TensorFieldValue *>(_tensorType->createFieldValue().release())); + _tensor.reset(dynamic_cast<TensorFieldValue *>(_tensorType->createFieldValue().release())); *_tensor = *rhs._tensor; } return *this; @@ -177,7 +177,7 @@ TensorModifyUpdate::apply_to(const Value &old_tensor, bool TensorModifyUpdate::applyTo(FieldValue& value) const { - if (value.inherits(TensorFieldValue::classId)) { + if (value.isA(FieldValue::Type::TENSOR)) { TensorFieldValue &tensorFieldValue = static_cast<TensorFieldValue &>(value); auto oldTensor = tensorFieldValue.getAsTensorPtr(); if (oldTensor) { @@ -188,7 +188,7 @@ TensorModifyUpdate::applyTo(FieldValue& value) const } } else { vespalib::string err = make_string("Unable to perform a tensor modify update on a '%s' field value", - value.getClass().name()); + value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; @@ -241,11 +241,11 @@ TensorModifyUpdate::deserialize(const DocumentTypeRepo &repo, const DataType &ty _operation = static_cast<Operation>(op); _tensorType = convertToCompatibleType(dynamic_cast<const TensorDataType &>(type)); auto tensor = _tensorType->createFieldValue(); - if (tensor->inherits(TensorFieldValue::classId)) { + if (tensor->isA(FieldValue::Type::TENSOR)) { _tensor.reset(static_cast<TensorFieldValue *>(tensor.release())); } else { vespalib::string err = make_string("Expected tensor field value, got a '%s' field value", - tensor->getClass().name()); + tensor->className()); throw IllegalStateException(err, VESPA_STRLOC); } VespaDocumentDeserializer deserializer(repo, stream, Document::getNewestSerializationVersion()); diff --git a/document/src/vespa/document/update/tensor_remove_update.cpp b/document/src/vespa/document/update/tensor_remove_update.cpp index f4dc9490b62..f2d11ef8234 100644 --- a/document/src/vespa/document/update/tensor_remove_update.cpp +++ b/document/src/vespa/document/update/tensor_remove_update.cpp @@ -54,7 +54,7 @@ TensorRemoveUpdate::TensorRemoveUpdate(const TensorRemoveUpdate &rhs) TensorRemoveUpdate::TensorRemoveUpdate(std::unique_ptr<TensorFieldValue> tensor) : _tensorType(std::make_unique<TensorDataType>(dynamic_cast<const TensorDataType &>(*tensor->getDataType()))), - _tensor(Identifiable::cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) + _tensor(static_cast<TensorFieldValue *>(_tensorType->createFieldValue().release())) { *_tensor = *tensor; } @@ -67,7 +67,7 @@ TensorRemoveUpdate::operator=(const TensorRemoveUpdate &rhs) if (&rhs != this) { _tensor.reset(); _tensorType = std::make_unique<TensorDataType>(*rhs._tensorType); - _tensor.reset(Identifiable::cast<TensorFieldValue *>(_tensorType->createFieldValue().release())); + _tensor.reset(static_cast<TensorFieldValue *>(_tensorType->createFieldValue().release())); *_tensor = *rhs._tensor; } return *this; @@ -122,7 +122,7 @@ TensorRemoveUpdate::apply_to(const Value &old_tensor, bool TensorRemoveUpdate::applyTo(FieldValue &value) const { - if (value.inherits(TensorFieldValue::classId)) { + if (value.isA(FieldValue::Type::TENSOR)) { TensorFieldValue &tensorFieldValue = static_cast<TensorFieldValue &>(value); auto oldTensor = tensorFieldValue.getAsTensorPtr(); if (oldTensor) { @@ -133,7 +133,7 @@ TensorRemoveUpdate::applyTo(FieldValue &value) const } } else { vespalib::string err = make_string("Unable to perform a tensor remove update on a '%s' field value", - value.getClass().name()); + value.className()); throw IllegalStateException(err, VESPA_STRLOC); } return true; diff --git a/document/src/vespa/document/update/valueupdate.h b/document/src/vespa/document/update/valueupdate.h index 9a8ed4e9537..ec903c1adc1 100644 --- a/document/src/vespa/document/update/valueupdate.h +++ b/document/src/vespa/document/update/valueupdate.h @@ -20,9 +20,9 @@ #include "updatevisitor.h" #include <vespa/document/util/printable.h> -#include <vespa/document/util/xmlserializable.h> #include <vespa/document/util/identifiableid.h> #include <vespa/vespalib/objects/nbostream.h> +#include <vespa/vespalib/util/xmlserializable.h> namespace document { @@ -33,12 +33,13 @@ class DataType; class ValueUpdate : public vespalib::Identifiable, public Printable, - public XmlSerializable + public vespalib::xml::XmlSerializable { protected: using nbostream = vespalib::nbostream; public: using CP = vespalib::CloneablePtr<ValueUpdate>; + using XmlOutputStream = vespalib::xml::XmlOutputStream; /** * Create a value update object from the given stream. diff --git a/document/src/vespa/document/util/feed_reject_helper.cpp b/document/src/vespa/document/util/feed_reject_helper.cpp index f23524eddfb..a6829ec0c60 100644 --- a/document/src/vespa/document/util/feed_reject_helper.cpp +++ b/document/src/vespa/document/util/feed_reject_helper.cpp @@ -4,14 +4,12 @@ #include <vespa/document/update/documentupdate.h> #include <vespa/document/update/assignvalueupdate.h> #include <vespa/document/fieldvalue/boolfieldvalue.h> -#include <vespa/document/fieldvalue/numericfieldvalue.h> - namespace document { bool FeedRejectHelper::isFixedSizeSingleValue(const document::FieldValue & fv) { - return fv.inherits(BoolFieldValue::classId) || fv.inherits(NumericFieldValueBase::classId); + return fv.isFixedSizeSingleValue(); } bool diff --git a/document/src/vespa/document/util/xmlserializable.h b/document/src/vespa/document/util/xmlserializable.h deleted file mode 100644 index f4a5db0de58..00000000000 --- a/document/src/vespa/document/util/xmlserializable.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/vespalib/util/xmlserializable.h> - -namespace document { - using XmlSerializable = vespalib::xml::XmlSerializable; - using XmlOutputStream = vespalib::xml::XmlOutputStream; -} diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index fb75fcd8c81..88d21f69f7a 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -370,7 +370,7 @@ public class Flags { ZONE_ID, APPLICATION_ID); public static final UnboundBooleanFlag REUSE_NODE_INDEXES = defineFeatureFlag( - "reuse-node-indexes", false, + "reuse-node-indexes", true, List.of("bratseth"), "2022-02-25", "2022-04-25", "Whether we should reuse earlier indexes when allocating new nodes", "Takes effect immediately", diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java index e3960d995e9..bc199f7160e 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java @@ -260,7 +260,7 @@ public class PermanentFlags { "Architecture to use for node resources. Used when implicitly creating admin clusters " + "(logserver, clustercontroller). Valid values: x86_64, arm64", "Takes effect on next redeployment", - ZONE_ID, APPLICATION_ID, CLUSTER_ID, CLUSTER_TYPE); + ZONE_ID, APPLICATION_ID); private PermanentFlags() {} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java index 30432c1c078..43a78e3a315 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java @@ -47,7 +47,7 @@ public class AllocationOptimizer { limits = Limits.of(new ClusterResources(minimumNodes, 1, NodeResources.unspecified()), new ClusterResources(maximumNodes, maximumNodes, NodeResources.unspecified())); else - limits = atLeast(minimumNodes, limits).fullySpecified(current.clusterSpec().type(), nodeRepository); + limits = atLeast(minimumNodes, limits).fullySpecified(current.clusterSpec().type(), nodeRepository, clusterModel.application().id()); Optional<AllocatableClusterResources> bestAllocation = Optional.empty(); NodeList hosts = nodeRepository.nodes().list().hosts(); for (int groups = limits.min().groups(); groups <= limits.max().groups(); groups++) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java index 3c9cbfe2620..ef45592ad18 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.autoscale; +import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; @@ -59,10 +60,10 @@ public class Limits { return resources; } - public Limits fullySpecified(ClusterSpec.Type type, NodeRepository nodeRepository) { + public Limits fullySpecified(ClusterSpec.Type type, NodeRepository nodeRepository, ApplicationId applicationId) { if (this.isEmpty()) throw new IllegalStateException("Unspecified limits can not be made fully specified"); - var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(type); + var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(type, applicationId); var specifiedMin = min.nodeResources().isUnspecified() ? min.with(defaultResources) : min; var specifiedMax = max.nodeResources().isUnspecified() ? max.with(defaultResources) : max; return new Limits(specifiedMin, specifiedMax); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerService.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerService.java deleted file mode 100644 index 23ddce3ba9e..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerService.java +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.lb; - -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.NodeType; - -import java.util.Comparator; -import java.util.Optional; -import java.util.Set; - -/** - * Implementation of a load balancer service that returns a real as the load balancer instance. This is intended for - * development purposes. - * - * @author mpolden - */ -public class PassthroughLoadBalancerService implements LoadBalancerService { - - @Override - public LoadBalancerInstance create(LoadBalancerSpec spec, boolean force) { - var real = spec.reals().stream() - .min(Comparator.naturalOrder()) - .orElseThrow(() -> new IllegalArgumentException("No reals given")); - return new LoadBalancerInstance(real.hostname(), Optional.empty(), Set.of(real.port()), - Set.of(real.ipAddress() + "/32"), Set.of()); - } - - @Override - public void remove(ApplicationId application, ClusterSpec.Id cluster) { - // Nothing to remove - } - - @Override - public Protocol protocol() { - return Protocol.ipv4; - } - - @Override - public boolean supports(NodeType nodeType, ClusterSpec.Type clusterType) { - return true; - } - -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java index 7dbebd1fc47..1345dfb8e65 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java @@ -5,16 +5,10 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.NodeType; -import com.yahoo.vespa.hosted.provision.Node; -import com.yahoo.vespa.hosted.provision.NodeList; -import com.yahoo.vespa.hosted.provision.NodeRepository; -import com.yahoo.vespa.hosted.provision.node.IP; -import java.util.Comparator; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; /** * This implementation of {@link LoadBalancerService} returns the load balancer(s) that exists by default in the shared @@ -27,28 +21,18 @@ import java.util.stream.Collectors; */ public class SharedLoadBalancerService implements LoadBalancerService { - private static final Comparator<Node> hostnameComparator = Comparator.comparing(Node::hostname); - - private final NodeRepository nodeRepository; private final String vipHostname; - public SharedLoadBalancerService(NodeRepository nodeRepository, String vipHostname) { - this.nodeRepository = Objects.requireNonNull(nodeRepository); + public SharedLoadBalancerService(String vipHostname) { this.vipHostname = Objects.requireNonNull(vipHostname); } @Override public LoadBalancerInstance create(LoadBalancerSpec spec, boolean force) { - NodeList proxyNodes = nodeRepository.nodes().list().nodeType(NodeType.proxy).sortedBy(hostnameComparator); - if (proxyNodes.isEmpty()) throw new IllegalStateException("No proxy nodes found in node-repository"); - Set<String> networks = proxyNodes.stream() - .flatMap(node -> node.ipConfig().primary().stream()) - .map(SharedLoadBalancerService::withPrefixLength) - .collect(Collectors.toSet()); return new LoadBalancerInstance(HostName.from(vipHostname), Optional.empty(), - Set.of(4080, 4443), - networks, + Set.of(4443), + Set.of(), spec.reals()); } @@ -68,11 +52,4 @@ public class SharedLoadBalancerService implements LoadBalancerService { return nodeType == NodeType.tenant && clusterType.isContainer(); } - private static String withPrefixLength(String address) { - if (IP.isV6(address)) { - return address + "/128"; - } - return address + "/32"; - } - } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java index 15decde0d7c..2d36108a1a6 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java @@ -66,7 +66,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent { maintainers.add(new ScalingSuggestionsMaintainer(nodeRepository, defaults.scalingSuggestionsInterval, metric)); maintainers.add(new SwitchRebalancer(nodeRepository, defaults.switchRebalancerInterval, metric, deployer)); - provisionServiceProvider.getLoadBalancerService(nodeRepository) + provisionServiceProvider.getLoadBalancerService() .map(lbService -> new LoadBalancerExpirer(nodeRepository, defaults.loadBalancerExpirerInterval, lbService, metric)) .ifPresent(maintainers::add); provisionServiceProvider.getHostProvisioner() diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index 45e9efc1a1d..f7d5b966c12 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -8,12 +8,15 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.provision.NodeRepository; import java.util.function.Function; import static com.yahoo.config.provision.NodeResources.Architecture; +import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID; +import static com.yahoo.vespa.flags.PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE; /** * Defines the policies for assigning cluster capacity in various environments @@ -25,12 +28,12 @@ public class CapacityPolicies { private final Zone zone; private final Function<ClusterSpec.Type, Boolean> sharedHosts; - private final Architecture architectureForAdminCluster; + private final FlagSource flagSource; public CapacityPolicies(NodeRepository nodeRepository) { this.zone = nodeRepository.zone(); this.sharedHosts = type -> PermanentFlags.SHARED_HOST.bindTo(nodeRepository.flagSource()).value().isEnabled(type.name()); - this.architectureForAdminCluster = Architecture.valueOf(PermanentFlags.ADMIN_CLUSTER_NODE_ARCHITECTURE.bindTo(nodeRepository.flagSource()).value()); + this.flagSource = nodeRepository.flagSource(); } public Capacity applyOn(Capacity capacity, ApplicationId application) { @@ -73,11 +76,16 @@ public class CapacityPolicies { return target; } - public NodeResources defaultNodeResources(ClusterSpec.Type clusterType) { + public NodeResources defaultNodeResources(ClusterSpec.Type clusterType, ApplicationId applicationId) { if (clusterType == ClusterSpec.Type.admin) { + Architecture architecture = Architecture.valueOf( + ADMIN_CLUSTER_NODE_ARCHITECTURE.bindTo(flagSource) + .with(APPLICATION_ID, applicationId.serializedForm()) + .value()); + return zone.getCloud().dynamicProvisioning() && ! sharedHosts.apply(clusterType) ? - new NodeResources(0.5, 4, 50, 0.3).with(architectureForAdminCluster) : - new NodeResources(0.5, 2, 50, 0.3).with(architectureForAdminCluster); + new NodeResources(0.5, 4, 50, 0.3).with(architecture) : + new NodeResources(0.5, 2, 50, 0.3).with(architecture); } return zone.getCloud().dynamicProvisioning() ? diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java index 9a7fa672cfc..e7332f6474d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java @@ -18,7 +18,7 @@ public class EmptyProvisionServiceProvider implements ProvisionServiceProvider { private final HostResourcesCalculator hostResourcesCalculator = new IdentityHostResourcesCalculator(); @Override - public Optional<LoadBalancerService> getLoadBalancerService(NodeRepository nodeRepository) { + public Optional<LoadBalancerService> getLoadBalancerService() { return Optional.empty(); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 97fe14caef6..e24d71f22f2 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -70,7 +70,7 @@ public class NodeRepositoryProvisioner implements Provisioner { this.allocationOptimizer = new AllocationOptimizer(nodeRepository); this.capacityPolicies = new CapacityPolicies(nodeRepository); this.zone = zone; - this.loadBalancerProvisioner = provisionServiceProvider.getLoadBalancerService(nodeRepository) + this.loadBalancerProvisioner = provisionServiceProvider.getLoadBalancerService() .map(lbService -> new LoadBalancerProvisioner(nodeRepository, lbService)); this.nodeResourceLimits = new NodeResourceLimits(nodeRepository); this.preparer = new Preparer(nodeRepository, @@ -106,14 +106,12 @@ public class NodeRepositoryProvisioner implements Provisioner { logIfDownscaled(requested.minResources().nodes(), actual.minResources().nodes(), cluster, logger); groups = target.groups(); - resources = target.nodeResources().isUnspecified() ? capacityPolicies.defaultNodeResources(cluster.type()) - : target.nodeResources(); + resources = getNodeResources(cluster, target.nodeResources(), application); nodeSpec = NodeSpec.from(target.nodes(), resources, exclusive, actual.canFail()); } else { groups = 1; // type request with multiple groups is not supported - resources = requested.minResources().nodeResources().isUnspecified() ? capacityPolicies.defaultNodeResources(cluster.type()) - : requested.minResources().nodeResources(); + resources = getNodeResources(cluster, requested.minResources().nodeResources(), application); nodeSpec = NodeSpec.from(requested.type()); } var reuseIndexes = Flags.REUSE_NODE_INDEXES.bindTo(nodeRepository.flagSource()) @@ -122,6 +120,12 @@ public class NodeRepositoryProvisioner implements Provisioner { return asSortedHosts(preparer.prepare(application, cluster, nodeSpec, groups, reuseIndexes), resources); } + private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId) { + return nodeResources.isUnspecified() + ? capacityPolicies.defaultNodeResources(cluster.type(), applicationId) + : nodeResources; + } + @Override public void activate(Collection<HostSpec> hosts, ActivationContext context, ApplicationTransaction transaction) { validate(hosts); @@ -170,16 +174,16 @@ public class NodeRepositoryProvisioner implements Provisioner { boolean firstDeployment = nodes.isEmpty(); AllocatableClusterResources currentResources = firstDeployment // start at min, preserve current resources otherwise - ? new AllocatableClusterResources(initialResourcesFrom(requested, clusterSpec), clusterSpec, nodeRepository) + ? new AllocatableClusterResources(initialResourcesFrom(requested, clusterSpec, application.id()), clusterSpec, nodeRepository) : new AllocatableClusterResources(nodes.asList(), nodeRepository); var clusterModel = new ClusterModel(application, cluster, clusterSpec, nodes, nodeRepository.metricsDb(), nodeRepository.clock()); return within(Limits.of(requested), currentResources, firstDeployment, clusterModel); } - private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec) { + private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec, ApplicationId applicationId) { var initial = requested.minResources(); if (initial.nodeResources().isUnspecified()) - initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec.type())); + initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec.type(), applicationId)); return initial; } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionServiceProvider.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionServiceProvider.java index c5835ec525a..6e301b7724c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionServiceProvider.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionServiceProvider.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.provisioning; -import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.lb.LoadBalancerService; import java.util.Optional; @@ -13,7 +12,7 @@ import java.util.Optional; */ public interface ProvisionServiceProvider { - Optional<LoadBalancerService> getLoadBalancerService(NodeRepository nodeRepository); + Optional<LoadBalancerService> getLoadBalancerService(); Optional<HostProvisioner> getHostProvisioner(); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisionServiceProvider.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisionServiceProvider.java index 9f6143e5daa..d72c5959082 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisionServiceProvider.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisionServiceProvider.java @@ -2,7 +2,6 @@ package com.yahoo.vespa.hosted.provision.testutils; import com.google.inject.Inject; -import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.lb.LoadBalancerService; import com.yahoo.vespa.hosted.provision.lb.LoadBalancerServiceMock; import com.yahoo.vespa.hosted.provision.provisioning.EmptyProvisionServiceProvider; @@ -38,7 +37,7 @@ public class MockProvisionServiceProvider implements ProvisionServiceProvider { } @Override - public Optional<LoadBalancerService> getLoadBalancerService(NodeRepository nodeRepository) { + public Optional<LoadBalancerService> getLoadBalancerService() { return loadBalancerService; } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java index a04a3828f13..40e38d752ff 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -15,7 +15,6 @@ import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.Nodelike; import com.yahoo.vespa.hosted.provision.provisioning.CapacityPolicies; @@ -240,7 +239,7 @@ public class AutoscalingTest { ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.container, "cluster1"); NodeResources defaultResources = - new CapacityPolicies(tester.nodeRepository()).defaultNodeResources(cluster1.type()); + new CapacityPolicies(tester.nodeRepository()).defaultNodeResources(cluster1.type(), application1); // deploy tester.deploy(application1, cluster1, Capacity.from(min, max)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java deleted file mode 100644 index 5fcc2afb85d..00000000000 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/PassthroughLoadBalancerServiceTest.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.lb; - -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.HostName; -import org.junit.Test; - -import java.util.Set; - -import static org.junit.Assert.assertEquals; - -/** - * @author mpolden - */ -public class PassthroughLoadBalancerServiceTest { - - @Test - public void create() { - var lbService = new PassthroughLoadBalancerService(); - var real = new Real(HostName.from("host1.example.com"), "192.0.2.10"); - var reals = Set.of(real, new Real(HostName.from("host2.example.com"), "192.0.2.11")); - var instance = lbService.create(new LoadBalancerSpec(ApplicationId.from("tenant1", "app1", "default"), - ClusterSpec.Id.from("c1"), reals), false); - assertEquals(real.hostname(), instance.hostname()); - assertEquals(Set.of(real.port()), instance.ports()); - assertEquals(Set.of(real.ipAddress() + "/32"), instance.networks()); - } - -} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java index 28b40bb7642..4975e670e86 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java @@ -4,8 +4,6 @@ package com.yahoo.vespa.hosted.provision.lb; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.HostName; -import com.yahoo.config.provision.NodeType; -import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; import org.junit.Test; import java.util.Optional; @@ -18,8 +16,7 @@ import static org.junit.Assert.assertEquals; */ public class SharedLoadBalancerServiceTest { - private final ProvisioningTester tester = new ProvisioningTester.Builder().build(); - private final SharedLoadBalancerService loadBalancerService = new SharedLoadBalancerService(tester.nodeRepository(), "vip.example.com"); + private final SharedLoadBalancerService loadBalancerService = new SharedLoadBalancerService("vip.example.com"); private final ApplicationId applicationId = ApplicationId.from("tenant1", "application1", "default"); private final ClusterSpec.Id clusterId = ClusterSpec.Id.from("qrs1"); private final Set<Real> reals = Set.of( @@ -29,18 +26,12 @@ public class SharedLoadBalancerServiceTest { @Test public void test_create_lb() { - tester.makeReadyNodes(2, "default", NodeType.proxy); var lb = loadBalancerService.create(new LoadBalancerSpec(applicationId, clusterId, reals), false); assertEquals(HostName.from("vip.example.com"), lb.hostname()); assertEquals(Optional.empty(), lb.dnsZone()); - assertEquals(Set.of("127.0.0.1/32", "127.0.0.2/32", "::1/128", "::2/128"), lb.networks()); - assertEquals(Set.of(4080, 4443), lb.ports()); - } - - @Test(expected = IllegalStateException.class) - public void test_exception_on_missing_proxies() { - loadBalancerService.create(new LoadBalancerSpec(applicationId, clusterId, reals), false); + assertEquals(Set.of(), lb.networks()); + assertEquals(Set.of(4443), lb.ports()); } @Test diff --git a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp index 1c779be18be..c0c6f729509 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp @@ -110,13 +110,6 @@ makeArray(const FieldPathEntry &fieldPathEntry, size_t size) return array; } -bool -checkInherits(const FieldValue &fieldValue, unsigned id) -{ - const vespalib::Identifiable::RuntimeClass &rc = fieldValue.getClass(); - return rc.inherits(id); -} - } DocumentFieldExtractor::DocumentFieldExtractor(const Document &doc) @@ -176,7 +169,7 @@ template <typename ExtractorFunc> std::unique_ptr<FieldValue> extractFieldFromMap(const FieldValue *outerFieldValue, const FieldPathEntry &innerEntry, ExtractorFunc &&extractor) { - if (outerFieldValue != nullptr && checkInherits(*outerFieldValue, MapFieldValue::classId)) { + if (outerFieldValue && outerFieldValue->isA(FieldValue::Type::MAP)) { const auto outerMap = static_cast<const MapFieldValue *>(outerFieldValue); auto array = makeArray(innerEntry, outerMap->size()); uint32_t arrayIndex = 0; @@ -190,9 +183,9 @@ extractFieldFromMap(const FieldValue *outerFieldValue, const FieldPathEntry &inn template <typename CollectionFieldValueT, typename ExtractorFunc> std::unique_ptr<FieldValue> -extractFieldFromStructCollection(const FieldValue *outerFieldValue, const FieldPathEntry &innerEntry, ExtractorFunc &&extractor) +extractFieldFromStructCollection(const FieldValue *outerFieldValue, FieldValue::Type expectedType, const FieldPathEntry &innerEntry, ExtractorFunc &&extractor) { - if (outerFieldValue != nullptr && checkInherits(*outerFieldValue, CollectionFieldValueT::classId)) { + if (outerFieldValue && outerFieldValue->isA(expectedType)) { const auto *outerCollection = static_cast<const CollectionFieldValueT *>(outerFieldValue); auto array = makeArray(innerEntry, outerCollection->size()); uint32_t arrayIndex = 0; @@ -213,7 +206,7 @@ extractFieldFromStructCollection(const FieldValue *outerFieldValue, const FieldP std::unique_ptr<FieldValue> DocumentFieldExtractor::extractFieldFromStructArray(const FieldPath &fieldPath) { - return extractFieldFromStructCollection<ArrayFieldValue>(getCachedFieldValue(fieldPath[0]), fieldPath[1], + return extractFieldFromStructCollection<ArrayFieldValue>(getCachedFieldValue(fieldPath[0]), FieldValue::Type::ARRAY, fieldPath[1], [](const auto *elem){ return elem; }); } @@ -234,7 +227,7 @@ DocumentFieldExtractor::extractValueFieldFromPrimitiveMap(const FieldPath &field std::unique_ptr<document::FieldValue> DocumentFieldExtractor::extractValueFieldFromStructMap(const FieldPath &fieldPath) { - return extractFieldFromStructCollection<MapFieldValue>(getCachedFieldValue(fieldPath[0]), fieldPath[2], + return extractFieldFromStructCollection<MapFieldValue>(getCachedFieldValue(fieldPath[0]), FieldValue::Type::MAP, fieldPath[2], [](const auto *elem){ return elem->second; }); } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/document_field_retriever.cpp b/searchcore/src/vespa/searchcore/proton/attribute/document_field_retriever.cpp index 00d84e795c7..cf543f1ba17 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/document_field_retriever.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/document_field_retriever.cpp @@ -58,7 +58,7 @@ setValue(DocumentIdT lid, Document &doc, const document::Field & field, const IA break; } FieldValue::UP fv = field.getDataType().createFieldValue(); - if (fv.get() && fv->getClass().id() != ArrayFieldValue::classId) { + if (fv && ! fv->isA(FieldValue::Type::ARRAY)) { throw IllegalStateException("Field " + field.getName() + " does not contain an array.", VESPA_STRLOC); } ArrayFieldValue &array = static_cast<ArrayFieldValue &>(*fv.get()); @@ -78,7 +78,7 @@ setValue(DocumentIdT lid, Document &doc, const document::Field & field, const IA break; } FieldValue::UP fv = field.getDataType().createFieldValue(); - if (fv.get() && fv->getClass().id() != WeightedSetFieldValue::classId) { + if (fv && ! fv->isA(FieldValue::Type::WSET)) { throw IllegalStateException("Field " + field.getName() + " does not contain a wset.", VESPA_STRLOC); } WeightedSetFieldValue & wset(static_cast<WeightedSetFieldValue &>(*fv.get())); diff --git a/searchcore/src/vespa/searchcore/proton/common/attribute_updater.cpp b/searchcore/src/vespa/searchcore/proton/common/attribute_updater.cpp index 9c7b4bbb4b7..5b134c65e84 100644 --- a/searchcore/src/vespa/searchcore/proton/common/attribute_updater.cpp +++ b/searchcore/src/vespa/searchcore/proton/common/attribute_updater.cpp @@ -136,16 +136,15 @@ AttributeUpdater::handleUpdateT(V & vec, Accessor, uint32_t lid, const ValueUpda const AssignValueUpdate & assign(static_cast<const AssignValueUpdate &>(upd)); if (assign.hasValue()) { const FieldValue & fv(assign.getValue()); - const vespalib::Identifiable::RuntimeClass & rc(fv.getClass()); - if (rc.inherits(ArrayFieldValue::classId)) { + if (fv.isA(FieldValue::Type::ARRAY)) { ArrayAccessor<Accessor> ac(static_cast<const ArrayFieldValue & >(fv)); appendValue(vec, lid, ac); - } else if (rc.inherits(WeightedSetFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::WSET)) { WeightedSetAccessor<Accessor> ac(static_cast<const WeightedSetFieldValue & >(fv)); appendValue(vec, lid, ac); } else { LOG(warning, "Unsupported value %s in assign operation on multivalue vector %s", - rc.name(), vec.getName().c_str()); + fv.className(), vec.getName().c_str()); } } } else if (op == ValueUpdate::Add) { @@ -158,7 +157,7 @@ AttributeUpdater::handleUpdateT(V & vec, Accessor, uint32_t lid, const ValueUpda const MapValueUpdate & map(static_cast<const MapValueUpdate &>(upd)); if (!vec.AttributeVector::apply(lid, map)) { throw UpdateException(make_string("attribute map(%s, %s) failed: %s[%u]", - map.getKey().getClass().name(), map.getUpdate().getClass().name(), + map.getKey().className(), map.getUpdate().getClass().name(), vec.getName().c_str(), lid)); } } else { @@ -323,15 +322,14 @@ AttributeUpdater::handleValueT(V & vec, Accessor, uint32_t lid, const FieldValue { if (vec.hasMultiValue()) { vec.clearDoc(lid); - const vespalib::Identifiable::RuntimeClass & rc = val.getClass(); - if (rc.inherits(ArrayFieldValue::classId)) { + if (val.isA(FieldValue::Type::ARRAY)) { ArrayAccessor<Accessor> ac(static_cast<const ArrayFieldValue & >(val)); appendValue(vec, lid, ac); - } else if (rc.inherits(WeightedSetFieldValue::classId)) { + } else if (val.isA(FieldValue::Type::WSET)) { WeightedSetAccessor<Accessor> ac(static_cast<const WeightedSetFieldValue & >(val)); appendValue(vec, lid, ac); } else { - LOG(warning, "Unsupported value '%s' to assign on multivalue vector '%s'", rc.name(), vec.getName().c_str()); + LOG(warning, "Unsupported value '%s' to assign on multivalue vector '%s'", val.className(), vec.getName().c_str()); } } else { updateValue(vec, lid, val); @@ -412,7 +410,7 @@ namespace { const vespalib::string & getString(const search::StringAttribute & attr, uint32_t lid, const FieldValue & val) { - if ( ! val.inherits(LiteralFieldValueB::classId) ) { + if ( ! val.isLiteral() ) { throw UpdateException(make_string("Can not update a string attribute '%s' for lid=%d from a non-literal fieldvalue: %s", attr.getName().c_str(), lid, val.toString().c_str())); } @@ -453,11 +451,10 @@ AttributeUpdater::updateValue(StringAttribute & vec, uint32_t lid, const FieldVa namespace { -template <typename ExpFieldValueType> void -validate_field_value_type(const FieldValue& val, const vespalib::string& attr_type, const vespalib::string& value_type) +validate_field_value_type(FieldValue::Type expectedType, const FieldValue& val, const vespalib::string& attr_type, const vespalib::string& value_type) { - if (!val.inherits(ExpFieldValueType::classId)) { + if (!val.isA(expectedType)) { throw UpdateException( make_string("%s must be updated with %s, but was '%s'", attr_type.c_str(), value_type.c_str(), val.toString(false).c_str())); @@ -469,14 +466,14 @@ validate_field_value_type(const FieldValue& val, const vespalib::string& attr_ty void AttributeUpdater::updateValue(PredicateAttribute &vec, uint32_t lid, const FieldValue &val) { - validate_field_value_type<PredicateFieldValue>(val, "PredicateAttribute", "PredicateFieldValue"); + validate_field_value_type(FieldValue::Type::PREDICATE, val, "PredicateAttribute", "PredicateFieldValue"); vec.updateValue(lid, static_cast<const PredicateFieldValue &>(val)); } void AttributeUpdater::updateValue(TensorAttribute &vec, uint32_t lid, const FieldValue &val) { - validate_field_value_type<TensorFieldValue>(val, "TensorAttribute", "TensorFieldValue"); + validate_field_value_type(FieldValue::Type::TENSOR, val, "TensorAttribute", "TensorFieldValue"); const auto &tensor = static_cast<const TensorFieldValue &>(val).getAsTensorPtr(); if (tensor) { vec.setTensor(lid, *tensor); @@ -488,7 +485,7 @@ AttributeUpdater::updateValue(TensorAttribute &vec, uint32_t lid, const FieldVal void AttributeUpdater::updateValue(ReferenceAttribute &vec, uint32_t lid, const FieldValue &val) { - if (!val.inherits(ReferenceFieldValue::classId)) { + if (!val.isA(FieldValue::Type::REFERENCE)) { vec.clearDoc(lid); throw UpdateException( make_string("ReferenceAttribute must be updated with " @@ -518,7 +515,7 @@ validate_tensor_attribute_type(AttributeVector& attr) std::unique_ptr<PrepareResult> prepare_set_tensor(TensorAttribute& attr, uint32_t docid, const FieldValue& val) { - validate_field_value_type<TensorFieldValue>(val, "TensorAttribute", "TensorFieldValue"); + validate_field_value_type(FieldValue::Type::TENSOR, val, "TensorAttribute", "TensorFieldValue"); const auto& tensor = static_cast<const TensorFieldValue&>(val).getAsTensorPtr(); if (tensor) { return attr.prepare_set_tensor(docid, *tensor); @@ -529,7 +526,7 @@ prepare_set_tensor(TensorAttribute& attr, uint32_t docid, const FieldValue& val) void complete_set_tensor(TensorAttribute& attr, uint32_t docid, const FieldValue& val, std::unique_ptr<PrepareResult> prepare_result) { - validate_field_value_type<TensorFieldValue>(val, "TensorAttribute", "TensorFieldValue"); + validate_field_value_type(FieldValue::Type::TENSOR, val, "TensorAttribute", "TensorFieldValue"); const auto& tensor = static_cast<const TensorFieldValue&>(val).getAsTensorPtr(); if (tensor) { attr.complete_set_tensor(docid, *tensor, std::move(prepare_result)); diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp index 1342324b727..3550b38383a 100644 --- a/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp +++ b/searchcore/src/vespa/searchcore/proton/docsummary/documentstoreadapter.cpp @@ -58,7 +58,7 @@ DocumentStoreAdapter::writeField(const FieldValue &value, ResType type) case RES_LONG_STRING: case RES_JSONSTRING: { - if (value.getClass().inherits(LiteralFieldValueB::classId)) { + if (value.isLiteral()) { auto & lfv = static_cast<const LiteralFieldValueB &>(value); vespalib::stringref s = lfv.getValueRef(); return writeStringField(s.data(), s.size(), type); @@ -80,7 +80,7 @@ DocumentStoreAdapter::writeField(const FieldValue &value, ResType type) case RES_TENSOR: { vespalib::nbostream serialized; - if (value.getClass().inherits(TensorFieldValue::classId)) { + if (value.isA(FieldValue::Type::TENSOR)) { const auto &tvalue = static_cast<const TensorFieldValue &>(value); auto tensor = tvalue.getAsTensorPtr(); if (tensor) { diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleValue.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleValue.java index 6154b5ea76c..d8443cfd1ef 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleValue.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleValue.java @@ -129,8 +129,8 @@ public final class DoubleValue extends DoubleCompatibleValue { /** Returns this or a mutable copy assigned the given value */ private DoubleValue mutable(double value) { - DoubleValue mutable=this.asMutable(); - mutable.value=value; + DoubleValue mutable = this.asMutable(); + mutable.value = value; return mutable; } @@ -147,7 +147,7 @@ public final class DoubleValue extends DoubleCompatibleValue { @Override public boolean equals(Object other) { - if (this==other) return true; + if (this == other) return true; if ( ! (other instanceof Value)) return false; if ( ! ((Value) other).hasDouble()) return false; return this.asDouble() == ((Value) other).asDouble(); diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TruthOperator.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TruthOperator.java index 6f264903122..fc259867923 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TruthOperator.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TruthOperator.java @@ -21,7 +21,7 @@ public enum TruthOperator implements Serializable { private final String operatorString; TruthOperator(String operatorString) { - this.operatorString=operatorString; + this.operatorString = operatorString; } /** Perform the truth operation on the input */ diff --git a/searchlib/src/tests/tensor/hnsw_saver/hnsw_save_load_test.cpp b/searchlib/src/tests/tensor/hnsw_saver/hnsw_save_load_test.cpp index 43ff6f5b83b..add7801e03a 100644 --- a/searchlib/src/tests/tensor/hnsw_saver/hnsw_save_load_test.cpp +++ b/searchlib/src/tests/tensor/hnsw_saver/hnsw_save_load_test.cpp @@ -89,13 +89,13 @@ public: HnswGraph copy; void expect_empty_d(uint32_t docid) const { - EXPECT_FALSE(copy.node_refs[docid].load_acquire().valid()); + EXPECT_FALSE(copy.acquire_node_ref(docid).valid()); } void expect_level_0(uint32_t docid, const V& exp_links) const { - auto levels = copy.get_level_array(docid); + auto levels = copy.acquire_level_array(docid); EXPECT_GE(levels.size(), 1); - auto links = copy.get_link_array(docid, 0); + auto links = copy.acquire_link_array(docid, 0); EXPECT_EQ(exp_links.size(), links.size()); for (size_t i = 0; i < exp_links.size() && i < links.size(); ++i) { EXPECT_EQ(exp_links[i], links[i]); @@ -103,9 +103,9 @@ public: } void expect_level_1(uint32_t docid, const V& exp_links) const { - auto levels = copy.get_level_array(docid); + auto levels = copy.acquire_level_array(docid); EXPECT_EQ(2, levels.size()); - auto links = copy.get_link_array(docid, 1); + auto links = copy.acquire_link_array(docid, 1); EXPECT_EQ(exp_links.size(), links.size()); for (size_t i = 0; i < exp_links.size() && i < links.size(); ++i) { EXPECT_EQ(exp_links[i], links[i]); diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.hpp b/searchlib/src/vespa/searchlib/attribute/attributevector.hpp index 623e10ef052..c75f7788467 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributevector.hpp +++ b/searchlib/src/vespa/searchlib/attribute/attributevector.hpp @@ -10,23 +10,6 @@ namespace search { -template <typename T> -inline bool myIsNan(T v) { (void)v; return false; } - -template <> -inline bool -myIsNan<float>(float v) -{ - return std::isnan(v); -} - -template <> -inline bool -myIsNan<double>(double v) -{ - return std::isnan(v); -} - template<typename T> bool AttributeVector::adjustWeight(ChangeVectorT< ChangeTemplate<T> > & changes, DocId doc, const T & v, @@ -70,7 +53,7 @@ AttributeVector::adjustWeight(ChangeVectorT< ChangeTemplate<T> >& changes, DocId size_t oldSz(changes.size()); if (wu.hasValue()) { const FieldValue &wv = wu.getValue(); - if (wv.inherits(document::IntFieldValue::classId)) { + if (wv.isA(FieldValue::Type::INT)) { changes.push_back(ChangeTemplate<T>(ChangeBase::SETWEIGHT, doc, v, wv.getAsInt())); } else { retval = false; diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp index df3d2e5b19b..91e5a36a7cf 100644 --- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp +++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp @@ -29,11 +29,12 @@ DocumentFieldNode::DocumentFieldNode(const DocumentFieldNode & rhs) : _fieldPath(rhs._fieldPath), _value(rhs._value), _fieldName(rhs._fieldName), - _doc(NULL) + _doc(nullptr) { } -DocumentFieldNode & DocumentFieldNode::operator = (const DocumentFieldNode & rhs) +DocumentFieldNode & +DocumentFieldNode::operator = (const DocumentFieldNode & rhs) { if (this != &rhs) { DocumentAccessorNode::operator=(rhs); @@ -49,12 +50,11 @@ std::unique_ptr<ResultNode> deduceResultNode(vespalib::stringref fieldName, const FieldValue & fv, bool preserveAccurateTypes, bool nestedMultiValue) { std::unique_ptr<ResultNode> value; - const Identifiable::RuntimeClass & cInfo = fv.getClass(); - if (cInfo.inherits(ByteFieldValue::classId) || cInfo.inherits(IntFieldValue::classId) || cInfo.inherits(LongFieldValue::classId)) { + if (fv.isA(FieldValue::Type::BYTE) || fv.isA(FieldValue::Type::INT) || fv.isA(FieldValue::Type::LONG)) { if (preserveAccurateTypes) { - if (cInfo.inherits(ByteFieldValue::classId)) { + if (fv.isA(FieldValue::Type::BYTE)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new Int8ResultNodeVector()) : static_cast<ResultNode *>(new Int8ResultNode())); - } else if (cInfo.inherits(IntFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::INT)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new Int32ResultNodeVector()) : static_cast<ResultNode *>(new Int32ResultNode())); } else { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new Int64ResultNodeVector()) : static_cast<ResultNode *>(new Int64ResultNode())); @@ -62,22 +62,20 @@ deduceResultNode(vespalib::stringref fieldName, const FieldValue & fv, bool pres } else { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new Int64ResultNodeVector()) : static_cast<ResultNode *>(new Int64ResultNode())); } - } else if (cInfo.inherits(FloatFieldValue::classId) || cInfo.inherits(DoubleFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::FLOAT) || fv.isA(FieldValue::Type::DOUBLE)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new FloatResultNodeVector()) : static_cast<ResultNode *>(new FloatResultNode())); - } else if (cInfo.inherits(BoolFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::BOOL)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new BoolResultNodeVector()) : static_cast<ResultNode *>(new BoolResultNode())); - } else if (cInfo.inherits(StringFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::STRING)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new StringResultNodeVector()) : static_cast<ResultNode *>(new StringResultNode())); - } else if (cInfo.inherits(RawFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::RAW)) { value.reset(nestedMultiValue ? static_cast<ResultNode *>(new RawResultNodeVector()) : static_cast<ResultNode *>(new RawResultNode())); - } else if (cInfo.inherits(CollectionFieldValue::classId) || cInfo.inherits(MapFieldValue::classId)) { - if (cInfo.inherits(CollectionFieldValue::classId)) { + } else if (fv.isCollection() || fv.isA(FieldValue::Type::MAP)) { + if (fv.isCollection()) { value = deduceResultNode(fieldName, *static_cast<const CollectionFieldValue &>(fv).createNested(), preserveAccurateTypes, nestedMultiValue); - } else if (cInfo.inherits(MapFieldValue::classId)) { - value = deduceResultNode(fieldName, *static_cast<const MapFieldValue &>(fv).createValue(), preserveAccurateTypes, nestedMultiValue); } else { - throw std::runtime_error(make_string("Can not deduce correct resultclass for documentfield '%s' in based on class '%s'", - vespalib::string(fieldName).c_str(), cInfo.name())); + assert(fv.isA(FieldValue::Type::MAP)); + value = deduceResultNode(fieldName, *static_cast<const MapFieldValue &>(fv).createValue(), preserveAccurateTypes, nestedMultiValue); } const Identifiable::RuntimeClass & rInfo = value->getClass(); if (rInfo.inherits(ResultNodeVector::classId)) { @@ -100,16 +98,17 @@ deduceResultNode(vespalib::stringref fieldName, const FieldValue & fv, bool pres value.reset(new RawResultNodeVector()); } else { throw std::runtime_error(make_string("Can not deduce correct resultclass for documentfield '%s' in based on class '%s'. It nests down to %s which is not expected", - vespalib::string(fieldName).c_str(), cInfo.name(), rInfo.name())); + vespalib::string(fieldName).c_str(), fv.className(), rInfo.name())); } } else { throw std::runtime_error(make_string("Can not deduce correct resultclass for documentfield '%s' in based on class '%s'", - vespalib::string(fieldName).c_str(), cInfo.name())); + vespalib::string(fieldName).c_str(), fv.className())); } return value; } -void DocumentFieldNode::onPrepare(bool preserveAccurateTypes) +void +DocumentFieldNode::onPrepare(bool preserveAccurateTypes) { LOG(debug, "DocumentFieldNode::onPrepare(this=%p)", this); @@ -118,8 +117,8 @@ void DocumentFieldNode::onPrepare(bool preserveAccurateTypes) for(document::FieldPath::const_iterator it(_fieldPath.begin()), mt(_fieldPath.end()); !nestedMultiValue && (it != mt); it++) { const FieldPathEntry & fpe = **it; if (fpe.getType() == document::FieldPathEntry::STRUCT_FIELD) { - const vespalib::Identifiable::RuntimeClass & cInfo(fpe.getFieldValueToSet().getClass()); - nestedMultiValue = cInfo.inherits(CollectionFieldValue::classId) || cInfo.inherits(MapFieldValue::classId); + const FieldValue & fv = fpe.getFieldValueToSet(); + nestedMultiValue = fv.isCollection() || fv.isA(FieldValue::Type::MAP); } } const document::FieldPathEntry & endOfPath(_fieldPath.back()); @@ -127,9 +126,9 @@ void DocumentFieldNode::onPrepare(bool preserveAccurateTypes) const FieldValue& fv = endOfPath.getFieldValueToSet(); _value.reset(deduceResultNode(_fieldName, fv, preserveAccurateTypes, nestedMultiValue).release()); if (_value->inherits(ResultNodeVector::classId)) { - _handler.reset(new MultiHandler(static_cast<ResultNodeVector &>(*_value))); + _handler = std::make_unique<MultiHandler>(static_cast<ResultNodeVector &>(*_value)); } else { - _handler.reset(new SingleHandler(*_value)); + _handler = std::make_unique<SingleHandler>(*_value); } } else { if (endOfPath.getDataType().isStructured()) { @@ -222,10 +221,10 @@ DocumentFieldNode::Handler::onCollectionStart(const Content & c) { const document::FieldValue & fv = c.getValue(); LOG(spam, "onCollectionStart: field value '%s'", fv.toString().c_str()); - if (fv.inherits(document::ArrayFieldValue::classId)) { + if (fv.isA(FieldValue::Type::ARRAY)) { const document::ArrayFieldValue & afv = static_cast<const document::ArrayFieldValue &>(fv); LOG(spam, "onCollectionStart: Array size = '%zu'", afv.size()); - } else if (fv.inherits(document::WeightedSetFieldValue::classId)) { + } else if (fv.isA(FieldValue::Type::WSET)) { const document::WeightedSetFieldValue & wsfv = static_cast<const document::WeightedSetFieldValue &>(fv); LOG(spam, "onCollectionStart: WeightedSet size = '%zu'", wsfv.size()); } @@ -253,9 +252,6 @@ DocumentFieldNode::visitMembers(vespalib::ObjectVisitor &visitor) const { visit(visitor, "fieldName", _fieldName); visit(visitor, "value", _value); - visitor.openStruct("fieldPath", "FieldPath"); - _fieldPath.visitMembers(visitor); - visitor.closeStruct(); } class String2ResultNode : public ResultNode diff --git a/searchlib/src/vespa/searchlib/memoryindex/field_inverter.cpp b/searchlib/src/vespa/searchlib/memoryindex/field_inverter.cpp index a443e994559..5a7d0e60153 100644 --- a/searchlib/src/vespa/searchlib/memoryindex/field_inverter.cpp +++ b/searchlib/src/vespa/searchlib/memoryindex/field_inverter.cpp @@ -271,7 +271,7 @@ FieldInverter::saveWord(const vespalib::stringref word) uint32_t FieldInverter::saveWord(const document::FieldValue &fv) { - assert(fv.getClass().id() == StringFieldValue::classId); + assert(fv.isA(FieldValue::Type::STRING)); using RawRef = std::pair<const char*, size_t>; RawRef sRef = fv.getAsRaw(); return saveWord(vespalib::stringref(sRef.first, sRef.second)); @@ -303,8 +303,7 @@ FieldInverter::endDoc() } _calculator.add_field_length(field_length); uint32_t newPosSize = static_cast<uint32_t>(_positions.size()); - _pendingDocs.insert({ _docId, - { _oldPosSize, newPosSize - _oldPosSize } }); + _pendingDocs.insert({ _docId, { _oldPosSize, newPosSize - _oldPosSize } }); _docId = 0; _oldPosSize = newPosSize; } @@ -324,7 +323,7 @@ FieldInverter::processNormalDocArrayTextField(const ArrayFieldValue &field) uint32_t ele = field.size(); for (;el < ele; ++el) { const FieldValue &elfv = field[el]; - assert(elfv.getClass().id() == StringFieldValue::classId); + assert(elfv.isA(FieldValue::Type::STRING)); const auto &element = static_cast<const StringFieldValue &>(elfv); startElement(1); processAnnotations(element); @@ -338,8 +337,8 @@ FieldInverter::processNormalDocWeightedSetTextField(const WeightedSetFieldValue for (const auto & el : field) { const FieldValue &key = *el.first; const FieldValue &xweight = *el.second; - assert(key.getClass().id() == StringFieldValue::classId); - assert(xweight.getClass().id() == IntFieldValue::classId); + assert(key.isA(FieldValue::Type::STRING)); + assert(xweight.isA(FieldValue::Type::INT)); const auto &element = static_cast<const StringFieldValue &>(key); int32_t weight = xweight.getAsInt(); startElement(weight); @@ -457,18 +456,17 @@ FieldInverter::startDoc(uint32_t docId) { void FieldInverter::invertNormalDocTextField(const FieldValue &val) { - const vespalib::Identifiable::RuntimeClass & cInfo(val.getClass()); const Schema::IndexField &field = _schema.getIndexField(_fieldId); switch (field.getCollectionType()) { case CollectionType::SINGLE: - if (cInfo.id() == StringFieldValue::classId) { + if (val.isA(FieldValue::Type::STRING)) { processNormalDocTextField(static_cast<const StringFieldValue &>(val)); } else { throw std::runtime_error(make_string("Expected DataType::STRING, got '%s'", val.getDataType()->getName().c_str())); } break; case CollectionType::WEIGHTEDSET: - if (cInfo.id() == WeightedSetFieldValue::classId) { + if (val.isA(FieldValue::Type::WSET)) { const auto &wset = static_cast<const WeightedSetFieldValue &>(val); if (wset.getNestedType() == *DataType::STRING) { processNormalDocWeightedSetTextField(wset); @@ -476,11 +474,11 @@ FieldInverter::invertNormalDocTextField(const FieldValue &val) throw std::runtime_error(make_string("Expected DataType::STRING, got '%s'", wset.getNestedType().getName().c_str())); } } else { - throw std::runtime_error(make_string("Expected weighted set, got '%s'", cInfo.name())); + throw std::runtime_error(make_string("Expected weighted set, got '%s'", val.className())); } break; case CollectionType::ARRAY: - if (cInfo.id() == ArrayFieldValue::classId) { + if (val.isA(FieldValue::Type::ARRAY)) { const auto &arr = static_cast<const ArrayFieldValue&>(val); if (arr.getNestedType() == *DataType::STRING) { processNormalDocArrayTextField(arr); @@ -488,7 +486,7 @@ FieldInverter::invertNormalDocTextField(const FieldValue &val) throw std::runtime_error(make_string("Expected DataType::STRING, got '%s'", arr.getNestedType().getName().c_str())); } } else { - throw std::runtime_error(make_string("Expected Array, got '%s'", cInfo.name())); + throw std::runtime_error(make_string("Expected Array, got '%s'", val.className())); } break; default: diff --git a/searchlib/src/vespa/searchlib/memoryindex/url_field_inverter.cpp b/searchlib/src/vespa/searchlib/memoryindex/url_field_inverter.cpp index 326b7b0967a..87bcdd31933 100644 --- a/searchlib/src/vespa/searchlib/memoryindex/url_field_inverter.cpp +++ b/searchlib/src/vespa/searchlib/memoryindex/url_field_inverter.cpp @@ -6,7 +6,6 @@ #include <vespa/document/fieldvalue/arrayfieldvalue.h> #include <vespa/document/fieldvalue/stringfieldvalue.h> #include <vespa/document/fieldvalue/weightedsetfieldvalue.h> -#include <vespa/searchlib/common/sort.h> #include <vespa/searchlib/util/url.h> #include <vespa/vespalib/text/lowercase.h> #include <vespa/vespalib/text/utf8.h> @@ -122,7 +121,7 @@ UrlFieldInverter::processUrlSubField(FieldInverter *inverter, if (!sfv) { return; } - if (!sfv->inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) { + if (!sfv->isA(FieldValue::Type::STRING)) { LOG(error, "Illegal field type %s for URL subfield %s, expected string", sfv->getDataType()->getName().c_str(), @@ -155,13 +154,13 @@ UrlFieldInverter::processAnnotatedUrlField(const StructFieldValue & field) void UrlFieldInverter::processUrlField(const FieldValue &url_field) { - if (url_field.inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) { + if (url_field.isA(FieldValue::Type::STRING)) { const vespalib::string &url_str = static_cast<const StringFieldValue &>(url_field).getValue(); processUrlOldStyle(url_str); return; } - assert(url_field.getClass().id() == StructFieldValue::classId); + assert(url_field.isA(FieldValue::Type::STRUCT)); const auto &field = static_cast<const StructFieldValue &>(url_field); const FieldValue::UP all_val = field.getValue("all"); @@ -173,7 +172,7 @@ UrlFieldInverter::processUrlField(const FieldValue &url_field) return; } - if (!all_val->inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) { + if (!all_val->isA(FieldValue::Type::STRING)) { LOG(error, "Illegal field type %s for URL subfield all, expected string", all_val->getDataType()->getName().c_str()); @@ -275,7 +274,7 @@ UrlFieldInverter::processWeightedSetUrlField(const WeightedSetFieldValue &field) for (const auto & el : field) { const FieldValue &key = *el.first; const FieldValue &xweight = *el.second; - assert(xweight.getClass().id() == IntFieldValue::classId); + assert(xweight.isA(FieldValue::Type::INT)); int32_t weight = xweight.getAsInt(); startElement(weight); processUrlField(key); @@ -298,7 +297,6 @@ isUriType(const DataType &type) void UrlFieldInverter::invertUrlField(const FieldValue &val) { - const vespalib::Identifiable::RuntimeClass & cInfo(val.getClass()); switch (_collectionType) { case CollectionType::SINGLE: if (isUriType(*val.getDataType())) { @@ -309,30 +307,29 @@ UrlFieldInverter::invertUrlField(const FieldValue &val) throw std::runtime_error(make_string("Expected URI struct, got '%s'", val.getDataType()->getName().c_str())); } break; - case CollectionType::WEIGHTEDSET: - if (cInfo.id() == WeightedSetFieldValue::classId) { - const auto &wset = static_cast<const WeightedSetFieldValue &>(val); - if (isUriType(wset.getNestedType())) { - processWeightedSetUrlField(wset); - } else { - throw std::runtime_error(make_string("Expected wset of URI struct, got '%s'", wset.getNestedType().getName().c_str())); - } + case CollectionType::WEIGHTEDSET: { + assert(val.isA(FieldValue::Type::WSET)); + const auto &wset = static_cast<const WeightedSetFieldValue &>(val); + if (isUriType(wset.getNestedType())) { + processWeightedSetUrlField(wset); } else { - throw std::runtime_error(make_string("Expected weighted set, got '%s'", cInfo.name())); + throw std::runtime_error( + make_string("Expected wset of URI struct, got '%s'", wset.getNestedType().getName().c_str())); } break; - case CollectionType::ARRAY: - if (cInfo.id() == ArrayFieldValue::classId) { - const auto &arr = static_cast<const ArrayFieldValue&>(val); - if (isUriType(arr.getNestedType())) { - processArrayUrlField(arr); - } else { - throw std::runtime_error(make_string("Expected array of URI struct, got '%s' (%s)", arr.getNestedType().getName().c_str(), arr.getNestedType().toString(true).c_str())); - } + } + case CollectionType::ARRAY: { + assert(val.isA(FieldValue::Type::ARRAY)); + const auto &arr = static_cast<const ArrayFieldValue &>(val); + if (isUriType(arr.getNestedType())) { + processArrayUrlField(arr); } else { - throw std::runtime_error(make_string("Expected Array, got '%s'", cInfo.name())); + throw std::runtime_error( + make_string("Expected array of URI struct, got '%s' (%s)", arr.getNestedType().getName().c_str(), + arr.getNestedType().toString(true).c_str())); } break; + } default: break; } diff --git a/searchlib/src/vespa/searchlib/parsequery/parse.h b/searchlib/src/vespa/searchlib/parsequery/parse.h index c9b7940b887..34ea692c370 100644 --- a/searchlib/src/vespa/searchlib/parsequery/parse.h +++ b/searchlib/src/vespa/searchlib/parsequery/parse.h @@ -33,7 +33,7 @@ public: ITEM_TERM = 4, ITEM_NUMTERM = 5, ITEM_PHRASE = 6, - /* removed: ITEM_PAREN = 7, */ + ITEM_MULTI_TERM = 7, ITEM_PREFIXTERM = 8, ITEM_SUBSTRINGTERM = 9, ITEM_ANY = 10, @@ -56,7 +56,7 @@ public: ITEM_GEO_LOCATION_TERM = 27, ITEM_TRUE = 28, ITEM_FALSE = 29, - ITEM_MULTI_TERM = 30, + ITEM_MAX = 30, // Indicates how long tables must be. ITEM_UNDEF = 31, }; diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp index 8beb111ca59..3049b643709 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp @@ -26,7 +26,7 @@ HnswGraph::make_node_for_document(uint32_t docid, uint32_t num_levels) { node_refs.ensure_size(docid + 1, AtomicEntryRef()); // A document cannot be added twice. - assert(!node_refs[docid].load_acquire().valid()); + assert(!get_node_ref(docid).valid()); // Note: The level array instance lives as long as the document is present in the index. vespalib::Array<AtomicEntryRef> levels(num_levels, AtomicEntryRef()); auto node_ref = nodes.add(levels); @@ -40,7 +40,7 @@ HnswGraph::make_node_for_document(uint32_t docid, uint32_t num_levels) void HnswGraph::remove_node_for_document(uint32_t docid) { - auto node_ref = node_refs[docid].load_acquire(); + auto node_ref = get_node_ref(docid); assert(node_ref.valid()); auto levels = nodes.get(node_ref); vespalib::datastore::EntryRef invalid; @@ -48,7 +48,7 @@ HnswGraph::remove_node_for_document(uint32_t docid) // Ensure data referenced through the old ref can be recycled: nodes.remove(node_ref); for (size_t i = 0; i < levels.size(); ++i) { - auto old_links_ref = levels[i].load_acquire(); + auto old_links_ref = levels[i].load_relaxed(); links.remove(old_links_ref); } if (docid + 1 == node_refs_size.load(std::memory_order_relaxed)) { @@ -60,7 +60,7 @@ void HnswGraph::trim_node_refs_size() { uint32_t check_doc_id = node_refs_size.load(std::memory_order_relaxed) - 1; - while (check_doc_id > 0u && !node_refs[check_doc_id].load_relaxed().valid()) { + while (check_doc_id > 0u && !get_node_ref(check_doc_id).valid()) { --check_doc_id; } node_refs_size.store(check_doc_id + 1, std::memory_order_release); @@ -70,11 +70,11 @@ void HnswGraph::set_link_array(uint32_t docid, uint32_t level, const LinkArrayRef& new_links) { auto new_links_ref = links.add(new_links); - auto node_ref = node_refs[docid].load_acquire(); + auto node_ref = get_node_ref(docid); assert(node_ref.valid()); auto levels = nodes.get_writable(node_ref); assert(level < levels.size()); - auto old_links_ref = levels[level].load_acquire(); + auto old_links_ref = levels[level].load_relaxed(); levels[level].store_release(new_links_ref); links.remove(old_links_ref); } @@ -83,9 +83,9 @@ HnswGraph::Histograms HnswGraph::histograms() const { Histograms result; - size_t num_nodes = node_refs.size(); + size_t num_nodes = node_refs_size.load(std::memory_order_acquire); for (size_t i = 0; i < num_nodes; ++i) { - auto node_ref = node_refs[i].load_acquire(); + auto node_ref = acquire_node_ref(i); if (node_ref.valid()) { uint32_t levels = 0; uint32_t l0links = 0; diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.h b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.h index 5d6cff73102..726abb8141d 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.h +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.h @@ -56,11 +56,15 @@ struct HnswGraph { void trim_node_refs_size(); NodeRef get_node_ref(uint32_t docid) const { - return node_refs[docid].load_acquire(); + return node_refs[docid].load_relaxed(); + } + + NodeRef acquire_node_ref(uint32_t docid) const { + return node_refs.acquire_elem_ref(docid).load_acquire(); } bool still_valid(uint32_t docid, NodeRef node_ref) const { - return node_ref.valid() && (get_node_ref(docid) == node_ref); + return node_ref.valid() && (acquire_node_ref(docid) == node_ref); } LevelArrayRef get_level_array(NodeRef node_ref) const { @@ -75,6 +79,11 @@ struct HnswGraph { return get_level_array(node_ref); } + LevelArrayRef acquire_level_array(uint32_t docid) const { + auto node_ref = acquire_node_ref(docid); + return get_level_array(node_ref); + } + LinkArrayRef get_link_array(LevelArrayRef levels, uint32_t level) const { if (level < levels.size()) { auto links_ref = levels[level].load_acquire(); @@ -90,6 +99,11 @@ struct HnswGraph { return get_link_array(levels, level); } + LinkArrayRef acquire_link_array(uint32_t docid, uint32_t level) const { + auto levels = acquire_level_array(docid); + return get_link_array(levels, level); + } + LinkArrayRef get_link_array(NodeRef node_ref, uint32_t level) const { auto levels = get_level_array(node_ref); return get_link_array(levels, level); @@ -124,7 +138,7 @@ struct HnswGraph { while (true) { uint64_t value = get_entry_atomic(); entry.docid = (uint32_t)value; - entry.node_ref = get_node_ref(entry.docid); + entry.node_ref = acquire_node_ref(entry.docid); entry.level = (int32_t)(value >> 32); if ((entry.docid == 0) && (entry.level == -1) @@ -144,7 +158,7 @@ struct HnswGraph { } } - size_t size() const { return node_refs.size(); } + size_t size() const { return node_refs_size.load(std::memory_order_acquire); } struct Histograms { std::vector<uint32_t> level_histogram; diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp index c99e059815b..5ae26757b0d 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp @@ -245,7 +245,7 @@ HnswIndex::find_nearest_in_layer(const TypedCells& input, const HnswCandidate& e while (keep_searching) { keep_searching = false; for (uint32_t neighbor_docid : _graph.get_link_array(nearest.node_ref, level)) { - auto neighbor_ref = _graph.get_node_ref(neighbor_docid); + auto neighbor_ref = _graph.acquire_node_ref(neighbor_docid); double dist = calc_distance(input, neighbor_docid); if (_graph.still_valid(neighbor_docid, neighbor_ref) && dist < nearest.distance) @@ -289,7 +289,7 @@ HnswIndex::search_layer_helper(const TypedCells& input, uint32_t neighbors_to_fi if (neighbor_docid >= doc_id_limit) { continue; } - auto neighbor_ref = _graph.get_node_ref(neighbor_docid); + auto neighbor_ref = _graph.acquire_node_ref(neighbor_docid); if ((! neighbor_ref.valid()) || ! visited.try_mark(neighbor_docid)) { @@ -433,7 +433,7 @@ HnswIndex::prepare_add_document(uint32_t docid, TypedCells vector, vespalib::GenerationHandler::Guard read_guard) const { - uint32_t max_nodes = _graph.node_refs.size(); + uint32_t max_nodes = _graph.node_refs_size.load(std::memory_order_acquire); if (max_nodes < _cfg.min_size_before_two_phase()) { // the first documents added will do all work in write thread // to ensure they are linked together: @@ -543,7 +543,7 @@ HnswIndex::compact_link_arrays(CompactionSpec compaction_spec, const CompactionS auto context = _graph.links.compactWorst(compaction_spec, compaction_strategy); uint32_t doc_id_limit = _graph.node_refs.size(); for (uint32_t doc_id = 1; doc_id < doc_id_limit; ++doc_id) { - EntryRef level_ref = _graph.node_refs[doc_id].load_relaxed(); + EntryRef level_ref = _graph.get_node_ref(doc_id); if (level_ref.valid()) { vespalib::ArrayRef<AtomicEntryRef> refs(_graph.nodes.get_writable(level_ref)); context->compact(refs); @@ -756,7 +756,7 @@ HnswIndex::top_k_candidates(const TypedCells &vector, uint32_t k, const BitVecto HnswNode HnswIndex::get_node(uint32_t docid) const { - auto node_ref = _graph.node_refs[docid].load_acquire(); + auto node_ref = _graph.acquire_node_ref(docid); if (!node_ref.valid()) { return HnswNode(); } @@ -790,15 +790,16 @@ bool HnswIndex::check_link_symmetry() const { bool all_sym = true; - for (size_t docid = 0; docid < _graph.node_refs.size(); ++docid) { - auto node_ref = _graph.node_refs[docid].load_acquire(); + size_t doc_id_limit = _graph.size(); + for (size_t docid = 0; docid < doc_id_limit; ++docid) { + auto node_ref = _graph.acquire_node_ref(docid); if (node_ref.valid()) { auto levels = _graph.nodes.get(node_ref); uint32_t level = 0; for (const auto& links_ref : levels) { auto links = _graph.links.get(links_ref.load_acquire()); for (auto neighbor_docid : links) { - auto neighbor_links = _graph.get_link_array(neighbor_docid, level); + auto neighbor_links = _graph.acquire_link_array(neighbor_docid, level); if (! has_link_to(neighbor_links, docid)) { all_sym = false; LOG(warning, "check_link_symmetry: docid %zu links to %u on level %u, but no backlink", @@ -822,8 +823,10 @@ HnswIndex::count_reachable_nodes() const } std::vector<bool> visited(_graph.size()); LinkArray found_links; - found_links.push_back(entry.docid); - visited[entry.docid] = true; + if (entry.docid < visited.size()) { + found_links.push_back(entry.docid); + visited[entry.docid] = true; + } vespalib::steady_time doom = vespalib::steady_clock::now() + MAX_COUNT_DURATION; while (search_level >= 0) { for (uint32_t idx = 0; idx < found_links.size(); ++idx) { @@ -831,11 +834,15 @@ HnswIndex::count_reachable_nodes() const return {found_links.size(), false}; } uint32_t docid = found_links[idx]; - auto neighbors = _graph.get_link_array(docid, search_level); - for (uint32_t neighbor : neighbors) { - if (visited[neighbor]) continue; - visited[neighbor] = true; - found_links.push_back(neighbor); + if (docid < visited.size()) { + auto neighbors = _graph.acquire_link_array(docid, search_level); + for (uint32_t neighbor : neighbors) { + if (neighbor >= visited.size() || visited[neighbor]) { + continue; + } + visited[neighbor] = true; + found_links.push_back(neighbor); + } } } --search_level; diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index_saver.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index_saver.cpp index 2eb9f7d4acd..cc2ecd584e1 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_index_saver.cpp +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index_saver.cpp @@ -14,7 +14,7 @@ count_valid_link_arrays(const HnswGraph & graph) { size_t count(0); size_t num_nodes = graph.node_refs.size(); for (size_t i = 0; i < num_nodes; ++i) { - auto node_ref = graph.node_refs[i].load_acquire(); + auto node_ref = graph.get_node_ref(i); if (node_ref.valid()) { count += graph.nodes.get(node_ref).size(); } @@ -47,11 +47,11 @@ HnswIndexSaver::HnswIndexSaver(const HnswGraph &graph) _meta_data.nodes.reserve(num_nodes+1); for (size_t i = 0; i < num_nodes; ++i) { _meta_data.nodes.push_back(_meta_data.refs.size()); - auto node_ref = graph.node_refs[i].load_acquire(); + auto node_ref = graph.get_node_ref(i); if (node_ref.valid()) { auto levels = graph.nodes.get(node_ref); for (const auto& links_ref : levels) { - _meta_data.refs.push_back(links_ref.load_acquire()); + _meta_data.refs.push_back(links_ref.load_relaxed()); } } } diff --git a/searchlib/src/vespa/searchlib/transactionlog/domain.cpp b/searchlib/src/vespa/searchlib/transactionlog/domain.cpp index 928497bf09d..0af1ffa7b33 100644 --- a/searchlib/src/vespa/searchlib/transactionlog/domain.cpp +++ b/searchlib/src/vespa/searchlib/transactionlog/domain.cpp @@ -214,9 +214,9 @@ Domain::triggerSyncNow(std::unique_ptr<vespalib::IDestructorCallback> after_sync std::unique_lock guard(_currentChunkMutex); commitAndTransferResponses(guard); } - _singleCommitter->execute(makeLambdaTask([after_sync=std::move(after_sync), domainPart=getActivePart()]() { + _singleCommitter->execute(makeLambdaTask([this, after_sync=std::move(after_sync)]() { (void) after_sync; - domainPart->sync(); + getActivePart()->sync(); })); } diff --git a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp index b31173c74c2..f3706bfc7c1 100644 --- a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp +++ b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp @@ -186,8 +186,9 @@ SimpleQueryStackItem::AppendBuffer(RawBuf *buf) const buf->appendCompressedPositiveNumber(_arg2); // allow_approximate buf->appendCompressedPositiveNumber(_arg3); // explore_additional_hits break; - case ITEM_PREDICATE_QUERY: // not handled at all here case ITEM_MULTI_TERM: // TODO: handle + case ITEM_PREDICATE_QUERY: // not handled at all here + case ITEM_MAX: case ITEM_UNDEF: abort(); break; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp index 2c2ce860e39..fb53ddcc470 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp @@ -82,7 +82,7 @@ filter_matching_elements_in_input_field_while_converting_to_slime(const FieldVal // Only difference is that we filter matched elements on the fly. auto converted = SummaryFieldConverter::convert_field_with_filter(false, input_field_value, matching_elems); // This should hold as we also have asserted that (type == ResType::RES_JSONSTRING); - assert(converted->getClass().inherits(LiteralFieldValueB::classId)); + assert(converted->isLiteral()); auto& literal = static_cast<const LiteralFieldValueB&>(*converted); vespalib::stringref buf = literal.getValueRef(); Slime input_field_as_slime; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/summaryfieldconverter.cpp b/searchsummary/src/vespa/searchsummary/docsummary/summaryfieldconverter.cpp index 487fb9e329f..c107e5c8739 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/summaryfieldconverter.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/summaryfieldconverter.cpp @@ -29,7 +29,6 @@ #include <vespa/eval/eval/value_codec.h> #include <vespa/searchcommon/common/schema.h> #include <vespa/searchlib/util/url.h> -#include <vespa/vespalib/encoding/base64.h> #include <vespa/vespalib/geo/zcurve.h> #include <vespa/vespalib/stllike/asciistream.h> #include <vespa/vespalib/util/size_literals.h> @@ -176,7 +175,7 @@ void handleIndexingTerms(Handler &handler, const StringFieldValue &value) { const StringFieldValue &ensureStringFieldValue(const FieldValue &value) __attribute__((noinline)); const StringFieldValue &ensureStringFieldValue(const FieldValue &value) { - if (!value.inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) { + if (!value.isA(FieldValue::Type::STRING)) { throw vespalib::IllegalArgumentException("Illegal field type. " + value.toString(), VESPA_STRLOC); } return static_cast<const StringFieldValue &>(value); @@ -287,9 +286,7 @@ class SummaryFieldValueConverter : protected ConstFieldValueVisitor void visit(const StructFieldValue &value) override { if (*value.getDataType() == *SearchDataType::URI) { FieldValue::UP uriAllValue = value.getValue("all"); - if (uriAllValue && - uriAllValue->inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) - { + if (uriAllValue && uriAllValue->isA(FieldValue::Type::STRING)) { uriAllValue->accept(*this); return; } @@ -488,9 +485,7 @@ private: } if (*value.getDataType() == *SearchDataType::URI) { FieldValue::UP uriAllValue = value.getValue("all"); - if (uriAllValue && - uriAllValue->inherits(IDENTIFIABLE_CLASSID(StringFieldValue))) - { + if (uriAllValue && uriAllValue->isA(FieldValue::Type::STRING)) { uriAllValue->accept(*this); return; } diff --git a/staging_vespalib/src/vespa/vespalib/objects/objectvisitor.h b/staging_vespalib/src/vespa/vespalib/objects/objectvisitor.h index 7e48e9f5b4b..dba731a8940 100644 --- a/staging_vespalib/src/vespa/vespalib/objects/objectvisitor.h +++ b/staging_vespalib/src/vespa/vespalib/objects/objectvisitor.h @@ -2,7 +2,6 @@ #pragma once #include <vespa/vespalib/stllike/string.h> -#include <stdint.h> namespace vespalib { diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h index 1ceee6dd7b2..76f0ad1fa3a 100644 --- a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h +++ b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h @@ -17,7 +17,7 @@ class XmlSerializable { public: XmlSerializable() {} - virtual ~XmlSerializable() {} + virtual ~XmlSerializable() = default; virtual void printXml(XmlOutputStream& out) const = 0; diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp index cbf58b5313d..1e091d9a6d8 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp @@ -72,7 +72,7 @@ createMultiValueAttribute(const vespalib::string & name, const document::FieldVa ndt = &cdt->getNestedType(); } LOG(debug, "Create %s attribute '%s' with data type '%s' (%s)", - arrayType ? "array" : "weighted set", name.c_str(), ndt->getName().c_str(), fv.getClass().name()); + arrayType ? "array" : "weighted set", name.c_str(), ndt->getName().c_str(), fv.className()); if (ndt->getId() == DataType::T_BYTE || ndt->getId() == DataType::T_INT || ndt->getId() == DataType::T_LONG) @@ -89,7 +89,7 @@ createMultiValueAttribute(const vespalib::string & name, const document::FieldVa : std::make_shared<search::WeightedSetStringExtAttribute>(name); } else { LOG(debug, "Can not make an multivalue attribute out of %s with data type '%s' (%s)", - name.c_str(), ndt->getName().c_str(), fv.getClass().name()); + name.c_str(), ndt->getName().c_str(), fv.className()); } return AttributeVector::SP(); } @@ -97,15 +97,15 @@ createMultiValueAttribute(const vespalib::string & name, const document::FieldVa AttributeVector::SP createAttribute(const vespalib::string & name, const document::FieldValue & fv) { - LOG(debug, "Create single value attribute '%s' with value type '%s'", name.c_str(), fv.getClass().name()); - if (fv.inherits(document::ByteFieldValue::classId) || fv.inherits(document::IntFieldValue::classId) || fv.inherits(document::LongFieldValue::classId)) { + LOG(debug, "Create single value attribute '%s' with value type '%s'", name.c_str(), fv.className()); + if (fv.isA(document::FieldValue::Type::BYTE) || fv.isA(document::FieldValue::Type::INT) || fv.isA(document::FieldValue::Type::LONG)) { return std::make_shared<search::SingleIntegerExtAttribute>(name); - } else if (fv.inherits(document::DoubleFieldValue::classId) || fv.inherits(document::FloatFieldValue::classId)) { + } else if (fv.isA(document::FieldValue::Type::DOUBLE) || fv.isA(document::FieldValue::Type::FLOAT)) { return std::make_shared<search::SingleFloatExtAttribute>(name); - } else if (fv.inherits(document::StringFieldValue::classId)) { + } else if (fv.isA(document::FieldValue::Type::STRING)) { return std::make_shared<search::SingleStringExtAttribute>(name); } else { - LOG(debug, "Can not make an attribute out of %s of type '%s'.", name.c_str(), fv.getClass().name()); + LOG(debug, "Can not make an attribute out of %s of type '%s'.", name.c_str(), fv.className()); } return AttributeVector::SP(); } @@ -761,14 +761,14 @@ void SearchVisitor::setupAttributeVector(const FieldPath &fieldPath) { if (attr) { LOG(debug, "Adding attribute '%s' for field '%s' with data type '%s' (%s)", - attr->getName().c_str(), attrName.c_str(), fv.getDataType()->getName().c_str(), fv.getClass().name()); + attr->getName().c_str(), attrName.c_str(), fv.getDataType()->getName().c_str(), fv.className()); if ( ! _attrMan.add(attr) ) { LOG(warning, "Failed adding attribute '%s' for field '%s' with data type '%s' (%s)", - attr->getName().c_str(), attrName.c_str(), fv.getDataType()->getName().c_str(), fv.getClass().name()); + attr->getName().c_str(), attrName.c_str(), fv.getDataType()->getName().c_str(), fv.className()); } } else { LOG(debug, "Cannot setup attribute for field '%s' with data type '%s' (%s). Aggregation and sorting will not work for this field", - attrName.c_str(), fv.getDataType()->getName().c_str(), fv.getClass().name()); + attrName.c_str(), fv.getDataType()->getName().c_str(), fv.className()); } } diff --git a/tsan-suppressions.txt b/tsan-suppressions.txt index a79340d887e..23b63b8945c 100644 --- a/tsan-suppressions.txt +++ b/tsan-suppressions.txt @@ -14,3 +14,5 @@ deadlock:proton::ImportedAttributesContext::getAttributeStableEnum # creation and locking is not strictly enough ordered. race:llvm::sys::MutexImpl +race:llvm::sys::SmartMutex<false>::lock +race:llvm::sys::SmartMutex<true>::lock diff --git a/vdslib/src/vespa/vdslib/container/parameters.cpp b/vdslib/src/vespa/vdslib/container/parameters.cpp index 85ba6318f7c..60527a00547 100644 --- a/vdslib/src/vespa/vdslib/container/parameters.cpp +++ b/vdslib/src/vespa/vdslib/container/parameters.cpp @@ -2,7 +2,6 @@ #include "parameters.hpp" #include <vespa/document/util/bytebuffer.h> -#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/objects/hexdump.h> #include <vespa/vespalib/stllike/hash_map.hpp> #include <vespa/vespalib/util/xmlstream.h> @@ -60,7 +59,7 @@ void Parameters::deserialize(document::ByteBuffer& buffer) } void -Parameters::printXml(document::XmlOutputStream& xos) const +Parameters::printXml(vespalib::xml::XmlOutputStream& xos) const { using namespace vespalib::xml; xos << XmlTag("parameters"); diff --git a/vdslib/src/vespa/vdslib/container/parameters.h b/vdslib/src/vespa/vdslib/container/parameters.h index 34568cc85cb..41c95d14da4 100644 --- a/vdslib/src/vespa/vdslib/container/parameters.h +++ b/vdslib/src/vespa/vdslib/container/parameters.h @@ -14,7 +14,7 @@ #pragma once -#include <vespa/document/util/xmlserializable.h> +#include <vespa/vespalib/util/xmlserializable.h> #include <vespa/vespalib/stllike/hash_map.h> namespace vespalib { class GrowableByteBuffer; } @@ -22,7 +22,7 @@ namespace document { class ByteBuffer; } namespace vdslib { -class Parameters : public document::XmlSerializable { +class Parameters : public vespalib::xml::XmlSerializable { public: typedef vespalib::stringref KeyT; class Value : public vespalib::string @@ -39,7 +39,7 @@ public: private: ParametersMap _parameters; - void printXml(document::XmlOutputStream& xos) const override; + void printXml(vespalib::xml::XmlOutputStream& xos) const override; public: Parameters(); diff --git a/vespamalloc/src/tests/test1/testatomic.cpp b/vespamalloc/src/tests/test1/testatomic.cpp index 5ce52330f77..948616065e6 100644 --- a/vespamalloc/src/tests/test1/testatomic.cpp +++ b/vespamalloc/src/tests/test1/testatomic.cpp @@ -2,6 +2,7 @@ #include <vespa/vespalib/testkit/testapp.h> #include <vespamalloc/malloc/allocchunk.h> #include <vespamalloc/malloc/mmappool.h> +#include <unistd.h> TEST("verify lock freeness of atomics"){ { @@ -23,29 +24,32 @@ TEST("verify lock freeness of atomics"){ TEST("test explicit mmap/munmap") { vespamalloc::MMapPool mmapPool; + size_t page_size = getpagesize(); + size_t mmap1_size = 3 * page_size; + size_t mmap2_size = 7 * page_size; EXPECT_EQUAL(0u, mmapPool.getNumMappings()); EXPECT_EQUAL(0u, mmapPool.getMmappedBytes()); - void * mmap1 = mmapPool.mmap(0xe000); + void * mmap1 = mmapPool.mmap(mmap1_size); EXPECT_EQUAL(1u, mmapPool.getNumMappings()); - EXPECT_EQUAL(0xe000u, mmapPool.getMmappedBytes()); - EXPECT_EQUAL(0xe000u, mmapPool.get_size(mmap1)); + EXPECT_EQUAL(mmap1_size, mmapPool.getMmappedBytes()); + EXPECT_EQUAL(mmap1_size, mmapPool.get_size(mmap1)); mmapPool.unmap(mmap1); EXPECT_EQUAL(0u, mmapPool.getNumMappings()); EXPECT_EQUAL(0u, mmapPool.getMmappedBytes()); - mmap1 = mmapPool.mmap(0xe000); + mmap1 = mmapPool.mmap(mmap1_size); EXPECT_EQUAL(1u, mmapPool.getNumMappings()); - EXPECT_EQUAL(0xe000u, mmapPool.getMmappedBytes()); - EXPECT_EQUAL(0xe000u, mmapPool.get_size(mmap1)); + EXPECT_EQUAL(mmap1_size, mmapPool.getMmappedBytes()); + EXPECT_EQUAL(mmap1_size, mmapPool.get_size(mmap1)); - void * mmap2 = mmapPool.mmap(0x1e000); + void * mmap2 = mmapPool.mmap(mmap2_size); EXPECT_EQUAL(2u, mmapPool.getNumMappings()); - EXPECT_EQUAL(0x2c000u, mmapPool.getMmappedBytes()); - EXPECT_EQUAL(0xe000u, mmapPool.get_size(mmap1)); - EXPECT_EQUAL(0x1e000u, mmapPool.get_size(mmap2)); + EXPECT_EQUAL(mmap1_size + mmap2_size, mmapPool.getMmappedBytes()); + EXPECT_EQUAL(mmap1_size, mmapPool.get_size(mmap1)); + EXPECT_EQUAL(mmap2_size, mmapPool.get_size(mmap2)); mmapPool.unmap(mmap1); EXPECT_EQUAL(1u, mmapPool.getNumMappings()); - EXPECT_EQUAL(0x1e000u, mmapPool.getMmappedBytes()); + EXPECT_EQUAL(mmap2_size, mmapPool.getMmappedBytes()); mmapPool.unmap(mmap2); EXPECT_EQUAL(0u, mmapPool.getNumMappings()); EXPECT_EQUAL(0u, mmapPool.getMmappedBytes()); diff --git a/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp b/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp index c587f9eadfb..e69999b160e 100644 --- a/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp +++ b/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp @@ -30,7 +30,7 @@ FieldSearcherBase::FieldSearcherBase() : _qtl(), _qtlFastBuffer(), _qtlFastSize(0), - _qtlFast(NULL) + _qtlFast(nullptr) { } @@ -38,7 +38,7 @@ FieldSearcherBase::FieldSearcherBase(const FieldSearcherBase & org) : _qtl(), _qtlFastBuffer(), _qtlFastSize(0), - _qtlFast(NULL) + _qtlFast(nullptr) { prepare(org._qtl); } @@ -260,8 +260,7 @@ bool FieldSearcher::onSearch(const StorageDocument & doc) bool retval(true); size_t fNo(field()); const StorageDocument::SubDocument & sub = doc.getComplexField(fNo); - if (sub.getFieldValue() != NULL) { - LOG(spam, "onSearch %s : %s", sub.getFieldValue()->getClass().name(), sub.getFieldValue()->toString().c_str()); + if (sub.getFieldValue() != nullptr) { IteratorHandler ih(*this); sub.getFieldValue()->iterateNested(sub.getRange(), ih); } @@ -282,10 +281,10 @@ FieldSearcher::IteratorHandler::onCollectionStart(const Content & c) { const document::FieldValue & fv = c.getValue(); LOG(spam, "onCollectionStart: field value '%s'", fv.toString().c_str()); - if (fv.inherits(document::ArrayFieldValue::classId)) { + if (fv.isA(document::FieldValue::Type::ARRAY)) { const document::ArrayFieldValue & afv = static_cast<const document::ArrayFieldValue &>(fv); LOG(spam, "onCollectionStart: Array size = '%zu'", afv.size()); - } else if (fv.inherits(document::WeightedSetFieldValue::classId)) { + } else if (fv.isA(document::FieldValue::Type::WSET)) { const document::WeightedSetFieldValue & wsfv = static_cast<const document::WeightedSetFieldValue &>(fv); LOG(spam, "onCollectionStart: WeightedSet size = '%zu'", wsfv.size()); } diff --git a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp index a74e41dfb3f..bd16c687fc7 100644 --- a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp +++ b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp @@ -71,7 +71,7 @@ public: StringResultHandler(ResType t, ResultPacker & p) : _type(t), _packer(p) {} void onPrimitive(uint32_t, const Content & c) override { const document::FieldValue & fv = c.getValue(); - if (fv.getClass().inherits(document::LiteralFieldValueB::classId)) { + if (fv.isLiteral()) { const document::LiteralFieldValueB & lfv = static_cast<const document::LiteralFieldValueB &>(fv); vespalib::stringref s = lfv.getValueRef(); addToPacker(s.data(), s.size()); diff --git a/vsm/src/vespa/vsm/vsm/flattendocsumwriter.cpp b/vsm/src/vespa/vsm/vsm/flattendocsumwriter.cpp index 821434a4ed6..06b652d85e6 100644 --- a/vsm/src/vespa/vsm/vsm/flattendocsumwriter.cpp +++ b/vsm/src/vespa/vsm/vsm/flattendocsumwriter.cpp @@ -18,13 +18,12 @@ FlattenDocsumWriter::onPrimitive(uint32_t, const Content & c) { considerSeparator(); const document::FieldValue & fv = c.getValue(); - const auto & clazz = fv.getClass(); - if (clazz.inherits(document::LiteralFieldValueB::classId)) { + if (fv.isLiteral()) { const document::LiteralFieldValueB & lfv = static_cast<const document::LiteralFieldValueB &>(fv); vespalib::stringref value = lfv.getValueRef(); _output.put(value.data(), value.size()); - } else if (clazz.inherits(document::NumericFieldValueBase::classId) || - clazz.inherits(document::BoolFieldValue::classId)) + } else if (fv.isNumeric() || + fv.isA(document::FieldValue::Type::BOOL)) { vespalib::string value = fv.getAsString(); _output.put(value.data(), value.size()); diff --git a/vsm/src/vespa/vsm/vsm/slimefieldwriter.cpp b/vsm/src/vespa/vsm/vsm/slimefieldwriter.cpp index 405f2292f5d..5bc5798fb9d 100644 --- a/vsm/src/vespa/vsm/vsm/slimefieldwriter.cpp +++ b/vsm/src/vespa/vsm/vsm/slimefieldwriter.cpp @@ -48,13 +48,12 @@ namespace vsm { void SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &inserter) { - const auto & clazz = fv.getClass(); LOG(debug, "traverseRecursive: class(%s), fieldValue(%s), currentPath(%s)", - clazz.name(), fv.toString().c_str(), toString(_currPath).c_str()); + fv.className(), fv.toString().c_str(), toString(_currPath).c_str()); - if (clazz.inherits(document::CollectionFieldValue::classId)) { + if (fv.isCollection()) { const document::CollectionFieldValue & cfv = static_cast<const document::CollectionFieldValue &>(fv); - if (cfv.inherits(document::ArrayFieldValue::classId)) { + if (cfv.isA(document::FieldValue::Type::ARRAY)) { const document::ArrayFieldValue & afv = static_cast<const document::ArrayFieldValue &>(cfv); Cursor &a = inserter.insertArray(); for (size_t i = 0; i < afv.size(); ++i) { @@ -62,7 +61,8 @@ SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &i ArrayInserter ai(a); traverseRecursive(nfv, ai); } - } else if (cfv.inherits(document::WeightedSetFieldValue::classId)) { + } else { + assert(cfv.isA(document::FieldValue::Type::WSET)); const document::WeightedSetFieldValue & wsfv = static_cast<const document::WeightedSetFieldValue &>(cfv); Cursor &a = inserter.insertArray(); Symbol isym = a.resolve("item"); @@ -75,10 +75,8 @@ SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &i int weight = static_cast<const document::IntFieldValue &>(*entry.second).getValue(); o.setLong(wsym, weight); } - } else { - LOG(warning, "traverseRecursive: Cannot handle collection field value of type '%s'", clazz.name()); } - } else if (clazz.inherits(document::MapFieldValue::classId)) { + } else if (fv.isA(document::FieldValue::Type::MAP)) { const document::MapFieldValue & mfv = static_cast<const document::MapFieldValue &>(fv); Cursor &a = inserter.insertArray(); Symbol keysym = a.resolve("key"); @@ -92,7 +90,7 @@ SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &i traverseRecursive(*entry.second, vi); _currPath.pop_back(); } - } else if (clazz.inherits(document::StructuredFieldValue::classId)) { + } else if (fv.isStructured()) { const document::StructuredFieldValue & sfv = static_cast<const document::StructuredFieldValue &>(fv); Cursor &o = inserter.insertObject(); if (sfv.getDataType() == &document::PositionDataType::getInstance() @@ -135,10 +133,10 @@ SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &i } } } else { - if (clazz.inherits(document::LiteralFieldValueB::classId)) { + if (fv.isLiteral()) { const document::LiteralFieldValueB & lfv = static_cast<const document::LiteralFieldValueB &>(fv); inserter.insertString(lfv.getValueRef()); - } else if (clazz.inherits(document::NumericFieldValueBase::classId)) { + } else if (fv.isNumeric()) { switch (fv.getDataType()->getId()) { case document::DataType::T_BYTE: case document::DataType::T_SHORT: @@ -155,7 +153,7 @@ SlimeFieldWriter::traverseRecursive(const document::FieldValue & fv, Inserter &i default: inserter.insertString(fv.getAsString()); } - } else if (clazz.inherits(document::BoolFieldValue::classId)) { + } else if (fv.isA(document::FieldValue::Type::BOOL)) { const auto & bfv = static_cast<const document::BoolFieldValue &>(fv); inserter.insertBool(bfv.getValue()); } else { |