aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--annotations/src/main/java/com/yahoo/api/annotations/Beta.java3
-rwxr-xr-xconfig-model/remove-indexes-from-temp-files.sh3
-rw-r--r--config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java43
-rw-r--r--config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java23
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java3
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java4
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedSchemas.java13
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentManager.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/configmodel/producers/DocumentTypes.java4
-rw-r--r--config-model/src/test/derived/attributeprefetch/summarymap.cfg48
-rw-r--r--config-model/src/test/derived/complex/summarymap.cfg60
-rw-r--r--config-model/src/test/derived/declstruct/documentmanager.cfg174
-rw-r--r--config-model/src/test/derived/duplicate_struct/documentmanager.cfg78
-rw-r--r--config-model/src/test/derived/duplicate_struct/documenttypes.cfg100
-rw-r--r--config-model/src/test/derived/duplicate_struct/foo.sd17
-rw-r--r--config-model/src/test/derived/duplicate_struct/foobar.sd16
-rw-r--r--config-model/src/test/derived/function_arguments/rank-profiles.cfg2
-rw-r--r--config-model/src/test/derived/function_arguments_with_expressions/rank-profiles.cfg2
-rw-r--r--config-model/src/test/derived/imported_fields_inherited_reference/documenttypes.cfg13
-rw-r--r--config-model/src/test/derived/imported_position_field/imported-fields.cfg6
-rw-r--r--config-model/src/test/derived/imported_position_field/summarymap.cfg12
-rw-r--r--config-model/src/test/derived/imported_struct_fields/imported-fields.cfg42
-rw-r--r--config-model/src/test/derived/imported_struct_fields/summarymap.cfg48
-rw-r--r--config-model/src/test/derived/indexschema/index-info.cfg4
-rw-r--r--config-model/src/test/derived/inheritance/documentmanager.cfg208
-rw-r--r--config-model/src/test/derived/inheritfromgrandparent/documentmanager.cfg136
-rw-r--r--config-model/src/test/derived/inheritfromparent/documentmanager.cfg138
-rw-r--r--config-model/src/test/derived/inheritfromparent/documenttypes.cfg34
-rw-r--r--config-model/src/test/derived/inheritstruct/index-info.cfg102
-rw-r--r--config-model/src/test/derived/language/ilscripts.cfg2
-rw-r--r--config-model/src/test/derived/lowercase/ilscripts.cfg2
-rw-r--r--config-model/src/test/derived/lowercase/index-info.cfg2
-rw-r--r--config-model/src/test/derived/renamedfeatures/rank-profiles.cfg164
-rw-r--r--config-model/src/test/derived/schemainheritance/summary.cfg2
-rw-r--r--config-model/src/test/derived/schemainheritance/summarymap.cfg6
-rw-r--r--config-model/src/test/derived/schemainheritance/vsmsummary.cfg6
-rw-r--r--config-model/src/test/derived/structinheritance/documenttypes.cfg200
-rw-r--r--config-model/src/test/derived/tensor/rank-profiles.cfg1
-rw-r--r--config-model/src/test/derived/tokenization/ilscripts.cfg2
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java4
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/derived/DuplicateStructTestCase.java30
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java3
-rw-r--r--container-search/abi-spec.json19
-rw-r--r--container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g42
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/CompositeItem.java10
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/EquivItem.java4
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/Item.java46
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/PhraseItem.java2
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/PhraseSegmentItem.java2
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/TaggableItem.java8
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/WeightedSetItem.java20
-rw-r--r--container-search/src/main/java/com/yahoo/search/grouping/GroupingQueryParser.java5
-rw-r--r--container-search/src/main/java/com/yahoo/search/grouping/GroupingRequest.java26
-rw-r--r--container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java2
-rw-r--r--container-search/src/main/java/com/yahoo/search/grouping/vespa/RequestBuilder.java28
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java30
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java14
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java22
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java6
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java1
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/servicedump/VespaServiceDumperImpl.java2
-rw-r--r--searchlib/src/tests/transactionlog/translogclient_test.cpp100
-rw-r--r--searchlib/src/vespa/searchlib/parsequery/parse.h4
-rw-r--r--searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp2
-rw-r--r--vespajlib/src/main/java/com/yahoo/collections/CopyOnWriteHashMap.java25
-rw-r--r--vespajlib/src/main/java/com/yahoo/text/Utf8.java4
-rw-r--r--vespajlib/src/test/java/com/yahoo/collections/CopyOnWriteHashMapTestCase.java3
-rw-r--r--vespalib/src/tests/text/lowercase/lowercase_test.cpp19
-rw-r--r--vespalib/src/vespa/vespalib/text/lowercase.cpp12
-rw-r--r--vespalib/src/vespa/vespalib/text/lowercase.h10
74 files changed, 1283 insertions, 925 deletions
diff --git a/annotations/src/main/java/com/yahoo/api/annotations/Beta.java b/annotations/src/main/java/com/yahoo/api/annotations/Beta.java
index c555fbbcb57..4d15bb377d3 100644
--- a/annotations/src/main/java/com/yahoo/api/annotations/Beta.java
+++ b/annotations/src/main/java/com/yahoo/api/annotations/Beta.java
@@ -18,6 +18,7 @@ import java.lang.annotation.Target;
@Target({
ElementType.CONSTRUCTOR,
ElementType.METHOD,
- ElementType.TYPE
+ ElementType.TYPE,
+ ElementType.FIELD
})
public @interface Beta {}
diff --git a/config-model/remove-indexes-from-temp-files.sh b/config-model/remove-indexes-from-temp-files.sh
new file mode 100755
index 00000000000..988c99bc6e6
--- /dev/null
+++ b/config-model/remove-indexes-from-temp-files.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+perl -pi -e 's{[[][0-9]*[]][.]}{[].}g;s{[[][0-9]*[]] }{[] };chomp;s/$/\n/' temp/*/*.cfg
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 7652000389b..65c282e01e2 100644
--- a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java
+++ b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentReferenceDataType.java
@@ -15,21 +15,22 @@ import com.yahoo.document.datatypes.ReferenceFieldValue;
*
* @author arnej
**/
-@SuppressWarnings("deprecation")
public final class NewDocumentReferenceDataType extends DataType {
- private StructuredDataType target;
- private DocumentType docTypeTarget = null;
+ private final StructuredDataType target;
+ private final DocumentType docTypeTarget;
private ReferenceDataType delegate = null;
private final boolean temporary;
private NewDocumentReferenceDataType(NewDocumentType.Name nameAndId,
StructuredDataType target,
+ DocumentType docTypeTarget,
boolean temporary)
{
super(nameAndId.getName(), nameAndId.getId());
this.target = target;
+ this.docTypeTarget = docTypeTarget;
this.temporary = temporary;
}
@@ -39,47 +40,27 @@ public final class NewDocumentReferenceDataType extends DataType {
}
public static NewDocumentReferenceDataType forDocumentName(String documentName) {
- return new NewDocumentReferenceDataType(buildTypeName(documentName),
- TemporaryStructuredDataType.create(documentName),
- true);
+ return new NewDocumentReferenceDataType(new DocumentType(documentName));
}
public NewDocumentReferenceDataType(DocumentType document) {
- this(buildTypeName(document.getName()), document, true);
- this.docTypeTarget = document;
+ this(buildTypeName(document.getName()), document, document, true);
}
public NewDocumentReferenceDataType(NewDocumentType document) {
- this(buildTypeName(document.getName()), document, false);
+ this(buildTypeName(document.getName()), document, new DocumentType(document.getName()), false);
}
public boolean isTemporary() { return temporary; }
public StructuredDataType getTargetType() { return target; }
-
- public void setTargetType(StructuredDataType type) {
- assert(target.getName().equals(type.getName()));
- if (temporary) {
- this.target = type;
- if ((docTypeTarget == null) && (type instanceof DocumentType)) {
- this.docTypeTarget = (DocumentType) type;
- }
- } else {
- throw new IllegalStateException
- (String.format("Unexpected attempt to replace already concrete target " +
- "type in NewDocumentReferenceDataType instance (type is '%s')", target.getName()));
- }
- }
+ public String getTargetTypeName() { return target.getName(); }
+ public int getTargetTypeId() { return target.getId(); }
@Override
public FieldValue createFieldValue() {
// TODO why do we even need this
if (delegate == null) {
- if (docTypeTarget == null) {
- var tmptmp = TemporaryStructuredDataType.create(target.getName());
- var tmp = ReferenceDataType.createWithInferredId(tmptmp);
- return tmp.createFieldValue();
- }
delegate = ReferenceDataType.createWithInferredId(docTypeTarget);
}
return delegate.createFieldValue();
@@ -109,4 +90,10 @@ public final class NewDocumentReferenceDataType extends DataType {
}
return false;
}
+
+ @Override
+ public String toString() {
+ return "{NDRTDT " + getName() + " id=" + getId() + " target=" + target + " [" + target.getClass().getSimpleName() + "]}";
+ }
+
}
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 a6571ef819d..dd8edbdde6c 100644
--- a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java
+++ b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java
@@ -38,7 +38,7 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
private final DataTypeRepo dataTypes = new DataTypeRepo();
private final Map<Integer, NewDocumentType> inherits = new LinkedHashMap<>();
private final AnnotationTypeRegistry annotations = new AnnotationTypeRegistry();
- private final StructDataType header;
+ private final StructDataType contentStruct;
private final Set<FieldSet> fieldSets = new LinkedHashSet<>();
private final Set<Name> documentReferences;
// Imported fields are virtual and therefore exist outside of the SD's document field definition
@@ -66,13 +66,13 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
}
public NewDocumentType(Name name,
- StructDataType header,
+ StructDataType contentStruct,
FieldSets fs,
Set<Name> documentReferences,
Set<String> importedFieldNames) {
super(name.getName());
this.name = name;
- this.header = header;
+ this.contentStruct = contentStruct;
if (fs != null) {
this.fieldSets.addAll(fs.userFieldSets().values());
for (FieldSet f : fs.builtInFieldSets().values()) {
@@ -90,22 +90,23 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
return name;
}
- public DataType getHeader() { return header; }
+ public DataType getContentStruct() { return contentStruct; }
public Collection<NewDocumentType> getInherited() { return inherits.values(); }
public NewDocumentType getInherited(Name inherited) { return inherits.get(inherited.getId()); }
public NewDocumentType removeInherited(Name inherited) { return inherits.remove(inherited.getId()); }
/**
* Data type of the header fields of this and all inherited document types
+ * Used by DocumentGenMojo
* @return merged {@link StructDataType}
*/
public StructDataType allHeader() {
- StructDataType ret = new StructDataType(header.getName());
- for (Field f : header.getFields()) {
+ StructDataType ret = new StructDataType(contentStruct.getName());
+ for (Field f : contentStruct.getFields()) {
ret.addField(f);
}
for (NewDocumentType inherited : getInherited()) {
- for (Field f : ((StructDataType) inherited.getHeader()).getFields()) {
+ for (Field f : ((StructDataType) inherited.getContentStruct()).getFields()) {
ret.addField(f);
}
}
@@ -172,7 +173,7 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
@Override
public Field getField(String name) {
- Field field = header.getField(name);
+ Field field = contentStruct.getField(name);
if (field == null) {
for (NewDocumentType inheritedType : inherits.values()) {
field = inheritedType.getField(name);
@@ -190,7 +191,7 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
@Override
public Field getField(int id) {
- Field field = header.getField(id);
+ Field field = contentStruct.getField(id);
if (field == null) {
for (NewDocumentType inheritedType : inherits.values()) {
field = inheritedType.getField(id);
@@ -209,13 +210,13 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp
collection.addAll(type.getAllFields());
}
- collection.addAll(header.getFields());
+ collection.addAll(contentStruct.getFields());
return Collections.unmodifiableCollection(collection);
}
public Collection<Field> getFields() {
Collection<Field> collection = new LinkedList<>();
- collection.addAll(header.getFields());
+ collection.addAll(contentStruct.getFields());
return Collections.unmodifiableCollection(collection);
}
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 16f60e40809..fb161cb8292 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentModelBuilder.java
@@ -306,8 +306,7 @@ public class DocumentModelBuilder {
}
else if (type instanceof NewDocumentReferenceDataType) {
var t = (NewDocumentReferenceDataType) type;
- var tt = t.getTargetType();
- var doc = getDocumentType(docs, tt.getId());
+ var doc = getDocumentType(docs, t.getTargetTypeId());
type = doc.getReferenceDataType();
}
if (type != original) {
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
index 446187eed00..2e8362f1839 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
@@ -16,7 +16,7 @@ import static java.util.stream.Collectors.toMap;
/**
* Resolves all document references in the search definitions
*
- * Iterates through all document fields having a {@link NewDocumentReferenceDataType} and uses {@link NewDocumentReferenceDataType#getTargetType()}
+ * Iterates through all document fields having a {@link NewDocumentReferenceDataType} and uses {@link NewDocumentReferenceDataType#getTargetTypeName()}
* to determine the referenced document. This information is aggregated into a {@link DocumentReferences} object.
*
* @author bjorncs
@@ -88,7 +88,7 @@ public class DocumentReferenceResolver {
}
private static String getTargetDocumentName(NewDocumentReferenceDataType reference) {
- return reference.getTargetType().getName();
+ return reference.getTargetTypeName();
}
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedSchemas.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedSchemas.java
index a9532c080ee..e4d03a3f471 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedSchemas.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertParsedSchemas.java
@@ -28,6 +28,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.logging.Level;
/**
* Class converting a collection of schemas from the intermediate format.
@@ -114,7 +115,17 @@ public class ConvertParsedSchemas {
}
for (var struct : parsed.getStructs()) {
var structProxy = fieldConverter.convertStructDeclaration(schema, document, struct);
- document.addType(structProxy);
+ var old = document.getType(struct.name());
+ if (old == null) {
+ document.addType(structProxy);
+ } else {
+ var oldFields = old.fieldSet();
+ var newFields = structProxy.fieldSet();
+ if (! newFields.equals(oldFields)) {
+ throw new IllegalArgumentException("Cannot modify already-existing struct: " + struct.name());
+ }
+ deployLogger.logApplicationPackage(Level.WARNING, "Duplicate struct declaration for: " + struct.name());
+ }
}
for (var annotation : parsed.getAnnotations()) {
fieldConverter.convertAnnotation(schema, document, annotation);
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 6f52a384a36..ff311795089 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
@@ -138,7 +138,7 @@ public class DocumentManager {
builder.documenttype(doc);
doc.
name(dt.getName()).
- headerstruct(dt.getHeader().getId());
+ headerstruct(dt.getContentStruct().getId());
for (NewDocumentType inherited : dt.getInherited()) {
doc.inherits(new Datatype.Documenttype.Inherits.Builder().name(inherited.getName()));
}
@@ -178,7 +178,7 @@ public class DocumentManager {
if (refType.isTemporary()) {
throw new IllegalArgumentException("Still temporary: " + refType);
}
- builder.referencetype(new Datatype.Referencetype.Builder().target_type_id(refType.getTargetType().getId()));
+ builder.referencetype(new Datatype.Referencetype.Builder().target_type_id(refType.getTargetTypeId()));
} else {
throw new IllegalArgumentException("Can not create config for data type " + type + " of class " + type.getClass());
}
@@ -280,13 +280,13 @@ public class DocumentManager {
db.
idx(indexMap.idxOf(documentType)).
name(documentType.getName()).
- contentstruct(indexMap.idxOf(documentType.getHeader()));
+ contentstruct(indexMap.idxOf(documentType.getContentStruct()));
docTypeBuildFieldSets(documentType.getFieldSets(), db);
docTypeBuildImportedFields(documentType.getImportedFieldNames(), db);
for (NewDocumentType inherited : documentType.getInherited()) {
db.inherits(b -> b.idx(indexMap.idxOf(inherited)));
}
- docTypeBuildAnyType(documentType.getHeader(), db, indexMap);
+ docTypeBuildAnyType(documentType.getContentStruct(), db, indexMap);
for (DataType dt : sortedList(documentType.getAllTypes().getTypes(),
(a,b) -> a.getName().compareTo(b.getName()))) {
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 2f0814bd664..1240dac8bf1 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
@@ -58,7 +58,7 @@ public class DocumentTypes {
db.
id(documentType.getId()).
name(documentType.getName()).
- headerstruct(documentType.getHeader().getId());
+ headerstruct(documentType.getContentStruct().getId());
Set<Integer> built = new HashSet<>();
for (NewDocumentType inherited : documentType.getInherited()) {
db.inherits(new DocumenttypesConfig.Documenttype.Inherits.Builder().id(inherited.getId()));
@@ -224,7 +224,7 @@ public class DocumentTypes {
DocumenttypesConfig.Documenttype.Referencetype.Builder refBuilder =
new DocumenttypesConfig.Documenttype.Referencetype.Builder();
refBuilder.id(refType.getId());
- refBuilder.target_type_id(type.getTargetType().getId());
+ refBuilder.target_type_id(type.getTargetTypeId());
documentBuilder.referencetype(refBuilder);
}
diff --git a/config-model/src/test/derived/attributeprefetch/summarymap.cfg b/config-model/src/test/derived/attributeprefetch/summarymap.cfg
index 28bc686a266..2e4bec651e7 100644
--- a/config-model/src/test/derived/attributeprefetch/summarymap.cfg
+++ b/config-model/src/test/derived/attributeprefetch/summarymap.cfg
@@ -1,25 +1,25 @@
defaultoutputclass -1
-override[0].field "rankfeatures"
-override[0].command "rankfeatures"
-override[0].arguments ""
-override[1].field "summaryfeatures"
-override[1].command "summaryfeatures"
-override[1].arguments ""
-override[2].field "singlebyte"
-override[2].command "attribute"
-override[2].arguments "singlebyte"
-override[3].field "singleint"
-override[3].command "attribute"
-override[3].arguments "singleint"
-override[4].field "singlelong"
-override[4].command "attribute"
-override[4].arguments "singlelong"
-override[5].field "singlefloat"
-override[5].command "attribute"
-override[5].arguments "singlefloat"
-override[6].field "singledouble"
-override[6].command "attribute"
-override[6].arguments "singledouble"
-override[7].field "singlestring"
-override[7].command "attribute"
-override[7].arguments "singlestring" \ No newline at end of file
+override[].field "rankfeatures"
+override[].command "rankfeatures"
+override[].arguments ""
+override[].field "summaryfeatures"
+override[].command "summaryfeatures"
+override[].arguments ""
+override[].field "singlebyte"
+override[].command "attribute"
+override[].arguments "singlebyte"
+override[].field "singleint"
+override[].command "attribute"
+override[].arguments "singleint"
+override[].field "singlelong"
+override[].command "attribute"
+override[].arguments "singlelong"
+override[].field "singlefloat"
+override[].command "attribute"
+override[].arguments "singlefloat"
+override[].field "singledouble"
+override[].command "attribute"
+override[].arguments "singledouble"
+override[].field "singlestring"
+override[].command "attribute"
+override[].arguments "singlestring"
diff --git a/config-model/src/test/derived/complex/summarymap.cfg b/config-model/src/test/derived/complex/summarymap.cfg
index f7ad249ae86..6f65e7d3bc3 100644
--- a/config-model/src/test/derived/complex/summarymap.cfg
+++ b/config-model/src/test/derived/complex/summarymap.cfg
@@ -1,31 +1,31 @@
defaultoutputclass -1
-override[0].field "dyntitle"
-override[0].command "dynamicteaser"
-override[0].arguments "dyntitle"
-override[1].field "rankfeatures"
-override[1].command "rankfeatures"
-override[1].arguments ""
-override[2].field "summaryfeatures"
-override[2].command "summaryfeatures"
-override[2].arguments ""
-override[3].field "year_sub"
-override[3].command "attribute"
-override[3].arguments "year_sub"
-override[4].field "prefixenabled"
-override[4].command "attribute"
-override[4].arguments "prefixenabled"
-override[5].field "fleeting2"
-override[5].command "attribute"
-override[5].arguments "fleeting2"
-override[6].field "foundat"
-override[6].command "attribute"
-override[6].arguments "foundat"
-override[7].field "collapseby"
-override[7].command "attribute"
-override[7].arguments "collapseby"
-override[8].field "ts"
-override[8].command "attribute"
-override[8].arguments "ts"
-override[9].field "combineda"
-override[9].command "attribute"
-override[9].arguments "combineda" \ No newline at end of file
+override[].field "dyntitle"
+override[].command "dynamicteaser"
+override[].arguments "dyntitle"
+override[].field "rankfeatures"
+override[].command "rankfeatures"
+override[].arguments ""
+override[].field "summaryfeatures"
+override[].command "summaryfeatures"
+override[].arguments ""
+override[].field "year_sub"
+override[].command "attribute"
+override[].arguments "year_sub"
+override[].field "prefixenabled"
+override[].command "attribute"
+override[].arguments "prefixenabled"
+override[].field "fleeting2"
+override[].command "attribute"
+override[].arguments "fleeting2"
+override[].field "foundat"
+override[].command "attribute"
+override[].arguments "foundat"
+override[].field "collapseby"
+override[].command "attribute"
+override[].arguments "collapseby"
+override[].field "ts"
+override[].command "attribute"
+override[].arguments "ts"
+override[].field "combineda"
+override[].command "attribute"
+override[].arguments "combineda"
diff --git a/config-model/src/test/derived/declstruct/documentmanager.cfg b/config-model/src/test/derived/declstruct/documentmanager.cfg
index d9c48ddc42f..0286af0eade 100644
--- a/config-model/src/test/derived/declstruct/documentmanager.cfg
+++ b/config-model/src/test/derived/declstruct/documentmanager.cfg
@@ -1,89 +1,89 @@
enablecompression false
usev8geopositions false
-doctype[0].name "document"
-doctype[0].idx 10000
-doctype[0].contentstruct 10001
-doctype[0].primitivetype[0].idx 10002
-doctype[0].primitivetype[0].name "bool"
-doctype[0].primitivetype[1].idx 10003
-doctype[0].primitivetype[1].name "byte"
-doctype[0].primitivetype[2].idx 10004
-doctype[0].primitivetype[2].name "double"
-doctype[0].primitivetype[3].idx 10005
-doctype[0].primitivetype[3].name "float"
-doctype[0].primitivetype[4].idx 10006
-doctype[0].primitivetype[4].name "float16"
-doctype[0].primitivetype[5].idx 10007
-doctype[0].primitivetype[5].name "int"
-doctype[0].primitivetype[6].idx 10008
-doctype[0].primitivetype[6].name "long"
-doctype[0].primitivetype[7].idx 10010
-doctype[0].primitivetype[7].name "predicate"
-doctype[0].primitivetype[8].idx 10011
-doctype[0].primitivetype[8].name "raw"
-doctype[0].primitivetype[9].idx 10012
-doctype[0].primitivetype[9].name "string"
-doctype[0].primitivetype[10].idx 10014
-doctype[0].primitivetype[10].name "uri"
-doctype[0].wsettype[0].idx 10013
-doctype[0].wsettype[0].elementtype 10012
-doctype[0].wsettype[0].createifnonexistent true
-doctype[0].wsettype[0].removeifzero true
-doctype[0].structtype[0].idx 10001
-doctype[0].structtype[0].name "document.header"
-doctype[0].structtype[1].idx 10009
-doctype[0].structtype[1].name "position"
-doctype[0].structtype[1].field[0].name "x"
-doctype[0].structtype[1].field[0].internalid 914677694
-doctype[0].structtype[1].field[0].type 10007
-doctype[0].structtype[1].field[1].name "y"
-doctype[0].structtype[1].field[1].internalid 900009410
-doctype[0].structtype[1].field[1].type 10007
-doctype[1].name "common"
-doctype[1].idx 10015
-doctype[1].inherits[0].idx 10000
-doctype[1].contentstruct 10016
-doctype[1].structtype[0].idx 10016
-doctype[1].structtype[0].name "common.header"
-doctype[1].structtype[1].idx 10017
-doctype[1].structtype[1].name "mystruct"
-doctype[1].structtype[1].field[0].name "f0"
-doctype[1].structtype[1].field[0].internalid 111558427
-doctype[1].structtype[1].field[0].type 10012
-doctype[2].name "foo"
-doctype[2].idx 10018
-doctype[2].inherits[0].idx 10000
-doctype[2].inherits[1].idx 10015
-doctype[2].contentstruct 10019
-doctype[2].structtype[0].idx 10019
-doctype[2].structtype[0].name "foo.header"
-doctype[2].structtype[1].idx 10020
-doctype[2].structtype[1].name "mystructinfoo"
-doctype[2].structtype[1].field[0].name "f1"
-doctype[2].structtype[1].field[0].internalid 1911889118
-doctype[2].structtype[1].field[0].type 10012
-doctype[3].name "bar"
-doctype[3].idx 10021
-doctype[3].inherits[0].idx 10000
-doctype[3].inherits[1].idx 10015
-doctype[3].contentstruct 10022
-doctype[3].structtype[0].idx 10022
-doctype[3].structtype[0].name "bar.header"
-doctype[3].structtype[1].idx 10023
-doctype[3].structtype[1].name "mystructinbar"
-doctype[3].structtype[1].field[0].name "f2"
-doctype[3].structtype[1].field[0].internalid 84639357
-doctype[3].structtype[1].field[0].type 10012
-doctype[4].name "foobar"
-doctype[4].idx 10024
-doctype[4].inherits[0].idx 10000
-doctype[4].inherits[1].idx 10018
-doctype[4].inherits[2].idx 10021
-doctype[4].contentstruct 10025
-doctype[4].structtype[0].idx 10025
-doctype[4].structtype[0].name "foobar.header"
-doctype[4].structtype[1].idx 10026
-doctype[4].structtype[1].name "mystructinfoobar"
-doctype[4].structtype[1].field[0].name "f3"
-doctype[4].structtype[1].field[0].internalid 63940691
-doctype[4].structtype[1].field[0].type 10012
+doctype[].name "document"
+doctype[].idx 10000
+doctype[].contentstruct 10001
+doctype[].primitivetype[].idx 10002
+doctype[].primitivetype[].name "bool"
+doctype[].primitivetype[].idx 10003
+doctype[].primitivetype[].name "byte"
+doctype[].primitivetype[].idx 10004
+doctype[].primitivetype[].name "double"
+doctype[].primitivetype[].idx 10005
+doctype[].primitivetype[].name "float"
+doctype[].primitivetype[].idx 10006
+doctype[].primitivetype[].name "float16"
+doctype[].primitivetype[].idx 10007
+doctype[].primitivetype[].name "int"
+doctype[].primitivetype[].idx 10008
+doctype[].primitivetype[].name "long"
+doctype[].primitivetype[].idx 10010
+doctype[].primitivetype[].name "predicate"
+doctype[].primitivetype[].idx 10011
+doctype[].primitivetype[].name "raw"
+doctype[].primitivetype[].idx 10012
+doctype[].primitivetype[].name "string"
+doctype[].primitivetype[].idx 10014
+doctype[].primitivetype[].name "uri"
+doctype[].wsettype[].idx 10013
+doctype[].wsettype[].elementtype 10012
+doctype[].wsettype[].createifnonexistent true
+doctype[].wsettype[].removeifzero true
+doctype[].structtype[].idx 10001
+doctype[].structtype[].name "document.header"
+doctype[].structtype[].idx 10009
+doctype[].structtype[].name "position"
+doctype[].structtype[].field[].name "x"
+doctype[].structtype[].field[].internalid 914677694
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "y"
+doctype[].structtype[].field[].internalid 900009410
+doctype[].structtype[].field[].type 10007
+doctype[].name "common"
+doctype[].idx 10015
+doctype[].inherits[].idx 10000
+doctype[].contentstruct 10016
+doctype[].structtype[].idx 10016
+doctype[].structtype[].name "common.header"
+doctype[].structtype[].idx 10017
+doctype[].structtype[].name "mystruct"
+doctype[].structtype[].field[].name "f0"
+doctype[].structtype[].field[].internalid 111558427
+doctype[].structtype[].field[].type 10012
+doctype[].name "foo"
+doctype[].idx 10018
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10019
+doctype[].structtype[].idx 10019
+doctype[].structtype[].name "foo.header"
+doctype[].structtype[].idx 10020
+doctype[].structtype[].name "mystructinfoo"
+doctype[].structtype[].field[].name "f1"
+doctype[].structtype[].field[].internalid 1911889118
+doctype[].structtype[].field[].type 10012
+doctype[].name "bar"
+doctype[].idx 10021
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10022
+doctype[].structtype[].idx 10022
+doctype[].structtype[].name "bar.header"
+doctype[].structtype[].idx 10023
+doctype[].structtype[].name "mystructinbar"
+doctype[].structtype[].field[].name "f2"
+doctype[].structtype[].field[].internalid 84639357
+doctype[].structtype[].field[].type 10012
+doctype[].name "foobar"
+doctype[].idx 10024
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10018
+doctype[].inherits[].idx 10021
+doctype[].contentstruct 10025
+doctype[].structtype[].idx 10025
+doctype[].structtype[].name "foobar.header"
+doctype[].structtype[].idx 10026
+doctype[].structtype[].name "mystructinfoobar"
+doctype[].structtype[].field[].name "f3"
+doctype[].structtype[].field[].internalid 63940691
+doctype[].structtype[].field[].type 10012
diff --git a/config-model/src/test/derived/duplicate_struct/documentmanager.cfg b/config-model/src/test/derived/duplicate_struct/documentmanager.cfg
new file mode 100644
index 00000000000..077b57df800
--- /dev/null
+++ b/config-model/src/test/derived/duplicate_struct/documentmanager.cfg
@@ -0,0 +1,78 @@
+enablecompression false
+usev8geopositions false
+doctype[].name "document"
+doctype[].idx 10000
+doctype[].contentstruct 10001
+doctype[].primitivetype[].idx 10002
+doctype[].primitivetype[].name "bool"
+doctype[].primitivetype[].idx 10003
+doctype[].primitivetype[].name "byte"
+doctype[].primitivetype[].idx 10004
+doctype[].primitivetype[].name "double"
+doctype[].primitivetype[].idx 10005
+doctype[].primitivetype[].name "float"
+doctype[].primitivetype[].idx 10006
+doctype[].primitivetype[].name "float16"
+doctype[].primitivetype[].idx 10007
+doctype[].primitivetype[].name "int"
+doctype[].primitivetype[].idx 10008
+doctype[].primitivetype[].name "long"
+doctype[].primitivetype[].idx 10010
+doctype[].primitivetype[].name "predicate"
+doctype[].primitivetype[].idx 10011
+doctype[].primitivetype[].name "raw"
+doctype[].primitivetype[].idx 10012
+doctype[].primitivetype[].name "string"
+doctype[].primitivetype[].idx 10014
+doctype[].primitivetype[].name "uri"
+doctype[].wsettype[].idx 10013
+doctype[].wsettype[].elementtype 10012
+doctype[].wsettype[].createifnonexistent true
+doctype[].wsettype[].removeifzero true
+doctype[].structtype[].idx 10001
+doctype[].structtype[].name "document.header"
+doctype[].structtype[].idx 10009
+doctype[].structtype[].name "position"
+doctype[].structtype[].field[].name "x"
+doctype[].structtype[].field[].internalid 914677694
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "y"
+doctype[].structtype[].field[].internalid 900009410
+doctype[].structtype[].field[].type 10007
+doctype[].name "foo"
+doctype[].idx 10015
+doctype[].inherits[].idx 10000
+doctype[].contentstruct 10016
+doctype[].fieldsets{[document]}.fields[] "mystuff"
+doctype[].fieldsets{[document]}.fields[] "timestamp"
+doctype[].arraytype[].idx 10017
+doctype[].arraytype[].elementtype 10018
+doctype[].structtype[].idx 10018
+doctype[].structtype[].name "mystruct"
+doctype[].structtype[].field[].name "name"
+doctype[].structtype[].field[].internalid 1160796772
+doctype[].structtype[].field[].type 10012
+doctype[].structtype[].field[].name "company"
+doctype[].structtype[].field[].internalid 2010814026
+doctype[].structtype[].field[].type 10012
+doctype[].structtype[].idx 10016
+doctype[].structtype[].name "foo.header"
+doctype[].structtype[].field[].name "timestamp"
+doctype[].structtype[].field[].internalid 808678733
+doctype[].structtype[].field[].type 10008
+doctype[].structtype[].field[].name "mystuff"
+doctype[].structtype[].field[].internalid 885106505
+doctype[].structtype[].field[].type 10017
+doctype[].name "foobar"
+doctype[].idx 10019
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10020
+doctype[].fieldsets{[document]}.fields[] "mystuff"
+doctype[].fieldsets{[document]}.fields[] "timestamp"
+doctype[].fieldsets{[document]}.fields[] "title"
+doctype[].structtype[].idx 10020
+doctype[].structtype[].name "foobar.header"
+doctype[].structtype[].field[].name "title"
+doctype[].structtype[].field[].internalid 567626448
+doctype[].structtype[].field[].type 10012
diff --git a/config-model/src/test/derived/duplicate_struct/documenttypes.cfg b/config-model/src/test/derived/duplicate_struct/documenttypes.cfg
new file mode 100644
index 00000000000..1b897214d73
--- /dev/null
+++ b/config-model/src/test/derived/duplicate_struct/documenttypes.cfg
@@ -0,0 +1,100 @@
+enablecompression false
+usev8geopositions false
+documenttype[].id 97614088
+documenttype[].name "foo"
+documenttype[].version 0
+documenttype[].headerstruct -308552393
+documenttype[].bodystruct 0
+documenttype[].inherits[].id 8
+documenttype[].datatype[].id -2092985853
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "mystruct"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "name"
+documenttype[].datatype[].sstruct.field[].id 1160796772
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "company"
+documenttype[].datatype[].sstruct.field[].id 2010814026
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].id 759956026
+documenttype[].datatype[].type ARRAY
+documenttype[].datatype[].array.element.id -2092985853
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name ""
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].id -308552393
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "foo.header"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "timestamp"
+documenttype[].datatype[].sstruct.field[].id 808678733
+documenttype[].datatype[].sstruct.field[].datatype 4
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "mystuff"
+documenttype[].datatype[].sstruct.field[].id 885106505
+documenttype[].datatype[].sstruct.field[].datatype 759956026
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].fieldsets{[document]}.fields[] "mystuff"
+documenttype[].fieldsets{[document]}.fields[] "timestamp"
+documenttype[].id 378030095
+documenttype[].name "foobar"
+documenttype[].version 0
+documenttype[].headerstruct -1365874608
+documenttype[].bodystruct 0
+documenttype[].inherits[].id 8
+documenttype[].inherits[].id 97614088
+documenttype[].datatype[].id -1365874608
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "foobar.header"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "title"
+documenttype[].datatype[].sstruct.field[].id 567626448
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].fieldsets{[document]}.fields[] "mystuff"
+documenttype[].fieldsets{[document]}.fields[] "timestamp"
+documenttype[].fieldsets{[document]}.fields[] "title"
diff --git a/config-model/src/test/derived/duplicate_struct/foo.sd b/config-model/src/test/derived/duplicate_struct/foo.sd
new file mode 100644
index 00000000000..8447b0440cb
--- /dev/null
+++ b/config-model/src/test/derived/duplicate_struct/foo.sd
@@ -0,0 +1,17 @@
+# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+search foo {
+ document foo {
+ field timestamp type long {
+ indexing: summary | attribute
+ }
+ field mystuff type array<mystruct> {
+ indexing: summary
+ }
+ }
+
+ struct mystruct {
+ field name type string { }
+ field company type string { }
+ }
+}
diff --git a/config-model/src/test/derived/duplicate_struct/foobar.sd b/config-model/src/test/derived/duplicate_struct/foobar.sd
new file mode 100644
index 00000000000..7ef4fb5dbe1
--- /dev/null
+++ b/config-model/src/test/derived/duplicate_struct/foobar.sd
@@ -0,0 +1,16 @@
+# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+search foobar {
+ document foobar inherits foo {
+ field title type string {
+ indexing: summary | index
+ }
+ }
+
+ struct mystruct {
+ field name type string { }
+ field company type string { }
+ }
+
+}
+
diff --git a/config-model/src/test/derived/function_arguments/rank-profiles.cfg b/config-model/src/test/derived/function_arguments/rank-profiles.cfg
index 318b0303a75..007c671229e 100644
--- a/config-model/src/test/derived/function_arguments/rank-profiles.cfg
+++ b/config-model/src/test/derived/function_arguments/rank-profiles.cfg
@@ -68,4 +68,4 @@ rankprofile[].fef.property[].value "rankingExpression(my_func@a03bffb2024104a4)"
rankprofile[].fef.property[].name "vespa.type.attribute.t1"
rankprofile[].fef.property[].value "tensor<float>(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.t2"
-rankprofile[].fef.property[].value "tensor<float>(x{})" \ No newline at end of file
+rankprofile[].fef.property[].value "tensor<float>(x{})"
diff --git a/config-model/src/test/derived/function_arguments_with_expressions/rank-profiles.cfg b/config-model/src/test/derived/function_arguments_with_expressions/rank-profiles.cfg
index 5e7b38fc264..650bc4cb15b 100644
--- a/config-model/src/test/derived/function_arguments_with_expressions/rank-profiles.cfg
+++ b/config-model/src/test/derived/function_arguments_with_expressions/rank-profiles.cfg
@@ -102,4 +102,4 @@ rankprofile[].fef.property[].value "rankingExpression(my_func@93366be10bade547)"
rankprofile[].fef.property[].name "vespa.type.attribute.t1"
rankprofile[].fef.property[].value "tensor<float>(x{})"
rankprofile[].fef.property[].name "vespa.type.attribute.t2"
-rankprofile[].fef.property[].value "tensor<float>(x{})" \ No newline at end of file
+rankprofile[].fef.property[].value "tensor<float>(x{})"
diff --git a/config-model/src/test/derived/imported_fields_inherited_reference/documenttypes.cfg b/config-model/src/test/derived/imported_fields_inherited_reference/documenttypes.cfg
index 311c85a6bb1..c3ea1318d33 100644
--- a/config-model/src/test/derived/imported_fields_inherited_reference/documenttypes.cfg
+++ b/config-model/src/test/derived/imported_fields_inherited_reference/documenttypes.cfg
@@ -25,7 +25,7 @@ documenttype[].datatype[].sstruct.field[].name "ref_from_a"
documenttype[].datatype[].sstruct.field[].id 300427062
documenttype[].datatype[].sstruct.field[].datatype 427398467
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].fieldsets{[]}.fields[] "ref_from_a"
+documenttype[].fieldsets{[document]}.fields[] "ref_from_a"
documenttype[].referencetype[].id 427398467
documenttype[].referencetype[].target_type_id 1175161836
documenttype[].id -94852095
@@ -54,8 +54,8 @@ documenttype[].datatype[].sstruct.field[].name "ref_from_b"
documenttype[].datatype[].sstruct.field[].id 185778735
documenttype[].datatype[].sstruct.field[].datatype 427398467
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].fieldsets{[]}.fields[] "ref_from_a"
-documenttype[].fieldsets{[]}.fields[] "ref_from_b"
+documenttype[].fieldsets{[document]}.fields[] "ref_from_a"
+documenttype[].fieldsets{[document]}.fields[] "ref_from_b"
documenttype[].id -94851134
documenttype[].name "child_c"
documenttype[].version 0
@@ -78,8 +78,8 @@ documenttype[].datatype[].sstruct.compression.type NONE
documenttype[].datatype[].sstruct.compression.level 0
documenttype[].datatype[].sstruct.compression.threshold 95
documenttype[].datatype[].sstruct.compression.minsize 200
-documenttype[].fieldsets{[]}.fields[] "ref_from_a"
-documenttype[].fieldsets{[]}.fields[] "ref_from_b"
+documenttype[].fieldsets{[document]}.fields[] "ref_from_a"
+documenttype[].fieldsets{[document]}.fields[] "ref_from_b"
documenttype[].importedfield[].name "from_a_int_field"
documenttype[].importedfield[].name "from_b_int_field"
documenttype[].id 1175161836
@@ -107,5 +107,4 @@ documenttype[].datatype[].sstruct.field[].name "int_field"
documenttype[].datatype[].sstruct.field[].id 2128822283
documenttype[].datatype[].sstruct.field[].datatype 0
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].fieldsets{[]}.fields[] "int_field"
-
+documenttype[].fieldsets{[document]}.fields[] "int_field"
diff --git a/config-model/src/test/derived/imported_position_field/imported-fields.cfg b/config-model/src/test/derived/imported_position_field/imported-fields.cfg
index 5ce853e17f2..72aebeaafc1 100644
--- a/config-model/src/test/derived/imported_position_field/imported-fields.cfg
+++ b/config-model/src/test/derived/imported_position_field/imported-fields.cfg
@@ -1,3 +1,3 @@
-attribute[0].name "my_pos_zcurve"
-attribute[0].referencefield "parent_ref"
-attribute[0].targetfield "pos_zcurve"
+attribute[].name "my_pos_zcurve"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "pos_zcurve"
diff --git a/config-model/src/test/derived/imported_position_field/summarymap.cfg b/config-model/src/test/derived/imported_position_field/summarymap.cfg
index 42b6e811ee6..8956a146b74 100644
--- a/config-model/src/test/derived/imported_position_field/summarymap.cfg
+++ b/config-model/src/test/derived/imported_position_field/summarymap.cfg
@@ -1,7 +1,7 @@
defaultoutputclass -1
-override[0].field "rankfeatures"
-override[0].command "rankfeatures"
-override[0].arguments ""
-override[1].field "summaryfeatures"
-override[1].command "summaryfeatures"
-override[1].arguments "" \ No newline at end of file
+override[].field "rankfeatures"
+override[].command "rankfeatures"
+override[].arguments ""
+override[].field "summaryfeatures"
+override[].command "summaryfeatures"
+override[].arguments ""
diff --git a/config-model/src/test/derived/imported_struct_fields/imported-fields.cfg b/config-model/src/test/derived/imported_struct_fields/imported-fields.cfg
index 699a3045075..f5f7ebdc614 100644
--- a/config-model/src/test/derived/imported_struct_fields/imported-fields.cfg
+++ b/config-model/src/test/derived/imported_struct_fields/imported-fields.cfg
@@ -1,21 +1,21 @@
-attribute[0].name "my_elem_array.name"
-attribute[0].referencefield "parent_ref"
-attribute[0].targetfield "elem_array.name"
-attribute[1].name "my_elem_array.weight"
-attribute[1].referencefield "parent_ref"
-attribute[1].targetfield "elem_array.weight"
-attribute[2].name "my_elem_map.key"
-attribute[2].referencefield "parent_ref"
-attribute[2].targetfield "elem_map.key"
-attribute[3].name "my_elem_map.value.name"
-attribute[3].referencefield "parent_ref"
-attribute[3].targetfield "elem_map.value.name"
-attribute[4].name "my_elem_map.value.weight"
-attribute[4].referencefield "parent_ref"
-attribute[4].targetfield "elem_map.value.weight"
-attribute[5].name "my_str_int_map.key"
-attribute[5].referencefield "parent_ref"
-attribute[5].targetfield "str_int_map.key"
-attribute[6].name "my_str_int_map.value"
-attribute[6].referencefield "parent_ref"
-attribute[6].targetfield "str_int_map.value"
+attribute[].name "my_elem_array.name"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "elem_array.name"
+attribute[].name "my_elem_array.weight"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "elem_array.weight"
+attribute[].name "my_elem_map.key"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "elem_map.key"
+attribute[].name "my_elem_map.value.name"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "elem_map.value.name"
+attribute[].name "my_elem_map.value.weight"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "elem_map.value.weight"
+attribute[].name "my_str_int_map.key"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "str_int_map.key"
+attribute[].name "my_str_int_map.value"
+attribute[].referencefield "parent_ref"
+attribute[].targetfield "str_int_map.value"
diff --git a/config-model/src/test/derived/imported_struct_fields/summarymap.cfg b/config-model/src/test/derived/imported_struct_fields/summarymap.cfg
index ccb61354ccb..cd19a75e85f 100644
--- a/config-model/src/test/derived/imported_struct_fields/summarymap.cfg
+++ b/config-model/src/test/derived/imported_struct_fields/summarymap.cfg
@@ -1,25 +1,25 @@
defaultoutputclass -1
-override[0].field "my_elem_array"
-override[0].command "attributecombiner"
-override[0].arguments ""
-override[1].field "my_elem_map"
-override[1].command "attributecombiner"
-override[1].arguments ""
-override[2].field "my_str_int_map"
-override[2].command "attributecombiner"
-override[2].arguments ""
-override[3].field "rankfeatures"
-override[3].command "rankfeatures"
-override[3].arguments ""
-override[4].field "summaryfeatures"
-override[4].command "summaryfeatures"
-override[4].arguments ""
-override[5].field "elem_array_filtered"
-override[5].command "matchedattributeelementsfilter"
-override[5].arguments "my_elem_array"
-override[6].field "elem_map_filtered"
-override[6].command "matchedattributeelementsfilter"
-override[6].arguments "my_elem_map"
-override[7].field "str_int_map_filtered"
-override[7].command "matchedattributeelementsfilter"
-override[7].arguments "my_str_int_map" \ No newline at end of file
+override[].field "my_elem_array"
+override[].command "attributecombiner"
+override[].arguments ""
+override[].field "my_elem_map"
+override[].command "attributecombiner"
+override[].arguments ""
+override[].field "my_str_int_map"
+override[].command "attributecombiner"
+override[].arguments ""
+override[].field "rankfeatures"
+override[].command "rankfeatures"
+override[].arguments ""
+override[].field "summaryfeatures"
+override[].command "summaryfeatures"
+override[].arguments ""
+override[].field "elem_array_filtered"
+override[].command "matchedattributeelementsfilter"
+override[].arguments "my_elem_array"
+override[].field "elem_map_filtered"
+override[].command "matchedattributeelementsfilter"
+override[].arguments "my_elem_map"
+override[].field "str_int_map_filtered"
+override[].command "matchedattributeelementsfilter"
+override[].arguments "my_str_int_map"
diff --git a/config-model/src/test/derived/indexschema/index-info.cfg b/config-model/src/test/derived/indexschema/index-info.cfg
index fd58423b868..4e81a0ae4a8 100644
--- a/config-model/src/test/derived/indexschema/index-info.cfg
+++ b/config-model/src/test/derived/indexschema/index-info.cfg
@@ -114,11 +114,11 @@ indexinfo[].command[].command "type WeightedSet<string>"
indexinfo[].command[].indexname "sh"
indexinfo[].command[].command "index"
indexinfo[].command[].indexname "sh"
+indexinfo[].command[].command "lowercase"
+indexinfo[].command[].indexname "sh"
indexinfo[].command[].command "plain-tokens"
indexinfo[].command[].indexname "sh"
indexinfo[].command[].command "fullurl"
-indexinfo[].command[].indexname "sh"
-indexinfo[].command[].command "lowercase"
indexinfo[].command[].indexname "sh.sh"
indexinfo[].command[].command "fullurl"
indexinfo[].command[].indexname "sh.sh"
diff --git a/config-model/src/test/derived/inheritance/documentmanager.cfg b/config-model/src/test/derived/inheritance/documentmanager.cfg
index 321bf9979cd..f0917864ebd 100644
--- a/config-model/src/test/derived/inheritance/documentmanager.cfg
+++ b/config-model/src/test/derived/inheritance/documentmanager.cfg
@@ -1,106 +1,106 @@
enablecompression false
usev8geopositions false
-doctype[0].name "document"
-doctype[0].idx 10000
-doctype[0].contentstruct 10001
-doctype[0].primitivetype[0].idx 10002
-doctype[0].primitivetype[0].name "bool"
-doctype[0].primitivetype[1].idx 10003
-doctype[0].primitivetype[1].name "byte"
-doctype[0].primitivetype[2].idx 10004
-doctype[0].primitivetype[2].name "double"
-doctype[0].primitivetype[3].idx 10005
-doctype[0].primitivetype[3].name "float"
-doctype[0].primitivetype[4].idx 10006
-doctype[0].primitivetype[4].name "float16"
-doctype[0].primitivetype[5].idx 10007
-doctype[0].primitivetype[5].name "int"
-doctype[0].primitivetype[6].idx 10008
-doctype[0].primitivetype[6].name "long"
-doctype[0].primitivetype[7].idx 10010
-doctype[0].primitivetype[7].name "predicate"
-doctype[0].primitivetype[8].idx 10011
-doctype[0].primitivetype[8].name "raw"
-doctype[0].primitivetype[9].idx 10012
-doctype[0].primitivetype[9].name "string"
-doctype[0].primitivetype[10].idx 10014
-doctype[0].primitivetype[10].name "uri"
-doctype[0].wsettype[0].idx 10013
-doctype[0].wsettype[0].elementtype 10012
-doctype[0].wsettype[0].createifnonexistent true
-doctype[0].wsettype[0].removeifzero true
-doctype[0].structtype[0].idx 10001
-doctype[0].structtype[0].name "document.header"
-doctype[0].structtype[1].idx 10009
-doctype[0].structtype[1].name "position"
-doctype[0].structtype[1].field[0].name "x"
-doctype[0].structtype[1].field[0].internalid 914677694
-doctype[0].structtype[1].field[0].type 10007
-doctype[0].structtype[1].field[1].name "y"
-doctype[0].structtype[1].field[1].internalid 900009410
-doctype[0].structtype[1].field[1].type 10007
-doctype[1].name "grandparent"
-doctype[1].idx 10015
-doctype[1].inherits[0].idx 10000
-doctype[1].contentstruct 10016
-doctype[1].fieldsets{[document]}.fields[0] "onlygrandparent"
-doctype[1].fieldsets{[document]}.fields[1] "overridden"
-doctype[1].structtype[0].idx 10016
-doctype[1].structtype[0].name "grandparent.header"
-doctype[1].structtype[0].field[0].name "onlygrandparent"
-doctype[1].structtype[0].field[0].internalid 1456982690
-doctype[1].structtype[0].field[0].type 10007
-doctype[1].structtype[0].field[1].name "overridden"
-doctype[1].structtype[0].field[1].internalid 1314355415
-doctype[1].structtype[0].field[1].type 10007
-doctype[2].name "mother"
-doctype[2].idx 10017
-doctype[2].inherits[0].idx 10015
-doctype[2].inherits[1].idx 10000
-doctype[2].contentstruct 10018
-doctype[2].fieldsets{[document]}.fields[0] "onlygrandparent"
-doctype[2].fieldsets{[document]}.fields[1] "onlymother"
-doctype[2].fieldsets{[document]}.fields[2] "overridden"
-doctype[2].structtype[0].idx 10018
-doctype[2].structtype[0].name "mother.header"
-doctype[2].structtype[0].field[0].name "onlymother"
-doctype[2].structtype[0].field[0].internalid 1390999339
-doctype[2].structtype[0].field[0].type 10012
-doctype[2].structtype[0].field[1].name "overridden"
-doctype[2].structtype[0].field[1].internalid 1314355415
-doctype[2].structtype[0].field[1].type 10007
-doctype[3].name "father"
-doctype[3].idx 10019
-doctype[3].inherits[0].idx 10015
-doctype[3].inherits[1].idx 10000
-doctype[3].contentstruct 10020
-doctype[3].fieldsets{[document]}.fields[0] "onlyfather"
-doctype[3].fieldsets{[document]}.fields[1] "onlygrandparent"
-doctype[3].fieldsets{[document]}.fields[2] "overridden"
-doctype[3].structtype[0].idx 10020
-doctype[3].structtype[0].name "father.header"
-doctype[3].structtype[0].field[0].name "onlyfather"
-doctype[3].structtype[0].field[0].internalid 1083094308
-doctype[3].structtype[0].field[0].type 10012
-doctype[3].structtype[0].field[1].name "overridden"
-doctype[3].structtype[0].field[1].internalid 1314355415
-doctype[3].structtype[0].field[1].type 10007
-doctype[4].name "child"
-doctype[4].idx 10021
-doctype[4].inherits[0].idx 10000
-doctype[4].inherits[1].idx 10019
-doctype[4].inherits[2].idx 10017
-doctype[4].contentstruct 10022
-doctype[4].fieldsets{[document]}.fields[0] "onlychild"
-doctype[4].fieldsets{[document]}.fields[1] "onlyfather"
-doctype[4].fieldsets{[document]}.fields[2] "onlygrandparent"
-doctype[4].fieldsets{[document]}.fields[3] "onlymother"
-doctype[4].fieldsets{[document]}.fields[4] "overridden"
-doctype[4].structtype[0].idx 10022
-doctype[4].structtype[0].name "child.header"
-doctype[4].structtype[0].field[0].name "onlychild"
-doctype[4].structtype[0].field[0].internalid 1737375598
-doctype[4].structtype[0].field[0].type 10012
-doctype[4].structtype[0].field[1].name "overridden"
-doctype[4].structtype[0].field[1].internalid 1314355415
-doctype[4].structtype[0].field[1].type 10007
+doctype[].name "document"
+doctype[].idx 10000
+doctype[].contentstruct 10001
+doctype[].primitivetype[].idx 10002
+doctype[].primitivetype[].name "bool"
+doctype[].primitivetype[].idx 10003
+doctype[].primitivetype[].name "byte"
+doctype[].primitivetype[].idx 10004
+doctype[].primitivetype[].name "double"
+doctype[].primitivetype[].idx 10005
+doctype[].primitivetype[].name "float"
+doctype[].primitivetype[].idx 10006
+doctype[].primitivetype[].name "float16"
+doctype[].primitivetype[].idx 10007
+doctype[].primitivetype[].name "int"
+doctype[].primitivetype[].idx 10008
+doctype[].primitivetype[].name "long"
+doctype[].primitivetype[].idx 10010
+doctype[].primitivetype[].name "predicate"
+doctype[].primitivetype[].idx 10011
+doctype[].primitivetype[].name "raw"
+doctype[].primitivetype[].idx 10012
+doctype[].primitivetype[].name "string"
+doctype[].primitivetype[].idx 10014
+doctype[].primitivetype[].name "uri"
+doctype[].wsettype[].idx 10013
+doctype[].wsettype[].elementtype 10012
+doctype[].wsettype[].createifnonexistent true
+doctype[].wsettype[].removeifzero true
+doctype[].structtype[].idx 10001
+doctype[].structtype[].name "document.header"
+doctype[].structtype[].idx 10009
+doctype[].structtype[].name "position"
+doctype[].structtype[].field[].name "x"
+doctype[].structtype[].field[].internalid 914677694
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "y"
+doctype[].structtype[].field[].internalid 900009410
+doctype[].structtype[].field[].type 10007
+doctype[].name "grandparent"
+doctype[].idx 10015
+doctype[].inherits[].idx 10000
+doctype[].contentstruct 10016
+doctype[].fieldsets{[document]}.fields[] "onlygrandparent"
+doctype[].fieldsets{[document]}.fields[] "overridden"
+doctype[].structtype[].idx 10016
+doctype[].structtype[].name "grandparent.header"
+doctype[].structtype[].field[].name "onlygrandparent"
+doctype[].structtype[].field[].internalid 1456982690
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "overridden"
+doctype[].structtype[].field[].internalid 1314355415
+doctype[].structtype[].field[].type 10007
+doctype[].name "mother"
+doctype[].idx 10017
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10018
+doctype[].fieldsets{[document]}.fields[] "onlygrandparent"
+doctype[].fieldsets{[document]}.fields[] "onlymother"
+doctype[].fieldsets{[document]}.fields[] "overridden"
+doctype[].structtype[].idx 10018
+doctype[].structtype[].name "mother.header"
+doctype[].structtype[].field[].name "onlymother"
+doctype[].structtype[].field[].internalid 1390999339
+doctype[].structtype[].field[].type 10012
+doctype[].structtype[].field[].name "overridden"
+doctype[].structtype[].field[].internalid 1314355415
+doctype[].structtype[].field[].type 10007
+doctype[].name "father"
+doctype[].idx 10019
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10020
+doctype[].fieldsets{[document]}.fields[] "onlyfather"
+doctype[].fieldsets{[document]}.fields[] "onlygrandparent"
+doctype[].fieldsets{[document]}.fields[] "overridden"
+doctype[].structtype[].idx 10020
+doctype[].structtype[].name "father.header"
+doctype[].structtype[].field[].name "onlyfather"
+doctype[].structtype[].field[].internalid 1083094308
+doctype[].structtype[].field[].type 10012
+doctype[].structtype[].field[].name "overridden"
+doctype[].structtype[].field[].internalid 1314355415
+doctype[].structtype[].field[].type 10007
+doctype[].name "child"
+doctype[].idx 10021
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10019
+doctype[].inherits[].idx 10017
+doctype[].contentstruct 10022
+doctype[].fieldsets{[document]}.fields[] "onlychild"
+doctype[].fieldsets{[document]}.fields[] "onlyfather"
+doctype[].fieldsets{[document]}.fields[] "onlygrandparent"
+doctype[].fieldsets{[document]}.fields[] "onlymother"
+doctype[].fieldsets{[document]}.fields[] "overridden"
+doctype[].structtype[].idx 10022
+doctype[].structtype[].name "child.header"
+doctype[].structtype[].field[].name "onlychild"
+doctype[].structtype[].field[].internalid 1737375598
+doctype[].structtype[].field[].type 10012
+doctype[].structtype[].field[].name "overridden"
+doctype[].structtype[].field[].internalid 1314355415
+doctype[].structtype[].field[].type 10007
diff --git a/config-model/src/test/derived/inheritfromgrandparent/documentmanager.cfg b/config-model/src/test/derived/inheritfromgrandparent/documentmanager.cfg
index f4398e59f0f..8c0ffd50840 100644
--- a/config-model/src/test/derived/inheritfromgrandparent/documentmanager.cfg
+++ b/config-model/src/test/derived/inheritfromgrandparent/documentmanager.cfg
@@ -1,70 +1,70 @@
enablecompression false
usev8geopositions false
-doctype[0].name "document"
-doctype[0].idx 10000
-doctype[0].contentstruct 10001
-doctype[0].primitivetype[0].idx 10002
-doctype[0].primitivetype[0].name "bool"
-doctype[0].primitivetype[1].idx 10003
-doctype[0].primitivetype[1].name "byte"
-doctype[0].primitivetype[2].idx 10004
-doctype[0].primitivetype[2].name "double"
-doctype[0].primitivetype[3].idx 10005
-doctype[0].primitivetype[3].name "float"
-doctype[0].primitivetype[4].idx 10006
-doctype[0].primitivetype[4].name "float16"
-doctype[0].primitivetype[5].idx 10007
-doctype[0].primitivetype[5].name "int"
-doctype[0].primitivetype[6].idx 10008
-doctype[0].primitivetype[6].name "long"
-doctype[0].primitivetype[7].idx 10010
-doctype[0].primitivetype[7].name "predicate"
-doctype[0].primitivetype[8].idx 10011
-doctype[0].primitivetype[8].name "raw"
-doctype[0].primitivetype[9].idx 10012
-doctype[0].primitivetype[9].name "string"
-doctype[0].primitivetype[10].idx 10014
-doctype[0].primitivetype[10].name "uri"
-doctype[0].wsettype[0].idx 10013
-doctype[0].wsettype[0].elementtype 10012
-doctype[0].wsettype[0].createifnonexistent true
-doctype[0].wsettype[0].removeifzero true
-doctype[0].structtype[0].idx 10001
-doctype[0].structtype[0].name "document.header"
-doctype[0].structtype[1].idx 10009
-doctype[0].structtype[1].name "position"
-doctype[0].structtype[1].field[0].name "x"
-doctype[0].structtype[1].field[0].internalid 914677694
-doctype[0].structtype[1].field[0].type 10007
-doctype[0].structtype[1].field[1].name "y"
-doctype[0].structtype[1].field[1].internalid 900009410
-doctype[0].structtype[1].field[1].type 10007
-doctype[1].name "grandparent"
-doctype[1].idx 10015
-doctype[1].inherits[0].idx 10000
-doctype[1].contentstruct 10016
-doctype[1].structtype[0].idx 10016
-doctype[1].structtype[0].name "grandparent.header"
-doctype[1].structtype[1].idx 10017
-doctype[1].structtype[1].name "grandparent_struct"
-doctype[1].structtype[1].field[0].name "grandparent_field"
-doctype[1].structtype[1].field[0].internalid 18801796
-doctype[1].structtype[1].field[0].type 10012
-doctype[2].name "parent"
-doctype[2].idx 10018
-doctype[2].inherits[0].idx 10015
-doctype[2].inherits[1].idx 10000
-doctype[2].contentstruct 10019
-doctype[2].structtype[0].idx 10019
-doctype[2].structtype[0].name "parent.header"
-doctype[3].name "child"
-doctype[3].idx 10020
-doctype[3].inherits[0].idx 10000
-doctype[3].inherits[1].idx 10018
-doctype[3].contentstruct 10021
-doctype[3].fieldsets{[document]}.fields[0] "child_field"
-doctype[3].structtype[0].idx 10021
-doctype[3].structtype[0].name "child.header"
-doctype[3].structtype[0].field[0].name "child_field"
-doctype[3].structtype[0].field[0].internalid 129089854
-doctype[3].structtype[0].field[0].type 10017
+doctype[].name "document"
+doctype[].idx 10000
+doctype[].contentstruct 10001
+doctype[].primitivetype[].idx 10002
+doctype[].primitivetype[].name "bool"
+doctype[].primitivetype[].idx 10003
+doctype[].primitivetype[].name "byte"
+doctype[].primitivetype[].idx 10004
+doctype[].primitivetype[].name "double"
+doctype[].primitivetype[].idx 10005
+doctype[].primitivetype[].name "float"
+doctype[].primitivetype[].idx 10006
+doctype[].primitivetype[].name "float16"
+doctype[].primitivetype[].idx 10007
+doctype[].primitivetype[].name "int"
+doctype[].primitivetype[].idx 10008
+doctype[].primitivetype[].name "long"
+doctype[].primitivetype[].idx 10010
+doctype[].primitivetype[].name "predicate"
+doctype[].primitivetype[].idx 10011
+doctype[].primitivetype[].name "raw"
+doctype[].primitivetype[].idx 10012
+doctype[].primitivetype[].name "string"
+doctype[].primitivetype[].idx 10014
+doctype[].primitivetype[].name "uri"
+doctype[].wsettype[].idx 10013
+doctype[].wsettype[].elementtype 10012
+doctype[].wsettype[].createifnonexistent true
+doctype[].wsettype[].removeifzero true
+doctype[].structtype[].idx 10001
+doctype[].structtype[].name "document.header"
+doctype[].structtype[].idx 10009
+doctype[].structtype[].name "position"
+doctype[].structtype[].field[].name "x"
+doctype[].structtype[].field[].internalid 914677694
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "y"
+doctype[].structtype[].field[].internalid 900009410
+doctype[].structtype[].field[].type 10007
+doctype[].name "grandparent"
+doctype[].idx 10015
+doctype[].inherits[].idx 10000
+doctype[].contentstruct 10016
+doctype[].structtype[].idx 10016
+doctype[].structtype[].name "grandparent.header"
+doctype[].structtype[].idx 10017
+doctype[].structtype[].name "grandparent_struct"
+doctype[].structtype[].field[].name "grandparent_field"
+doctype[].structtype[].field[].internalid 18801796
+doctype[].structtype[].field[].type 10012
+doctype[].name "parent"
+doctype[].idx 10018
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10019
+doctype[].structtype[].idx 10019
+doctype[].structtype[].name "parent.header"
+doctype[].name "child"
+doctype[].idx 10020
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10018
+doctype[].contentstruct 10021
+doctype[].fieldsets{[document]}.fields[] "child_field"
+doctype[].structtype[].idx 10021
+doctype[].structtype[].name "child.header"
+doctype[].structtype[].field[].name "child_field"
+doctype[].structtype[].field[].internalid 129089854
+doctype[].structtype[].field[].type 10017
diff --git a/config-model/src/test/derived/inheritfromparent/documentmanager.cfg b/config-model/src/test/derived/inheritfromparent/documentmanager.cfg
index 1363453017f..186f3c0e3c1 100644
--- a/config-model/src/test/derived/inheritfromparent/documentmanager.cfg
+++ b/config-model/src/test/derived/inheritfromparent/documentmanager.cfg
@@ -1,71 +1,71 @@
enablecompression false
usev8geopositions false
-doctype[0].name "document"
-doctype[0].idx 10000
-doctype[0].contentstruct 10001
-doctype[0].primitivetype[0].idx 10002
-doctype[0].primitivetype[0].name "bool"
-doctype[0].primitivetype[1].idx 10003
-doctype[0].primitivetype[1].name "byte"
-doctype[0].primitivetype[2].idx 10004
-doctype[0].primitivetype[2].name "double"
-doctype[0].primitivetype[3].idx 10005
-doctype[0].primitivetype[3].name "float"
-doctype[0].primitivetype[4].idx 10006
-doctype[0].primitivetype[4].name "float16"
-doctype[0].primitivetype[5].idx 10007
-doctype[0].primitivetype[5].name "int"
-doctype[0].primitivetype[6].idx 10008
-doctype[0].primitivetype[6].name "long"
-doctype[0].primitivetype[7].idx 10010
-doctype[0].primitivetype[7].name "predicate"
-doctype[0].primitivetype[8].idx 10011
-doctype[0].primitivetype[8].name "raw"
-doctype[0].primitivetype[9].idx 10012
-doctype[0].primitivetype[9].name "string"
-doctype[0].primitivetype[10].idx 10014
-doctype[0].primitivetype[10].name "uri"
-doctype[0].wsettype[0].idx 10013
-doctype[0].wsettype[0].elementtype 10012
-doctype[0].wsettype[0].createifnonexistent true
-doctype[0].wsettype[0].removeifzero true
-doctype[0].structtype[0].idx 10001
-doctype[0].structtype[0].name "document.header"
-doctype[0].structtype[1].idx 10009
-doctype[0].structtype[1].name "position"
-doctype[0].structtype[1].field[0].name "x"
-doctype[0].structtype[1].field[0].internalid 914677694
-doctype[0].structtype[1].field[0].type 10007
-doctype[0].structtype[1].field[1].name "y"
-doctype[0].structtype[1].field[1].internalid 900009410
-doctype[0].structtype[1].field[1].type 10007
-doctype[1].name "parent"
-doctype[1].idx 10015
-doctype[1].inherits[0].idx 10000
-doctype[1].contentstruct 10016
-doctype[1].fieldsets{[document]}.fields[0] "weight_src"
-doctype[1].structtype[0].idx 10016
-doctype[1].structtype[0].name "parent.header"
-doctype[1].structtype[0].field[0].name "weight_src"
-doctype[1].structtype[0].field[0].internalid 1225660233
-doctype[1].structtype[0].field[0].type 10005
-doctype[1].structtype[0].field[1].name "weight"
-doctype[1].structtype[0].field[1].internalid 1001392207
-doctype[1].structtype[0].field[1].type 10005
-doctype[1].structtype[1].idx 10017
-doctype[1].structtype[1].name "parent_struct"
-doctype[1].structtype[1].field[0].name "parent_field"
-doctype[1].structtype[1].field[0].internalid 933533022
-doctype[1].structtype[1].field[0].type 10012
-doctype[2].name "child"
-doctype[2].idx 10018
-doctype[2].inherits[0].idx 10000
-doctype[2].inherits[1].idx 10015
-doctype[2].contentstruct 10019
-doctype[2].fieldsets{[document]}.fields[0] "child_field"
-doctype[2].fieldsets{[document]}.fields[1] "weight_src"
-doctype[2].structtype[0].idx 10019
-doctype[2].structtype[0].name "child.header"
-doctype[2].structtype[0].field[0].name "child_field"
-doctype[2].structtype[0].field[0].internalid 1814271363
-doctype[2].structtype[0].field[0].type 10017
+doctype[].name "document"
+doctype[].idx 10000
+doctype[].contentstruct 10001
+doctype[].primitivetype[].idx 10002
+doctype[].primitivetype[].name "bool"
+doctype[].primitivetype[].idx 10003
+doctype[].primitivetype[].name "byte"
+doctype[].primitivetype[].idx 10004
+doctype[].primitivetype[].name "double"
+doctype[].primitivetype[].idx 10005
+doctype[].primitivetype[].name "float"
+doctype[].primitivetype[].idx 10006
+doctype[].primitivetype[].name "float16"
+doctype[].primitivetype[].idx 10007
+doctype[].primitivetype[].name "int"
+doctype[].primitivetype[].idx 10008
+doctype[].primitivetype[].name "long"
+doctype[].primitivetype[].idx 10010
+doctype[].primitivetype[].name "predicate"
+doctype[].primitivetype[].idx 10011
+doctype[].primitivetype[].name "raw"
+doctype[].primitivetype[].idx 10012
+doctype[].primitivetype[].name "string"
+doctype[].primitivetype[].idx 10014
+doctype[].primitivetype[].name "uri"
+doctype[].wsettype[].idx 10013
+doctype[].wsettype[].elementtype 10012
+doctype[].wsettype[].createifnonexistent true
+doctype[].wsettype[].removeifzero true
+doctype[].structtype[].idx 10001
+doctype[].structtype[].name "document.header"
+doctype[].structtype[].idx 10009
+doctype[].structtype[].name "position"
+doctype[].structtype[].field[].name "x"
+doctype[].structtype[].field[].internalid 914677694
+doctype[].structtype[].field[].type 10007
+doctype[].structtype[].field[].name "y"
+doctype[].structtype[].field[].internalid 900009410
+doctype[].structtype[].field[].type 10007
+doctype[].name "parent"
+doctype[].idx 10015
+doctype[].inherits[].idx 10000
+doctype[].contentstruct 10016
+doctype[].fieldsets{[document]}.fields[] "weight_src"
+doctype[].structtype[].idx 10016
+doctype[].structtype[].name "parent.header"
+doctype[].structtype[].field[].name "weight_src"
+doctype[].structtype[].field[].internalid 1225660233
+doctype[].structtype[].field[].type 10005
+doctype[].structtype[].field[].name "weight"
+doctype[].structtype[].field[].internalid 1001392207
+doctype[].structtype[].field[].type 10005
+doctype[].structtype[].idx 10017
+doctype[].structtype[].name "parent_struct"
+doctype[].structtype[].field[].name "parent_field"
+doctype[].structtype[].field[].internalid 933533022
+doctype[].structtype[].field[].type 10012
+doctype[].name "child"
+doctype[].idx 10018
+doctype[].inherits[].idx 10000
+doctype[].inherits[].idx 10015
+doctype[].contentstruct 10019
+doctype[].fieldsets{[document]}.fields[] "child_field"
+doctype[].fieldsets{[document]}.fields[] "weight_src"
+doctype[].structtype[].idx 10019
+doctype[].structtype[].name "child.header"
+doctype[].structtype[].field[].name "child_field"
+doctype[].structtype[].field[].internalid 1814271363
+doctype[].structtype[].field[].type 10017
diff --git a/config-model/src/test/derived/inheritfromparent/documenttypes.cfg b/config-model/src/test/derived/inheritfromparent/documenttypes.cfg
index ea7a49b1acf..da65510ee5a 100644
--- a/config-model/src/test/derived/inheritfromparent/documenttypes.cfg
+++ b/config-model/src/test/derived/inheritfromparent/documenttypes.cfg
@@ -6,7 +6,7 @@ documenttype[].version 0
documenttype[].headerstruct 836075987
documenttype[].bodystruct 0
documenttype[].inherits[].id 8
-documenttype[].datatype[].id 1091188812
+documenttype[].datatype[].id 836075987
documenttype[].datatype[].type STRUCT
documenttype[].datatype[].array.element.id 0
documenttype[].datatype[].map.key.id 0
@@ -15,17 +15,21 @@ documenttype[].datatype[].wset.key.id 0
documenttype[].datatype[].wset.createifnonexistent false
documenttype[].datatype[].wset.removeifzero false
documenttype[].datatype[].annotationref.annotation.id 0
-documenttype[].datatype[].sstruct.name "parent_struct"
+documenttype[].datatype[].sstruct.name "parent.header"
documenttype[].datatype[].sstruct.version 0
documenttype[].datatype[].sstruct.compression.type NONE
documenttype[].datatype[].sstruct.compression.level 0
documenttype[].datatype[].sstruct.compression.threshold 95
documenttype[].datatype[].sstruct.compression.minsize 200
-documenttype[].datatype[].sstruct.field[].name "parent_field"
-documenttype[].datatype[].sstruct.field[].id 933533022
-documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].name "weight_src"
+documenttype[].datatype[].sstruct.field[].id 1225660233
+documenttype[].datatype[].sstruct.field[].datatype 1
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].datatype[].id 836075987
+documenttype[].datatype[].sstruct.field[].name "weight"
+documenttype[].datatype[].sstruct.field[].id 1001392207
+documenttype[].datatype[].sstruct.field[].datatype 1
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].id 1091188812
documenttype[].datatype[].type STRUCT
documenttype[].datatype[].array.element.id 0
documenttype[].datatype[].map.key.id 0
@@ -34,21 +38,17 @@ documenttype[].datatype[].wset.key.id 0
documenttype[].datatype[].wset.createifnonexistent false
documenttype[].datatype[].wset.removeifzero false
documenttype[].datatype[].annotationref.annotation.id 0
-documenttype[].datatype[].sstruct.name "parent.header"
+documenttype[].datatype[].sstruct.name "parent_struct"
documenttype[].datatype[].sstruct.version 0
documenttype[].datatype[].sstruct.compression.type NONE
documenttype[].datatype[].sstruct.compression.level 0
documenttype[].datatype[].sstruct.compression.threshold 95
documenttype[].datatype[].sstruct.compression.minsize 200
-documenttype[].datatype[].sstruct.field[].name "weight_src"
-documenttype[].datatype[].sstruct.field[].id 1225660233
-documenttype[].datatype[].sstruct.field[].datatype 1
-documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].datatype[].sstruct.field[].name "weight"
-documenttype[].datatype[].sstruct.field[].id 1001392207
-documenttype[].datatype[].sstruct.field[].datatype 1
+documenttype[].datatype[].sstruct.field[].name "parent_field"
+documenttype[].datatype[].sstruct.field[].id 933533022
+documenttype[].datatype[].sstruct.field[].datatype 2
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].fieldsets{[]}.fields[] "weight_src"
+documenttype[].fieldsets{[document]}.fields[] "weight_src"
documenttype[].id 746267614
documenttype[].name "child"
documenttype[].version 0
@@ -75,5 +75,5 @@ documenttype[].datatype[].sstruct.field[].name "child_field"
documenttype[].datatype[].sstruct.field[].id 1814271363
documenttype[].datatype[].sstruct.field[].datatype 1091188812
documenttype[].datatype[].sstruct.field[].detailedtype ""
-documenttype[].fieldsets{[]}.fields[] "child_field"
-documenttype[].fieldsets{[]}.fields[] "weight_src"
+documenttype[].fieldsets{[document]}.fields[] "child_field"
+documenttype[].fieldsets{[document]}.fields[] "weight_src"
diff --git a/config-model/src/test/derived/inheritstruct/index-info.cfg b/config-model/src/test/derived/inheritstruct/index-info.cfg
index 5afa91ea1bb..9c880f7b3f4 100644
--- a/config-model/src/test/derived/inheritstruct/index-info.cfg
+++ b/config-model/src/test/derived/inheritstruct/index-info.cfg
@@ -1,51 +1,51 @@
-indexinfo[0].name "child"
-indexinfo[0].command[0].indexname "sddocname"
-indexinfo[0].command[0].command "index"
-indexinfo[0].command[1].indexname "sddocname"
-indexinfo[0].command[1].command "word"
-indexinfo[0].command[2].indexname "child_struct_field.my_str"
-indexinfo[0].command[2].command "index"
-indexinfo[0].command[3].indexname "child_struct_field.my_str"
-indexinfo[0].command[3].command "lowercase"
-indexinfo[0].command[4].indexname "child_struct_field.my_str"
-indexinfo[0].command[4].command "stem:BEST"
-indexinfo[0].command[5].indexname "child_struct_field.my_str"
-indexinfo[0].command[5].command "normalize"
-indexinfo[0].command[6].indexname "child_struct_field.my_str"
-indexinfo[0].command[6].command "plain-tokens"
-indexinfo[0].command[7].indexname "child_struct_field.my_str"
-indexinfo[0].command[7].command "type string"
-indexinfo[0].command[8].indexname "child_struct_field"
-indexinfo[0].command[8].command "index"
-indexinfo[0].command[9].indexname "child_struct_field"
-indexinfo[0].command[9].command "lowercase"
-indexinfo[0].command[10].indexname "child_struct_field"
-indexinfo[0].command[10].command "plain-tokens"
-indexinfo[0].command[11].indexname "child_struct_field"
-indexinfo[0].command[11].command "type my_struct"
-indexinfo[0].command[12].indexname "other_field.my_str"
-indexinfo[0].command[12].command "index"
-indexinfo[0].command[13].indexname "other_field.my_str"
-indexinfo[0].command[13].command "type string"
-indexinfo[0].command[14].indexname "other_field.my_int"
-indexinfo[0].command[14].command "index"
-indexinfo[0].command[15].indexname "other_field.my_int"
-indexinfo[0].command[15].command "numerical"
-indexinfo[0].command[16].indexname "other_field.my_int"
-indexinfo[0].command[16].command "type int"
-indexinfo[0].command[17].indexname "other_field"
-indexinfo[0].command[17].command "index"
-indexinfo[0].command[18].indexname "other_field"
-indexinfo[0].command[18].command "type other_struct"
-indexinfo[0].command[19].indexname "wrapped_field.wrapped.my_str"
-indexinfo[0].command[19].command "index"
-indexinfo[0].command[20].indexname "wrapped_field.wrapped.my_str"
-indexinfo[0].command[20].command "type string"
-indexinfo[0].command[21].indexname "wrapped_field.wrapped"
-indexinfo[0].command[21].command "index"
-indexinfo[0].command[22].indexname "wrapped_field.wrapped"
-indexinfo[0].command[22].command "type my_struct"
-indexinfo[0].command[23].indexname "wrapped_field"
-indexinfo[0].command[23].command "index"
-indexinfo[0].command[24].indexname "wrapped_field"
-indexinfo[0].command[24].command "type wrapper" \ No newline at end of file
+indexinfo[].name "child"
+indexinfo[].command[].indexname "sddocname"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "sddocname"
+indexinfo[].command[].command "word"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "lowercase"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "stem:BEST"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "normalize"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "plain-tokens"
+indexinfo[].command[].indexname "child_struct_field.my_str"
+indexinfo[].command[].command "type string"
+indexinfo[].command[].indexname "child_struct_field"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "child_struct_field"
+indexinfo[].command[].command "lowercase"
+indexinfo[].command[].indexname "child_struct_field"
+indexinfo[].command[].command "plain-tokens"
+indexinfo[].command[].indexname "child_struct_field"
+indexinfo[].command[].command "type my_struct"
+indexinfo[].command[].indexname "other_field.my_str"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "other_field.my_str"
+indexinfo[].command[].command "type string"
+indexinfo[].command[].indexname "other_field.my_int"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "other_field.my_int"
+indexinfo[].command[].command "numerical"
+indexinfo[].command[].indexname "other_field.my_int"
+indexinfo[].command[].command "type int"
+indexinfo[].command[].indexname "other_field"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "other_field"
+indexinfo[].command[].command "type other_struct"
+indexinfo[].command[].indexname "wrapped_field.wrapped.my_str"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "wrapped_field.wrapped.my_str"
+indexinfo[].command[].command "type string"
+indexinfo[].command[].indexname "wrapped_field.wrapped"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "wrapped_field.wrapped"
+indexinfo[].command[].command "type my_struct"
+indexinfo[].command[].indexname "wrapped_field"
+indexinfo[].command[].command "index"
+indexinfo[].command[].indexname "wrapped_field"
+indexinfo[].command[].command "type wrapper"
diff --git a/config-model/src/test/derived/language/ilscripts.cfg b/config-model/src/test/derived/language/ilscripts.cfg
index cafc7feafb8..4858788095c 100644
--- a/config-model/src/test/derived/language/ilscripts.cfg
+++ b/config-model/src/test/derived/language/ilscripts.cfg
@@ -6,4 +6,4 @@ ilscript[].docfield[] "title"
ilscript[].content[] "clear_state | guard { input language | tokenize normalize stem:\"BEST\" | summary language | index language | set_language; }"
ilscript[].content[] "clear_state | guard { input title | tokenize normalize stem:\"BEST\" | index titlebest; }"
ilscript[].content[] "clear_state | guard { input title | tokenize normalize | index titlenone; }"
-ilscript[].content[] "clear_state | guard { input title | tokenize normalize stem:\"BEST\" | summary title | index title; }" \ No newline at end of file
+ilscript[].content[] "clear_state | guard { input title | tokenize normalize stem:\"BEST\" | summary title | index title; }"
diff --git a/config-model/src/test/derived/lowercase/ilscripts.cfg b/config-model/src/test/derived/lowercase/ilscripts.cfg
index 0cf56eb43e0..fe36dc5daef 100644
--- a/config-model/src/test/derived/lowercase/ilscripts.cfg
+++ b/config-model/src/test/derived/lowercase/ilscripts.cfg
@@ -6,4 +6,4 @@ ilscript[].docfield[] "array_field_source"
ilscript[].content[] "clear_state | guard { input array_field_source | for_each { lowercase } | for_each { tokenize normalize stem:\"BEST\" } | summary array_field | index array_field; }"
ilscript[].content[] "clear_state | guard { input single_field_source | lowercase | tokenize normalize stem:\"BEST\" | summary single_field | index single_field; }"
ilscript[].content[] "input array_field_source | passthrough array_field_source"
-ilscript[].content[] "input single_field_source | passthrough single_field_source" \ No newline at end of file
+ilscript[].content[] "input single_field_source | passthrough single_field_source"
diff --git a/config-model/src/test/derived/lowercase/index-info.cfg b/config-model/src/test/derived/lowercase/index-info.cfg
index b94125de79d..ff6008fe1ce 100644
--- a/config-model/src/test/derived/lowercase/index-info.cfg
+++ b/config-model/src/test/derived/lowercase/index-info.cfg
@@ -38,4 +38,4 @@ indexinfo[].command[].command "normalize"
indexinfo[].command[].indexname "single_field"
indexinfo[].command[].command "plain-tokens"
indexinfo[].command[].indexname "single_field"
-indexinfo[].command[].command "type string" \ No newline at end of file
+indexinfo[].command[].command "type string"
diff --git a/config-model/src/test/derived/renamedfeatures/rank-profiles.cfg b/config-model/src/test/derived/renamedfeatures/rank-profiles.cfg
index 0a327575a48..d084401d920 100644
--- a/config-model/src/test/derived/renamedfeatures/rank-profiles.cfg
+++ b/config-model/src/test/derived/renamedfeatures/rank-profiles.cfg
@@ -1,82 +1,82 @@
-rankprofile[0].name "default"
-rankprofile[0].fef.property[0].name "rankingExpression(myplus).rankingScript"
-rankprofile[0].fef.property[0].value "attribute(foo1) + attribute(foo2)"
-rankprofile[0].fef.property[1].name "rankingExpression(mymul).rankingScript"
-rankprofile[0].fef.property[1].value "attribute(t1) * query(fromq)"
-rankprofile[0].fef.property[2].name "rankingExpression(mymul).type"
-rankprofile[0].fef.property[2].value "tensor(m{},v[3])"
-rankprofile[0].fef.property[3].name "vespa.rank.firstphase"
-rankprofile[0].fef.property[3].value "classicRank"
-rankprofile[0].fef.property[4].name "vespa.dump.feature"
-rankprofile[0].fef.property[4].value "attribute(foo1).out"
-rankprofile[0].fef.property[5].name "vespa.dump.feature"
-rankprofile[0].fef.property[5].value "attribute(bar1)"
-rankprofile[0].fef.property[6].name "vespa.dump.feature"
-rankprofile[0].fef.property[6].value "myplus"
-rankprofile[0].fef.property[7].name "vespa.dump.feature"
-rankprofile[0].fef.property[7].value "mymul"
-rankprofile[0].fef.property[8].name "vespa.dump.ignoredefaultfeatures"
-rankprofile[0].fef.property[8].value "true"
-rankprofile[0].fef.property[9].name "vespa.type.attribute.t1"
-rankprofile[0].fef.property[9].value "tensor(m{},v[3])"
-rankprofile[1].name "unranked"
-rankprofile[1].fef.property[0].name "vespa.rank.firstphase"
-rankprofile[1].fef.property[0].value "value(0)"
-rankprofile[1].fef.property[1].name "vespa.hitcollector.heapsize"
-rankprofile[1].fef.property[1].value "0"
-rankprofile[1].fef.property[2].name "vespa.hitcollector.arraysize"
-rankprofile[1].fef.property[2].value "0"
-rankprofile[1].fef.property[3].name "vespa.dump.ignoredefaultfeatures"
-rankprofile[1].fef.property[3].value "true"
-rankprofile[1].fef.property[4].name "vespa.type.attribute.t1"
-rankprofile[1].fef.property[4].value "tensor(m{},v[3])"
-rankprofile[2].name "withsf"
-rankprofile[2].fef.property[0].name "rankingExpression(myplus).rankingScript"
-rankprofile[2].fef.property[0].value "attribute(foo1) + attribute(foo2)"
-rankprofile[2].fef.property[1].name "rankingExpression(mymul).rankingScript"
-rankprofile[2].fef.property[1].value "attribute(t1) * query(fromq)"
-rankprofile[2].fef.property[2].name "rankingExpression(mymul).type"
-rankprofile[2].fef.property[2].value "tensor(m{},v[3])"
-rankprofile[2].fef.property[3].name "vespa.rank.firstphase"
-rankprofile[2].fef.property[3].value "attribute(year)"
-rankprofile[2].fef.property[4].name "vespa.summary.feature"
-rankprofile[2].fef.property[4].value "attribute(foo1).out"
-rankprofile[2].fef.property[5].name "vespa.summary.feature"
-rankprofile[2].fef.property[5].value "attribute(bar1)"
-rankprofile[2].fef.property[6].name "vespa.summary.feature"
-rankprofile[2].fef.property[6].value "rankingExpression(mymul)"
-rankprofile[2].fef.property[7].name "vespa.summary.feature"
-rankprofile[2].fef.property[7].value "rankingExpression(myplus)"
-rankprofile[2].fef.property[8].name "vespa.feature.rename"
-rankprofile[2].fef.property[8].value "rankingExpression(myplus)"
-rankprofile[2].fef.property[9].name "vespa.feature.rename"
-rankprofile[2].fef.property[9].value "myplus"
-rankprofile[2].fef.property[10].name "vespa.type.attribute.t1"
-rankprofile[2].fef.property[10].value "tensor(m{},v[3])"
-rankprofile[3].name "withmf"
-rankprofile[3].fef.property[0].name "rankingExpression(mymul).rankingScript"
-rankprofile[3].fef.property[0].value "attribute(t1) * query(fromq)"
-rankprofile[3].fef.property[1].name "rankingExpression(myplus).rankingScript"
-rankprofile[3].fef.property[1].value "attribute(foo1) + attribute(foo2)"
-rankprofile[3].fef.property[2].name "vespa.rank.firstphase"
-rankprofile[3].fef.property[2].value "attribute(foo1)"
-rankprofile[3].fef.property[3].name "vespa.rank.secondphase"
-rankprofile[3].fef.property[3].value "attribute(foo2)"
-rankprofile[3].fef.property[4].name "vespa.match.feature"
-rankprofile[3].fef.property[4].value "attribute(foo1).out"
-rankprofile[3].fef.property[5].name "vespa.match.feature"
-rankprofile[3].fef.property[5].value "attribute(bar1)"
-rankprofile[3].fef.property[6].name "vespa.match.feature"
-rankprofile[3].fef.property[6].value "rankingExpression(myplus)"
-rankprofile[3].fef.property[7].name "vespa.match.feature"
-rankprofile[3].fef.property[7].value "firstPhase"
-rankprofile[3].fef.property[8].name "vespa.match.feature"
-rankprofile[3].fef.property[8].value "secondPhase"
-rankprofile[3].fef.property[9].name "vespa.match.feature"
-rankprofile[3].fef.property[9].value "rankingExpression(mymul)"
-rankprofile[3].fef.property[10].name "vespa.feature.rename"
-rankprofile[3].fef.property[10].value "rankingExpression(mymul)"
-rankprofile[3].fef.property[11].name "vespa.feature.rename"
-rankprofile[3].fef.property[11].value "mymul"
-rankprofile[3].fef.property[12].name "vespa.type.attribute.t1"
-rankprofile[3].fef.property[12].value "tensor(m{},v[3])"
+rankprofile[].name "default"
+rankprofile[].fef.property[].name "rankingExpression(myplus).rankingScript"
+rankprofile[].fef.property[].value "attribute(foo1) + attribute(foo2)"
+rankprofile[].fef.property[].name "rankingExpression(mymul).rankingScript"
+rankprofile[].fef.property[].value "attribute(t1) * query(fromq)"
+rankprofile[].fef.property[].name "rankingExpression(mymul).type"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "classicRank"
+rankprofile[].fef.property[].name "vespa.dump.feature"
+rankprofile[].fef.property[].value "attribute(foo1).out"
+rankprofile[].fef.property[].name "vespa.dump.feature"
+rankprofile[].fef.property[].value "attribute(bar1)"
+rankprofile[].fef.property[].name "vespa.dump.feature"
+rankprofile[].fef.property[].value "myplus"
+rankprofile[].fef.property[].name "vespa.dump.feature"
+rankprofile[].fef.property[].value "mymul"
+rankprofile[].fef.property[].name "vespa.dump.ignoredefaultfeatures"
+rankprofile[].fef.property[].value "true"
+rankprofile[].fef.property[].name "vespa.type.attribute.t1"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
+rankprofile[].name "unranked"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "value(0)"
+rankprofile[].fef.property[].name "vespa.hitcollector.heapsize"
+rankprofile[].fef.property[].value "0"
+rankprofile[].fef.property[].name "vespa.hitcollector.arraysize"
+rankprofile[].fef.property[].value "0"
+rankprofile[].fef.property[].name "vespa.dump.ignoredefaultfeatures"
+rankprofile[].fef.property[].value "true"
+rankprofile[].fef.property[].name "vespa.type.attribute.t1"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
+rankprofile[].name "withsf"
+rankprofile[].fef.property[].name "rankingExpression(myplus).rankingScript"
+rankprofile[].fef.property[].value "attribute(foo1) + attribute(foo2)"
+rankprofile[].fef.property[].name "rankingExpression(mymul).rankingScript"
+rankprofile[].fef.property[].value "attribute(t1) * query(fromq)"
+rankprofile[].fef.property[].name "rankingExpression(mymul).type"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "attribute(year)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "attribute(foo1).out"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "attribute(bar1)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(mymul)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(myplus)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(myplus)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "myplus"
+rankprofile[].fef.property[].name "vespa.type.attribute.t1"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
+rankprofile[].name "withmf"
+rankprofile[].fef.property[].name "rankingExpression(mymul).rankingScript"
+rankprofile[].fef.property[].value "attribute(t1) * query(fromq)"
+rankprofile[].fef.property[].name "rankingExpression(myplus).rankingScript"
+rankprofile[].fef.property[].value "attribute(foo1) + attribute(foo2)"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "attribute(foo1)"
+rankprofile[].fef.property[].name "vespa.rank.secondphase"
+rankprofile[].fef.property[].value "attribute(foo2)"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "attribute(foo1).out"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "attribute(bar1)"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "rankingExpression(myplus)"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "firstPhase"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "secondPhase"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "rankingExpression(mymul)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(mymul)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "mymul"
+rankprofile[].fef.property[].name "vespa.type.attribute.t1"
+rankprofile[].fef.property[].value "tensor(m{},v[3])"
diff --git a/config-model/src/test/derived/schemainheritance/summary.cfg b/config-model/src/test/derived/schemainheritance/summary.cfg
index 6fcf5b2aaa8..11f876c66c6 100644
--- a/config-model/src/test/derived/schemainheritance/summary.cfg
+++ b/config-model/src/test/derived/schemainheritance/summary.cfg
@@ -47,4 +47,4 @@ classes[].fields[].type "featuredata"
classes[].fields[].name "summaryfeatures"
classes[].fields[].type "featuredata"
classes[].fields[].name "cf1"
-classes[].fields[].type "longstring" \ No newline at end of file
+classes[].fields[].type "longstring"
diff --git a/config-model/src/test/derived/schemainheritance/summarymap.cfg b/config-model/src/test/derived/schemainheritance/summarymap.cfg
index ad98cbe76e7..d09407ca8a5 100644
--- a/config-model/src/test/derived/schemainheritance/summarymap.cfg
+++ b/config-model/src/test/derived/schemainheritance/summarymap.cfg
@@ -5,9 +5,9 @@ override[].arguments ""
override[].field "summaryfeatures"
override[].command "summaryfeatures"
override[].arguments ""
-override[].field "child_field"
-override[].command "attribute"
-override[].arguments "child_field"
override[].field "parent_field"
override[].command "attribute"
override[].arguments "parent_field"
+override[].field "child_field"
+override[].command "attribute"
+override[].arguments "child_field"
diff --git a/config-model/src/test/derived/schemainheritance/vsmsummary.cfg b/config-model/src/test/derived/schemainheritance/vsmsummary.cfg
index 91ca5363a25..f1c052598bd 100644
--- a/config-model/src/test/derived/schemainheritance/vsmsummary.cfg
+++ b/config-model/src/test/derived/schemainheritance/vsmsummary.cfg
@@ -1,13 +1,13 @@
outputclass ""
+fieldmap[].summary "parent_field"
+fieldmap[].document[].field "parent_field"
+fieldmap[].command NONE
fieldmap[].summary "child_field"
fieldmap[].document[].field "child_field"
fieldmap[].command NONE
fieldmap[].summary "pf1"
fieldmap[].document[].field "pf1"
fieldmap[].command NONE
-fieldmap[].summary "parent_field"
-fieldmap[].document[].field "parent_field"
-fieldmap[].command NONE
fieldmap[].summary "cf1"
fieldmap[].document[].field "cf1"
fieldmap[].command NONE
diff --git a/config-model/src/test/derived/structinheritance/documenttypes.cfg b/config-model/src/test/derived/structinheritance/documenttypes.cfg
index 52a154905c2..cf4bc89866f 100644
--- a/config-model/src/test/derived/structinheritance/documenttypes.cfg
+++ b/config-model/src/test/derived/structinheritance/documenttypes.cfg
@@ -1,102 +1,102 @@
enablecompression false
usev8geopositions false
-documenttype[0].id 485659380
-documenttype[0].name "simple"
-documenttype[0].version 0
-documenttype[0].headerstruct -2142109237
-documenttype[0].bodystruct 0
-documenttype[0].inherits[0].id 8
-documenttype[0].datatype[0].id 1811766610
-documenttype[0].datatype[0].type STRUCT
-documenttype[0].datatype[0].array.element.id 0
-documenttype[0].datatype[0].map.key.id 0
-documenttype[0].datatype[0].map.value.id 0
-documenttype[0].datatype[0].wset.key.id 0
-documenttype[0].datatype[0].wset.createifnonexistent false
-documenttype[0].datatype[0].wset.removeifzero false
-documenttype[0].datatype[0].annotationref.annotation.id 0
-documenttype[0].datatype[0].sstruct.name "grandchild"
-documenttype[0].datatype[0].sstruct.version 0
-documenttype[0].datatype[0].sstruct.compression.type NONE
-documenttype[0].datatype[0].sstruct.compression.level 0
-documenttype[0].datatype[0].sstruct.compression.threshold 95
-documenttype[0].datatype[0].sstruct.compression.minsize 200
-documenttype[0].datatype[0].sstruct.field[0].name "toy"
-documenttype[0].datatype[0].sstruct.field[0].id 536645790
-documenttype[0].datatype[0].sstruct.field[0].datatype 2
-documenttype[0].datatype[0].sstruct.field[0].detailedtype ""
-documenttype[0].datatype[0].sstruct.field[1].name "age"
-documenttype[0].datatype[0].sstruct.field[1].id 1862473705
-documenttype[0].datatype[0].sstruct.field[1].datatype 0
-documenttype[0].datatype[0].sstruct.field[1].detailedtype ""
-documenttype[0].datatype[0].sstruct.field[2].name "name"
-documenttype[0].datatype[0].sstruct.field[2].id 1160796772
-documenttype[0].datatype[0].sstruct.field[2].datatype 2
-documenttype[0].datatype[0].sstruct.field[2].detailedtype ""
-documenttype[0].datatype[1].id -1396204461
-documenttype[0].datatype[1].type STRUCT
-documenttype[0].datatype[1].array.element.id 0
-documenttype[0].datatype[1].map.key.id 0
-documenttype[0].datatype[1].map.value.id 0
-documenttype[0].datatype[1].wset.key.id 0
-documenttype[0].datatype[1].wset.createifnonexistent false
-documenttype[0].datatype[1].wset.removeifzero false
-documenttype[0].datatype[1].annotationref.annotation.id 0
-documenttype[0].datatype[1].sstruct.name "base"
-documenttype[0].datatype[1].sstruct.version 0
-documenttype[0].datatype[1].sstruct.compression.type NONE
-documenttype[0].datatype[1].sstruct.compression.level 0
-documenttype[0].datatype[1].sstruct.compression.threshold 95
-documenttype[0].datatype[1].sstruct.compression.minsize 200
-documenttype[0].datatype[1].sstruct.field[0].name "name"
-documenttype[0].datatype[1].sstruct.field[0].id 1160796772
-documenttype[0].datatype[1].sstruct.field[0].datatype 2
-documenttype[0].datatype[1].sstruct.field[0].detailedtype ""
-documenttype[0].datatype[2].id 746267614
-documenttype[0].datatype[2].type STRUCT
-documenttype[0].datatype[2].array.element.id 0
-documenttype[0].datatype[2].map.key.id 0
-documenttype[0].datatype[2].map.value.id 0
-documenttype[0].datatype[2].wset.key.id 0
-documenttype[0].datatype[2].wset.createifnonexistent false
-documenttype[0].datatype[2].wset.removeifzero false
-documenttype[0].datatype[2].annotationref.annotation.id 0
-documenttype[0].datatype[2].sstruct.name "child"
-documenttype[0].datatype[2].sstruct.version 0
-documenttype[0].datatype[2].sstruct.compression.type NONE
-documenttype[0].datatype[2].sstruct.compression.level 0
-documenttype[0].datatype[2].sstruct.compression.threshold 95
-documenttype[0].datatype[2].sstruct.compression.minsize 200
-documenttype[0].datatype[2].sstruct.field[0].name "age"
-documenttype[0].datatype[2].sstruct.field[0].id 1862473705
-documenttype[0].datatype[2].sstruct.field[0].datatype 0
-documenttype[0].datatype[2].sstruct.field[0].detailedtype ""
-documenttype[0].datatype[2].sstruct.field[1].name "name"
-documenttype[0].datatype[2].sstruct.field[1].id 1160796772
-documenttype[0].datatype[2].sstruct.field[1].datatype 2
-documenttype[0].datatype[2].sstruct.field[1].detailedtype ""
-documenttype[0].datatype[3].id -2142109237
-documenttype[0].datatype[3].type STRUCT
-documenttype[0].datatype[3].array.element.id 0
-documenttype[0].datatype[3].map.key.id 0
-documenttype[0].datatype[3].map.value.id 0
-documenttype[0].datatype[3].wset.key.id 0
-documenttype[0].datatype[3].wset.createifnonexistent false
-documenttype[0].datatype[3].wset.removeifzero false
-documenttype[0].datatype[3].annotationref.annotation.id 0
-documenttype[0].datatype[3].sstruct.name "simple.header"
-documenttype[0].datatype[3].sstruct.version 0
-documenttype[0].datatype[3].sstruct.compression.type NONE
-documenttype[0].datatype[3].sstruct.compression.level 0
-documenttype[0].datatype[3].sstruct.compression.threshold 95
-documenttype[0].datatype[3].sstruct.compression.minsize 200
-documenttype[0].datatype[3].sstruct.field[0].name "f1"
-documenttype[0].datatype[3].sstruct.field[0].id 750623154
-documenttype[0].datatype[3].sstruct.field[0].datatype 746267614
-documenttype[0].datatype[3].sstruct.field[0].detailedtype ""
-documenttype[0].datatype[3].sstruct.field[1].name "f2"
-documenttype[0].datatype[3].sstruct.field[1].id 1523850983
-documenttype[0].datatype[3].sstruct.field[1].datatype 1811766610
-documenttype[0].datatype[3].sstruct.field[1].detailedtype ""
-documenttype[0].fieldsets{[document]}.fields[0] "f1"
-documenttype[0].fieldsets{[document]}.fields[1] "f2"
+documenttype[].id 485659380
+documenttype[].name "simple"
+documenttype[].version 0
+documenttype[].headerstruct -2142109237
+documenttype[].bodystruct 0
+documenttype[].inherits[].id 8
+documenttype[].datatype[].id -1396204461
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "base"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "name"
+documenttype[].datatype[].sstruct.field[].id 1160796772
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].id 746267614
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "child"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "age"
+documenttype[].datatype[].sstruct.field[].id 1862473705
+documenttype[].datatype[].sstruct.field[].datatype 0
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "name"
+documenttype[].datatype[].sstruct.field[].id 1160796772
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].id 1811766610
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "grandchild"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "toy"
+documenttype[].datatype[].sstruct.field[].id 536645790
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "age"
+documenttype[].datatype[].sstruct.field[].id 1862473705
+documenttype[].datatype[].sstruct.field[].datatype 0
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "name"
+documenttype[].datatype[].sstruct.field[].id 1160796772
+documenttype[].datatype[].sstruct.field[].datatype 2
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].id -2142109237
+documenttype[].datatype[].type STRUCT
+documenttype[].datatype[].array.element.id 0
+documenttype[].datatype[].map.key.id 0
+documenttype[].datatype[].map.value.id 0
+documenttype[].datatype[].wset.key.id 0
+documenttype[].datatype[].wset.createifnonexistent false
+documenttype[].datatype[].wset.removeifzero false
+documenttype[].datatype[].annotationref.annotation.id 0
+documenttype[].datatype[].sstruct.name "simple.header"
+documenttype[].datatype[].sstruct.version 0
+documenttype[].datatype[].sstruct.compression.type NONE
+documenttype[].datatype[].sstruct.compression.level 0
+documenttype[].datatype[].sstruct.compression.threshold 95
+documenttype[].datatype[].sstruct.compression.minsize 200
+documenttype[].datatype[].sstruct.field[].name "f1"
+documenttype[].datatype[].sstruct.field[].id 750623154
+documenttype[].datatype[].sstruct.field[].datatype 746267614
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].datatype[].sstruct.field[].name "f2"
+documenttype[].datatype[].sstruct.field[].id 1523850983
+documenttype[].datatype[].sstruct.field[].datatype 1811766610
+documenttype[].datatype[].sstruct.field[].detailedtype ""
+documenttype[].fieldsets{[document]}.fields[] "f1"
+documenttype[].fieldsets{[document]}.fields[] "f2"
diff --git a/config-model/src/test/derived/tensor/rank-profiles.cfg b/config-model/src/test/derived/tensor/rank-profiles.cfg
index 7970e05b790..ac66ccf6938 100644
--- a/config-model/src/test/derived/tensor/rank-profiles.cfg
+++ b/config-model/src/test/derived/tensor/rank-profiles.cfg
@@ -161,4 +161,3 @@ rankprofile[].fef.property[].name "vespa.type.attribute.f4"
rankprofile[].fef.property[].value "tensor(x[10],y[10])"
rankprofile[].fef.property[].name "vespa.type.attribute.f5"
rankprofile[].fef.property[].value "tensor<float>(x[10])"
-
diff --git a/config-model/src/test/derived/tokenization/ilscripts.cfg b/config-model/src/test/derived/tokenization/ilscripts.cfg
index ead74110db3..4414ad0f7cb 100644
--- a/config-model/src/test/derived/tokenization/ilscripts.cfg
+++ b/config-model/src/test/derived/tokenization/ilscripts.cfg
@@ -6,4 +6,4 @@ ilscript[].docfield[] "text_array"
ilscript[].content[] "clear_state | guard { input text_array | for_each { lowercase } | for_each { normalize } | for_each { tokenize normalize stem:\"BEST\" } | index text_array_derived | summary text_array_derived; }"
ilscript[].content[] "clear_state | guard { input text | normalize | tokenize normalize stem:\"BEST\" | index text_derived | summary text_derived; }"
ilscript[].content[] "clear_state | guard { input text | tokenize normalize stem:\"BEST\" | index text | summary text; }"
-ilscript[].content[] "clear_state | guard { input text_array | for_each { tokenize normalize stem:\"BEST\" } | index text_array | summary text_array; }" \ No newline at end of file
+ilscript[].content[] "clear_state | guard { input text_array | for_each { tokenize normalize stem:\"BEST\" } | index text_array | summary text_array; }"
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
index d77c6d822e3..38ebb147cac 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
@@ -8,6 +8,7 @@ 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.document.DataType;
+import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileRegistry;
import com.yahoo.search.query.profile.types.FieldDescription;
import com.yahoo.search.query.profile.types.FieldType;
@@ -363,6 +364,9 @@ public class RankProfileTestCase extends AbstractSchemaTestCase {
type.addField(new FieldDescription("ranking.features.query(numeric)",
FieldType.fromString("integer", typeRegistry)), typeRegistry);
typeRegistry.register(type);
+ var profile = new QueryProfile(new ComponentId("testprofile"));
+ profile.setType(type);
+ registry.register(profile);
return registry;
}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/DuplicateStructTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/DuplicateStructTestCase.java
new file mode 100644
index 00000000000..05b16c9d30b
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/DuplicateStructTestCase.java
@@ -0,0 +1,30 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.searchdefinition.derived;
+
+import com.yahoo.config.model.deploy.TestProperties;
+import org.junit.Test;
+
+/**
+ * @author arnej
+ */
+public class DuplicateStructTestCase extends AbstractExportingTestCase {
+
+ @Test
+ public void exact_duplicate_struct_works() throws Exception {
+ assertCorrectDeriving("duplicate_struct", "foobar",
+ new TestProperties()
+ .setExperimentalSdParsing(false)
+ .setUseV8DocManagerCfg(true),
+ new TestableDeployLogger());
+ }
+
+ @Test
+ public void exact_duplicate_struct_works_new() throws Exception {
+ assertCorrectDeriving("duplicate_struct", "foobar",
+ new TestProperties()
+ .setExperimentalSdParsing(true)
+ .setUseV8DocManagerCfg(true),
+ new TestableDeployLogger());
+ }
+
+}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
index c517e36bce1..bfd87580dbe 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
@@ -108,7 +108,8 @@ public class ReferenceFieldTestCase {
DataType dataType = field.getDataType();
assertTrue(dataType instanceof NewDocumentReferenceDataType);
NewDocumentReferenceDataType refField = (NewDocumentReferenceDataType) dataType;
- assertEquals(referencedDocType, refField.getTargetType().getName());
+ assertEquals(referencedDocType, refField.getTargetTypeName());
+ assertTrue(! refField.isTemporary());
}
}
diff --git a/container-search/abi-spec.json b/container-search/abi-spec.json
index 0e45aa59421..8ac5aaa127d 100644
--- a/container-search/abi-spec.json
+++ b/container-search/abi-spec.json
@@ -441,7 +441,7 @@
"protected void encodeThis(java.nio.ByteBuffer)",
"protected int encodingArity()",
"protected void appendBodyString(java.lang.StringBuilder)",
- "protected boolean shouldParenthize()",
+ "protected boolean shouldParenthesize()",
"public com.yahoo.prelude.query.CompositeItem clone()",
"public int hashCode()",
"public boolean equals(java.lang.Object)",
@@ -741,6 +741,7 @@
"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"
]
},
@@ -774,12 +775,12 @@
"public com.yahoo.prelude.query.CompositeItem getParent()",
"public abstract int encode(java.nio.ByteBuffer)",
"protected void encodeThis(java.nio.ByteBuffer)",
- "protected static final byte[] getBytes(java.lang.String)",
+ "protected static byte[] getBytes(java.lang.String)",
"public static void putString(java.lang.String, java.nio.ByteBuffer)",
"public static void putBytes(byte[], java.nio.ByteBuffer)",
"public abstract int getTermCount()",
"public java.lang.String toString()",
- "protected boolean shouldParenthize()",
+ "protected boolean shouldParenthesize()",
"protected void appendHeadingString(java.lang.StringBuilder)",
"protected abstract void appendBodyString(java.lang.StringBuilder)",
"public com.yahoo.prelude.query.Item clone()",
@@ -1027,7 +1028,7 @@
"public com.yahoo.prelude.query.BlockItem getBlockItem(int)",
"protected void encodeThis(java.nio.ByteBuffer)",
"public int encode(java.nio.ByteBuffer)",
- "protected boolean shouldParenthize()",
+ "protected boolean shouldParenthesize()",
"protected void appendHeadingString(java.lang.StringBuilder)",
"protected void appendBodyString(java.lang.StringBuilder)",
"public java.lang.String getIndexedString()",
@@ -1060,7 +1061,7 @@
"protected void encodeThis(java.nio.ByteBuffer)",
"public int encode(java.nio.ByteBuffer)",
"public int encodeContent(java.nio.ByteBuffer)",
- "protected boolean shouldParenthize()",
+ "protected boolean shouldParenthesize()",
"protected void appendHeadingString(java.lang.StringBuilder)",
"protected void appendBodyString(java.lang.StringBuilder)",
"public java.lang.String getIndexedString()",
@@ -2317,7 +2318,9 @@
"public static final java.lang.String SELECT_PARAMETER_PARSING",
"public static final com.yahoo.processing.request.CompoundName PARAM_CONTINUE",
"public static final com.yahoo.processing.request.CompoundName PARAM_REQUEST",
- "public static final com.yahoo.processing.request.CompoundName PARAM_TIMEZONE"
+ "public static final com.yahoo.processing.request.CompoundName PARAM_TIMEZONE",
+ "public static final com.yahoo.processing.request.CompoundName PARAM_DEFAULT_MAX_HITS",
+ "public static final com.yahoo.processing.request.CompoundName PARAM_DEFAULT_MAX_GROUPS"
]
},
"com.yahoo.search.grouping.GroupingRequest": {
@@ -2335,6 +2338,10 @@
"public com.yahoo.search.grouping.GroupingRequest setTimeZone(java.util.TimeZone)",
"public com.yahoo.search.grouping.result.RootGroup getResultGroup(com.yahoo.search.Result)",
"public java.util.List continuations()",
+ "public java.util.OptionalInt defaultMaxHits()",
+ "public void setDefaultMaxHits(int)",
+ "public java.util.OptionalInt defaultMaxGroups()",
+ "public void setDefaultMaxGroups(int)",
"public static com.yahoo.search.grouping.GroupingRequest newInstance(com.yahoo.search.Query)",
"public java.lang.String toString()"
],
diff --git a/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4 b/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
index 9af8d83c6d7..422c3c8681e 100644
--- a/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
+++ b/container-search/src/main/antlr4/com/yahoo/search/yql/yqlplus.g4
@@ -127,7 +127,7 @@ HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
- : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\'|'/')
+ : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\''|'\\'|'/')
| UNICODE_ESC
;
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/CompositeItem.java b/container-search/src/main/java/com/yahoo/prelude/query/CompositeItem.java
index d3fbeb020f8..f48dc9a8630 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/CompositeItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/CompositeItem.java
@@ -42,13 +42,9 @@ public abstract class CompositeItem extends Item {
}
public void ensureNotInSubtree(CompositeItem item) {
- for (Iterator<Item> i = item.getItemIterator(); i.hasNext();) {
- Item possibleCycle = i.next();
-
- if (this == possibleCycle) {
+ for (Item i = this; i != null; i = i.getParent()) {
+ if (i == item) {
throw new IllegalArgumentException("Cannot add " + item + " to " + this + " as it would create a cycle");
- } else if (possibleCycle instanceof CompositeItem) {
- ensureNotInSubtree((CompositeItem) possibleCycle);
}
}
}
@@ -205,7 +201,7 @@ public abstract class CompositeItem extends Item {
}
/** Composite items should be parenthized when not on the top level */
- protected boolean shouldParenthize() {
+ protected boolean shouldParenthesize() {
return getParent()!= null && ! (getParent() instanceof QueryTree);
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/EquivItem.java b/container-search/src/main/java/com/yahoo/prelude/query/EquivItem.java
index 500c68cf4bd..43258db8963 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/EquivItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/EquivItem.java
@@ -20,7 +20,7 @@ public class EquivItem extends CompositeTaggableItem {
public EquivItem() {}
/**
- * Creates an EQUIV with the given item as child. The new EQUIV will take connectivity,
+ * Creates an EQUIV with the given item as child. The new EQUIV will take connectivity,
* significance and weight from the given item.
*
* @param item will be modified and added as a child
@@ -48,7 +48,7 @@ public class EquivItem extends CompositeTaggableItem {
// steal other item's weight:
setWeight(item.getWeight());
- // we have now stolen all of the other item's unique id needs:
+ // we have now stolen all the other item's unique id needs:
item.setHasUniqueID(false);
}
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 92b321adb70..06fe07d3895 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
@@ -11,7 +11,6 @@ import com.yahoo.text.Utf8;
import java.nio.ByteBuffer;
import java.util.Objects;
-import java.util.Optional;
/**
@@ -20,7 +19,7 @@ import java.util.Optional;
* Items are in general mutable and not thread safe.
* They can be deeply cloned by calling clone().
* Their identity is defined by their content
- * (i.e the field value of two items decide if they are equal).
+ * (i.e. the field value of two items decide if they are equal).
*
* @author bratseth
* @author havardpe
@@ -60,7 +59,8 @@ public abstract class Item implements Cloneable {
NEAREST_NEIGHBOR(26),
GEO_LOCATION_TERM(27),
TRUE(28),
- FALSE(29);
+ FALSE(29),
+ MULTI_TERM(30);
public final int code;
@@ -233,36 +233,34 @@ public abstract class Item implements Cloneable {
public abstract int encode(ByteBuffer buffer);
protected void encodeThis(ByteBuffer buffer) {
- int FEAT_SHIFT = 5;
- int CODE_MASK = 0x1f;
- int FEAT_MASK = 0xe0;
- int FEAT_WEIGHT = 0x01;
- int FEAT_UNIQUEID = 0x02;
- int FEAT_FLAGS = 0x04;
+ byte CODE_MASK = 0b00011111;
+ byte FEAT_WEIGHT = 0b00100000;
+ byte FEAT_UNIQUEID = 0b01000000;
+ byte FEAT_FLAGS = -0b10000000;
- int features = 0;
+ byte type = (byte) (getCode() & CODE_MASK);
+ if (type != getCode())
+ throw new IllegalStateException("must increase number of bytes in serialization format for queries");
if (weight != DEFAULT_WEIGHT) {
- features |= FEAT_WEIGHT;
+ type |= FEAT_WEIGHT;
}
if (hasUniqueID()) {
- features |= FEAT_UNIQUEID;
+ type |= FEAT_UNIQUEID;
}
byte flags = getFlagsFeature();
if (flags != 0) {
- features |= FEAT_FLAGS;
+ type |= FEAT_FLAGS;
}
- byte type = (byte)(((getCode() & CODE_MASK)
- | ((features << FEAT_SHIFT) & FEAT_MASK)) & 0xff);
buffer.put(type);
- if ((features & FEAT_WEIGHT) != 0) {
+ if ((type & FEAT_WEIGHT) != 0) {
IntegerCompressor.putCompressedNumber(weight, buffer);
}
- if ((features & FEAT_UNIQUEID) != 0) {
+ if ((type & FEAT_UNIQUEID) != 0) {
IntegerCompressor.putCompressedPositiveNumber(uniqueID, buffer);
}
- if (flags != 0) {
+ if ((type & FEAT_FLAGS) != 0) {
buffer.put(flags);
}
}
@@ -297,7 +295,7 @@ public abstract class Item implements Cloneable {
/** Utility method for turning a string into utf-8 bytes */
- protected static final byte[] getBytes(String string) {
+ protected static byte[] getBytes(String string) {
return Utf8.toBytes(string);
}
public static void putString(String s, ByteBuffer buffer) {
@@ -322,7 +320,7 @@ public abstract class Item implements Cloneable {
public String toString() {
StringBuilder buffer = new StringBuilder();
- if (shouldParenthize()) {
+ if (shouldParenthesize()) {
buffer.append("(");
}
if (isFilter()) {
@@ -330,7 +328,7 @@ public abstract class Item implements Cloneable {
}
appendHeadingString(buffer);
appendBodyString(buffer);
- if (shouldParenthize()) {
+ if (shouldParenthesize()) {
buffer.append(")");
}
@@ -343,10 +341,10 @@ public abstract class Item implements Cloneable {
}
/**
- * Returns whether this item should be parethized when printed.
+ * Returns whether this item should be parenthesized when printed.
* Default is false - no parentheses
*/
- protected boolean shouldParenthize() {
+ protected boolean shouldParenthesize() {
return false;
}
@@ -376,7 +374,7 @@ public abstract class Item implements Cloneable {
// note: connectedItem and connectedBacklink references are corrected in CompositeItem.clone()
return clone;
} catch (CloneNotSupportedException e) {
- throw new RuntimeException("Someone made Item unclonable");
+ throw new RuntimeException("Someone made Item uncloneable");
}
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/PhraseItem.java b/container-search/src/main/java/com/yahoo/prelude/query/PhraseItem.java
index fae282868f8..379dfd6bb30 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/PhraseItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/PhraseItem.java
@@ -202,7 +202,7 @@ public class PhraseItem extends CompositeIndexedItem {
/** Returns false, no parenthezes for phrases */
@Override
- protected boolean shouldParenthize() {
+ protected boolean shouldParenthesize() {
return false;
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/PhraseSegmentItem.java b/container-search/src/main/java/com/yahoo/prelude/query/PhraseSegmentItem.java
index 16e22f6d482..2a97970ac4a 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/PhraseSegmentItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/PhraseSegmentItem.java
@@ -148,7 +148,7 @@ public class PhraseSegmentItem extends IndexedSegmentItem {
/** Returns false, no parenthezes for phrases */
@Override
- protected boolean shouldParenthize() {
+ protected boolean shouldParenthesize() {
return false;
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/TaggableItem.java b/container-search/src/main/java/com/yahoo/prelude/query/TaggableItem.java
index f23f2088f1d..eb23570ec90 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/TaggableItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/TaggableItem.java
@@ -18,10 +18,10 @@ public interface TaggableItem {
* This is used to influence ranking features taking proximity into account: nativeRank and a subset of the
* fieldMatch features.
* <p>
- * By default consecutive query terms are 'somewhat' connected, meaning ranking features will be better in documents
+ * By default consecutive query terms are 'somewhat' connected, meaning ranking features will score higher in documents
* where the terms are found close to each other. This effect can be increased or decreased by manipulating the
* connectivity value. Typical use is to increase the connectivity between terms in the query that we believe are
- * semantically connected. E.g in the query 'new york hotel', it is a good idea to increase the connectivity between
+ * semantically connected. E.g., in the query 'new york hotel', it is a good idea to increase the connectivity between
* "new" and "york" to ensure that a document containing "List of hotels in New York" is ranked above one containing
* "List of new hotels in York".
*
@@ -36,8 +36,8 @@ public interface TaggableItem {
/**
* Used for setting explicit term significance (in the tf/idf sense) to a single term or phrase,
* relative to the rest of the query.
- * This influences ranking features which take term significance into account and overrides the default
- * partial corpus based term significance computation happening in the backend.
+ * This influences ranking features which take term significance into account, and overrides the default
+ * partial corpus based term significance computation in the backend.
*/
void setSignificance(double significance);
boolean hasExplicitSignificance();
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/WeightedSetItem.java b/container-search/src/main/java/com/yahoo/prelude/query/WeightedSetItem.java
index a988753d699..a5903f24cbd 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/WeightedSetItem.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/WeightedSetItem.java
@@ -10,6 +10,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
+import static java.util.Objects.requireNonNullElse;
+
/**
* A term which contains a weighted set.
*
@@ -30,20 +32,12 @@ public class WeightedSetItem extends SimpleTaggableItem {
/** Creates an empty weighted set; note you must provide an index name up front */
public WeightedSetItem(String indexName) {
- if (indexName == null) {
- this.indexName = "";
- } else {
- this.indexName = indexName;
- }
+ this.indexName = requireNonNullElse(indexName, "");
set = new CopyOnWriteHashMap<>(1000);
}
public WeightedSetItem(String indexName, Map<Object, Integer> map) {
- if (indexName == null) {
- this.indexName = "";
- } else {
- this.indexName = indexName;
- }
+ this.indexName = requireNonNullElse(indexName, "");
set = new CopyOnWriteHashMap<>(map);
}
@@ -96,11 +90,7 @@ public class WeightedSetItem extends SimpleTaggableItem {
@Override
public void setIndexName(String index) {
- if (index == null) {
- this.indexName = "";
- } else {
- this.indexName = index;
- }
+ this.indexName = requireNonNullElse(index, "");
}
public String getIndexName() {
diff --git a/container-search/src/main/java/com/yahoo/search/grouping/GroupingQueryParser.java b/container-search/src/main/java/com/yahoo/search/grouping/GroupingQueryParser.java
index f4603e5ea28..0de4e36eae5 100644
--- a/container-search/src/main/java/com/yahoo/search/grouping/GroupingQueryParser.java
+++ b/container-search/src/main/java/com/yahoo/search/grouping/GroupingQueryParser.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.search.grouping;
+import com.yahoo.api.annotations.Beta;
import com.yahoo.component.chain.dependencies.After;
import com.yahoo.component.chain.dependencies.Before;
import com.yahoo.component.chain.dependencies.Provides;
@@ -37,6 +38,8 @@ public class GroupingQueryParser extends Searcher {
public static final CompoundName PARAM_CONTINUE = new CompoundName("continue");
public static final CompoundName PARAM_REQUEST = new CompoundName(Select.SELECT);
public static final CompoundName PARAM_TIMEZONE = new CompoundName("timezone");
+ @Beta public static final CompoundName PARAM_DEFAULT_MAX_HITS = new CompoundName("grouping.defaultMaxHits");
+ @Beta public static final CompoundName PARAM_DEFAULT_MAX_GROUPS = new CompoundName("grouping.defaultMaxGroups");
private static final ThreadLocal<ZoneCache> zoneCache = new ThreadLocal<>();
@Override
@@ -52,6 +55,8 @@ public class GroupingQueryParser extends Searcher {
grpRequest.setRootOperation(op);
grpRequest.setTimeZone(zone);
grpRequest.continuations().addAll(continuations);
+ grpRequest.setDefaultMaxGroups(query.properties().getInteger(PARAM_DEFAULT_MAX_GROUPS, -1));
+ grpRequest.setDefaultMaxHits(query.properties().getInteger(PARAM_DEFAULT_MAX_HITS, -1));
}
return execution.search(query);
}
diff --git a/container-search/src/main/java/com/yahoo/search/grouping/GroupingRequest.java b/container-search/src/main/java/com/yahoo/search/grouping/GroupingRequest.java
index 6b21b2c6b5c..0c163aaacae 100644
--- a/container-search/src/main/java/com/yahoo/search/grouping/GroupingRequest.java
+++ b/container-search/src/main/java/com/yahoo/search/grouping/GroupingRequest.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.search.grouping;
+import com.yahoo.api.annotations.Beta;
import com.yahoo.net.URI;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
@@ -13,6 +14,7 @@ import com.yahoo.search.result.Hit;
import java.util.ArrayList;
import java.util.List;
+import java.util.OptionalInt;
import java.util.TimeZone;
/**
@@ -30,6 +32,8 @@ public class GroupingRequest {
private final List<Continuation> continuations = new ArrayList<>();
private GroupingOperation root;
private TimeZone timeZone;
+ private int defaultMaxHits = -1;
+ private int defaultMaxGroups = -1;
private GroupingRequest(Select parent) {
this.parent = parent;
@@ -38,16 +42,20 @@ public class GroupingRequest {
private GroupingRequest(Select parent,
List<Continuation> continuations,
GroupingOperation root,
- TimeZone timeZone) {
+ TimeZone timeZone,
+ int defaultMaxHits,
+ int defaultMaxGroups) {
this.parent = parent;
continuations.forEach(item -> this.continuations.add(item.copy()));
this.root = root != null ? root.copy(null) : null;
this.timeZone = timeZone;
+ this.defaultMaxHits = defaultMaxHits;
+ this.defaultMaxGroups = defaultMaxGroups;
}
/** Returns a deep copy of this */
public GroupingRequest copy(Select parentOfCopy) {
- return new GroupingRequest(parentOfCopy, continuations, root, timeZone);
+ return new GroupingRequest(parentOfCopy, continuations, root, timeZone, defaultMaxHits, defaultMaxGroups);
}
/**
@@ -131,6 +139,20 @@ public class GroupingRequest {
return continuations;
}
+ @Beta
+ public OptionalInt defaultMaxHits() {
+ return defaultMaxHits >= 0 ? OptionalInt.of(defaultMaxHits) : OptionalInt.empty();
+ }
+
+ @Beta public void setDefaultMaxHits(int v) { this.defaultMaxHits = v; }
+
+ @Beta
+ public OptionalInt defaultMaxGroups() {
+ return defaultMaxGroups >= 0 ? OptionalInt.of(defaultMaxGroups) : OptionalInt.empty();
+ }
+
+ @Beta public void setDefaultMaxGroups(int v) { this.defaultMaxGroups = v; }
+
/**
* Creates a new grouping request and adds it to the query.getSelect().getGrouping() list
*
diff --git a/container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java b/container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java
index 3e707b0cd38..c09502110b1 100644
--- a/container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java
+++ b/container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java
@@ -150,6 +150,8 @@ public class GroupingExecutor extends Searcher {
builder.setDefaultSummaryName(query.getPresentation().getSummary());
builder.setTimeZone(req.getTimeZone());
builder.addContinuations(req.continuations());
+ req.defaultMaxGroups().ifPresent(builder::setDefaultMaxGroups);
+ req.defaultMaxHits().ifPresent(builder::setDefaultMaxHits);
builder.build();
RequestContext ctx = new RequestContext(req, builder.getTransform());
diff --git a/container-search/src/main/java/com/yahoo/search/grouping/vespa/RequestBuilder.java b/container-search/src/main/java/com/yahoo/search/grouping/vespa/RequestBuilder.java
index e636c0d63a6..5ee6f7bc604 100644
--- a/container-search/src/main/java/com/yahoo/search/grouping/vespa/RequestBuilder.java
+++ b/container-search/src/main/java/com/yahoo/search/grouping/vespa/RequestBuilder.java
@@ -27,6 +27,8 @@ class RequestBuilder {
private final GroupingTransform transform;
private GroupingOperation root;
private int tag = 0;
+ private int defaultMaxHits = -1;
+ private int defaultMaxGroups = -1;
/**
* Constructs a new instance of this class.
@@ -138,6 +140,10 @@ class RequestBuilder {
return this;
}
+ public RequestBuilder setDefaultMaxGroups(int v) { this.defaultMaxGroups = v; return this; }
+
+ public RequestBuilder setDefaultMaxHits(int v) { this.defaultMaxHits = v; return this; }
+
private void processRequestNode(BuildFrame frame) {
int level = frame.astNode.getLevel();
if (level > 2) {
@@ -173,10 +179,16 @@ class RequestBuilder {
grpLevel.setPrecision(frame.state.precision + offset);
frame.state.precision = null;
}
+ int max = -1;
if (frame.state.max != null) {
- transform.putMax(tag, frame.state.max, "group list");
- grpLevel.setMaxGroups(LOOKAHEAD + frame.state.max + offset);
+ max = frame.state.max;
frame.state.max = null;
+ } else if (defaultMaxGroups >= 0) {
+ max = defaultMaxGroups;
+ }
+ if (max >= 0) {
+ transform.putMax(tag, max, "group list");
+ grpLevel.setMaxGroups(LOOKAHEAD + max + offset);
}
frame.grouping.getLevels().add(grpLevel);
}
@@ -285,11 +297,17 @@ class RequestBuilder {
throw new UnsupportedOperationException("Can not label expression '" + exp + "'.");
}
HitsAggregationResult hits = (HitsAggregationResult)result;
+ int max = -1;
if (frame.state.max != null) {
- transform.putMax(tag, frame.state.max, "hit list");
- int offset = transform.getOffset(tag);
- hits.setMaxHits(LOOKAHEAD + frame.state.max + offset);
+ max = frame.state.max;
frame.state.max = null;
+ } else if (defaultMaxHits >= 0) {
+ max = defaultMaxHits;
+ }
+ if (max >= 0) {
+ transform.putMax(tag, max, "hit list");
+ int offset = transform.getOffset(tag);
+ hits.setMaxHits(LOOKAHEAD + max + offset);
}
transform.putLabel(group.getTag(), tag, frame.state.label, "hit list");
} else {
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
index ba225722fd0..418d7121769 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
@@ -212,7 +212,7 @@ public class ItemsCommonStuffTestCase {
w.setConnectivity(v, 1.0);
String expected = "puppy";
String expected2 = "kvalp";
- EquivItem e = new EquivItem(w, Arrays.asList(new String[] { expected, expected2 }));
+ EquivItem e = new EquivItem(w, Arrays.asList(expected, expected2));
assertEquals(1.0, e.getConnectivity(), 1e-9);
assertSame(v, e.getConnectedItem());
assertEquals(expected, ((WordItem) e.getItem(1)).getWord());
diff --git a/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java
index 4397831af6e..29d9f7802c1 100644
--- a/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java
@@ -698,6 +698,36 @@ public class RequestBuilderTestCase {
assertOutput(test);
}
+ @Test
+ public void require_that_default_max_values_from_request_builder_restricts_max_groups_and_hits() {
+ int defaultMaxHits = 19;
+ int defaultMaxGroups = 7;
+ RequestBuilder builder = new RequestBuilder(0)
+ .setDefaultMaxGroups(defaultMaxGroups)
+ .setDefaultMaxHits(defaultMaxHits)
+ .setRootOperation(GroupingOperation.fromString("all(group(foo)each(each(output(summary()))))"));
+ builder.build();
+ List<Grouping> requests = builder.getRequestList();
+ assertEquals(defaultMaxGroups + 1, requests.get(0).getLevels().get(0).getMaxGroups());
+ HitsAggregationResult hitsAggregation =
+ (HitsAggregationResult)requests.get(0).getLevels().get(0).getGroupPrototype().getAggregationResults().get(0);
+ assertEquals(defaultMaxHits + 1, hitsAggregation.getMaxHits());
+ }
+
+ @Test
+ public void require_that_default_max_values_from_request_builder_restricts_respects_explicit_max() {
+ RequestBuilder builder = new RequestBuilder(0)
+ .setDefaultMaxGroups(7)
+ .setDefaultMaxHits(19)
+ .setRootOperation(GroupingOperation.fromString("all(group(foo)max(11)each(max(21)each(output(summary()))))"));
+ builder.build();
+ List<Grouping> requests = builder.getRequestList();
+ assertEquals(12, requests.get(0).getLevels().get(0).getMaxGroups());
+ HitsAggregationResult hitsAggregation =
+ (HitsAggregationResult)requests.get(0).getLevels().get(0).getGroupPrototype().getAggregationResults().get(0);
+ assertEquals(22, hitsAggregation.getMaxHits());
+ }
+
private static CompositeContinuation newComposite(EncodableContinuation... conts) {
CompositeContinuation ret = new CompositeContinuation();
for (EncodableContinuation cont : conts) {
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
index f7876f9cddd..5d8fae5cf0a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
@@ -20,7 +20,7 @@ public interface AccessControlService {
boolean decideSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials, boolean approve);
boolean requestSshAccess(TenantName tenantName);
AthenzRoleInformation getAccessRoleInformation(TenantName tenantName);
- void setPreapprovedAccess(TenantName tenantName, boolean preapproved);
- boolean getPreapprovedAccess(TenantName tenantName);
+ void setManagedAccess(TenantName tenantName, boolean managedAccess);
+ boolean getManagedAccess(TenantName tenantName);
Collection<AthenzUser> listMembers();
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
index 2e4f3f16218..f761734aa13 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
@@ -116,27 +116,27 @@ public class AthenzAccessControlService implements AccessControlService {
).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"));
}
- public void setPreapprovedAccess(TenantName tenantName, boolean preapprovedAccess) {
+ public void setManagedAccess(TenantName tenantName, boolean managedAccess) {
vespaZmsClient.ifPresentOrElse(
zms -> {
var role = sshRole(tenantName);
var assertion = getApprovalAssertion(role);
- if (preapprovedAccess) {
- zms.addPolicyRule(role.domain(), ACCESS_APPROVAL_POLICY, assertion.action(), assertion.resource(), assertion.role());
- } else {
+ if (managedAccess) {
zms.deletePolicyRule(role.domain(), ACCESS_APPROVAL_POLICY, assertion.action(), assertion.resource(), assertion.role());
+ } else {
+ zms.addPolicyRule(role.domain(), ACCESS_APPROVAL_POLICY, assertion.action(), assertion.resource(), assertion.role());
}
},() -> { throw new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"); });
}
- public boolean getPreapprovedAccess(TenantName tenantName) {
+ public boolean getManagedAccess(TenantName tenantName) {
return vespaZmsClient.map(
zms -> {
var role = sshRole(tenantName);
var approvalAssertion = getApprovalAssertion(role);
return zms.getPolicy(role.domain(), ACCESS_APPROVAL_POLICY)
- .map(policy -> policy.assertions().stream().anyMatch(assertion -> assertion.satisfies(approvalAssertion)))
- .orElse(false);
+ .map(policy -> policy.assertions().stream().noneMatch(assertion -> assertion.satisfies(approvalAssertion)))
+ .orElse(true);
}).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance") );
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
index 95ebe3380d4..c0e0f0baa5d 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
@@ -50,12 +50,12 @@ public class MockAccessControlService implements AccessControlService {
}
@Override
- public void setPreapprovedAccess(TenantName tenantName, boolean preapproved) {
+ public void setManagedAccess(TenantName tenantName, boolean managedAccess) {
}
@Override
- public boolean getPreapprovedAccess(TenantName tenant) {
+ public boolean getManagedAccess(TenantName tenant) {
return false;
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
index aca8425328d..30a086a59a0 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
@@ -242,7 +242,7 @@ enum PathGroup {
/** Paths used to approve requests to access tenant resources */
accessRequestApproval(Matcher.tenant, "/application/v4/tenant/{tenant}/access/approve/{*}",
- "/application/v4/tenant/{tenant}/access/preapprove/{*}");
+ "/application/v4/tenant/{tenant}/access/managed/{*}");
final List<String> pathSpecs;
final List<Matcher> matchers;
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 dcd5d90780c..246f3fff17e 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
@@ -297,7 +297,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}")) return updateTenant(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/access/request/operator")) return requestSshAccess(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/access/approve/operator")) return approveAccessRequest(path.get("tenant"), request);
- if (path.matches("/application/v4/tenant/{tenant}/access/preapprove/operator")) return addPreapprovedAccess(path.get("tenant"));
+ if (path.matches("/application/v4/tenant/{tenant}/access/managed/operator")) return addManagedAccess(path.get("tenant"));
if (path.matches("/application/v4/tenant/{tenant}/info")) return updateTenantInfo(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/archive-access")) return allowArchiveAccess(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/secret-store/{name}")) return addSecretStore(path.get("tenant"), path.get("name"), request);
@@ -345,7 +345,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
private HttpResponse handleDELETE(Path path, HttpRequest request) {
if (path.matches("/application/v4/tenant/{tenant}")) return deleteTenant(path.get("tenant"), request);
- if (path.matches("/application/v4/tenant/{tenant}/access/preapprove/operator")) return removePreapprovedAccess(path.get("tenant"));
+ if (path.matches("/application/v4/tenant/{tenant}/access/managed/operator")) return removeManagedAccess(path.get("tenant"));
if (path.matches("/application/v4/tenant/{tenant}/key")) return removeDeveloperKey(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/archive-access")) return removeArchiveAccess(path.get("tenant"));
if (path.matches("/application/v4/tenant/{tenant}/secret-store/{name}")) return deleteSecretStore(path.get("tenant"), path.get("name"), request);
@@ -422,10 +422,10 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
var accessControlService = controller.serviceRegistry().accessControlService();
var accessRoleInformation = accessControlService.getAccessRoleInformation(tenant);
- var preapprovedAccess = accessControlService.getPreapprovedAccess(tenant);
+ var managedAccess = accessControlService.getManagedAccess(tenant);
var slime = new Slime();
var cursor = slime.setObject();
- cursor.setBool("preapprovedAccess", preapprovedAccess);
+ cursor.setBool("managedAccess", managedAccess);
accessRoleInformation.getPendingRequest()
.ifPresent(membershipRequest -> {
var requestCursor = cursor.setObject("pendingRequest");
@@ -473,23 +473,23 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
return new MessageResponse("OK");
}
- private HttpResponse addPreapprovedAccess(String tenantName) {
- return setPreapprovedAccess(tenantName, true);
+ private HttpResponse addManagedAccess(String tenantName) {
+ return setManagedAccess(tenantName, true);
}
- private HttpResponse removePreapprovedAccess(String tenantName) {
- return setPreapprovedAccess(tenantName, false);
+ private HttpResponse removeManagedAccess(String tenantName) {
+ return setManagedAccess(tenantName, false);
}
- private HttpResponse setPreapprovedAccess(String tenantName, boolean preapprovedAccess) {
+ private HttpResponse setManagedAccess(String tenantName, boolean managedAccess) {
var tenant = TenantName.from(tenantName);
if (controller.tenants().require(tenant).type() != Tenant.Type.cloud)
return ErrorResponse.badRequest("Can only set access privel for cloud tenants");
- controller.serviceRegistry().accessControlService().setPreapprovedAccess(tenant, preapprovedAccess);
+ controller.serviceRegistry().accessControlService().setManagedAccess(tenant, managedAccess);
var slime = new Slime();
- slime.setObject().setBool("preapprovedAccess", preapprovedAccess);
+ slime.setObject().setBool("managedAccess", managedAccess);
return new SlimeJsonResponse(slime);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
index 792ec36bbb3..162890ff74d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
@@ -59,7 +59,7 @@ public class VespaVersion implements Comparable<VespaVersion> {
if ( ! failingOnThis.with(UpgradePolicy.canary).isEmpty())
return Confidence.broken;
- // 'broken' if 4 non-canary was broken by this, and that is at least 10% of all
+ // 'broken' if 4 non-canary was broken by this, and that is at least 5% of all
if (nonCanaryApplicationsBroken(statistics.version(), failingOnThis, productionOnThis))
return Confidence.broken;
@@ -173,9 +173,9 @@ public class VespaVersion implements Comparable<VespaVersion> {
if (productionNonCanaries.size() + failingNonCanaries.size() == 0) return false;
- // 'broken' if 4 non-canary was broken by this, and that is at least 10% of all
+ // 'broken' if 4 non-canary was broken by this, and that is at least 5% of all
int brokenByThisVersion = failingNonCanaries.size();
- return brokenByThisVersion >= 4 && brokenByThisVersion >= productionOnThis.size() * 0.1;
+ return brokenByThisVersion >= 4 && brokenByThisVersion >= productionOnThis.size() * 0.05;
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java
index 234ef0b37c5..30fb9ac03de 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java
@@ -81,6 +81,7 @@ public class StorageMaintainer {
}
public boolean syncLogs(NodeAgentContext context, boolean throttle) {
+ if (context.zone().getCloudName().value().equals("gcp")) return false;
Optional<URI> archiveUri = context.node().archiveUri();
if (archiveUri.isEmpty()) return false;
ApplicationId owner = context.node().owner().orElseThrow();
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/servicedump/VespaServiceDumperImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/servicedump/VespaServiceDumperImpl.java
index 0ea8c57dc57..93195a3c340 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/servicedump/VespaServiceDumperImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/servicedump/VespaServiceDumperImpl.java
@@ -61,6 +61,8 @@ public class VespaServiceDumperImpl implements VespaServiceDumper {
@Override
public void processServiceDumpRequest(NodeAgentContext context) {
+ if (context.zone().getCloudName().value().equals("gcp")) return;
+
Instant startedAt = clock.instant();
NodeSpec nodeSpec = context.node();
ServiceDumpReport request = nodeSpec.reports().getReport(ServiceDumpReport.REPORT_ID, ServiceDumpReport.class)
diff --git a/searchlib/src/tests/transactionlog/translogclient_test.cpp b/searchlib/src/tests/transactionlog/translogclient_test.cpp
index bf3a269107c..a922795d570 100644
--- a/searchlib/src/tests/transactionlog/translogclient_test.cpp
+++ b/searchlib/src/tests/transactionlog/translogclient_test.cpp
@@ -61,21 +61,42 @@ createDomainConfig(uint32_t partSizeLimit) {
.setEncoding(Encoding(Encoding::xxh64, Encoding::none_multi));
}
+// Used to signal 'eof' when visiting in a way that makes sure the
+// stuff we have visited is visible to the test code.
+class Eof {
+private:
+ std::atomic<bool> _eof;
+public:
+ Eof() : _eof(false) {}
+ void set() {
+ _eof.store(true, std::memory_order_release);
+ }
+ bool wait() const {
+ for (size_t i = 0; !_eof.load(std::memory_order_relaxed) && (i < 120000); i++) {
+ std::this_thread::sleep_for(1ms);
+ }
+ return _eof.load(std::memory_order_acquire);
+ }
+ void clear() {
+ _eof = false;
+ }
+};
+
class CallBackTest : public Callback
{
private:
RPC::Result receive(const Packet & packet) override;
- void eof() override { _eof = true; }
+ void eof() override { _eof.set(); }
typedef std::map<SerialNum, std::unique_ptr<ByteBuffer>> PacketMap;
PacketMap _packetMap;
+ Eof _eof;
public:
- CallBackTest() : _eof(false) { }
+ CallBackTest() : _packetMap(), _eof() { }
size_t size() const { return _packetMap.size(); }
bool hasSerial(SerialNum n) const { return (_packetMap.find(n) != _packetMap.end()); }
- void clear() { _eof = false; _packetMap.clear(); }
+ void clear() { _eof.clear(); _packetMap.clear(); }
const ByteBuffer & packet(SerialNum n) { return *(_packetMap.find(n)->second); }
-
- bool _eof;
+ bool wait_for_eof() const { return _eof.wait(); }
};
RPC::Result
@@ -96,11 +117,12 @@ class CallBackManyTest : public Callback
{
private:
RPC::Result receive(const Packet & packet) override;
- void eof() override { _eof = true; }
+ void eof() override { _eof.set(); }
+ Eof _eof;
public:
- explicit CallBackManyTest(size_t start) : _eof(false), _count(start), _value(start) { }
- void clear() { _eof = false; _count = 0; _value = 0; }
- bool _eof;
+ explicit CallBackManyTest(size_t start) : _eof(), _count(start), _value(start) { }
+ void clear() { _eof.clear(); _count = 0; _value = 0; }
+ bool wait_for_eof() const { return _eof.wait(); }
size_t _count;
size_t _value;
};
@@ -127,10 +149,11 @@ public:
typedef std::map<SerialNum, Identifiable *> PacketMap;
private:
RPC::Result receive(const Packet & packet) override;
- void eof() override { _eof = true; }
+ void eof() override { _eof.set(); }
PacketMap _packetMap;
+ Eof _eof;
public:
- CallBackUpdate() : _eof(false) { }
+ CallBackUpdate() : _packetMap(), _eof() { }
~CallBackUpdate() override {
while (_packetMap.begin() != _packetMap.end()) {
delete _packetMap.begin()->second;
@@ -139,7 +162,7 @@ public:
}
bool hasSerial(SerialNum n) const { return (_packetMap.find(n) != _packetMap.end()); }
const PacketMap & map() const { return _packetMap; }
- bool _eof;
+ bool wait_for_eof() const { return _eof.wait(); }
};
@@ -180,15 +203,16 @@ class CallBackStatsTest : public Callback
{
private:
RPC::Result receive(const Packet & packet) override;
- void eof() override { _eof = true; }
+ void eof() override { _eof.set(); }
+ Eof _eof;
public:
- CallBackStatsTest() : _eof(false),
+ CallBackStatsTest() : _eof(),
_count(0), _inOrder(0),
_firstSerial(0), _lastSerial(0),
_prevSerial(0) { }
- void clear() { _eof = false; _count = 0; _inOrder = 0;
+ void clear() { _eof.clear(); _count = 0; _inOrder = 0;
_firstSerial = 0; _lastSerial = 0; _inOrder = 0; }
- bool _eof;
+ bool wait_for_eof() const { return _eof.wait(); }
uint64_t _count;
uint64_t _inOrder; // increase when next entry is one above previous
SerialNum _firstSerial;
@@ -409,8 +433,7 @@ visitDomainTest(TransLogClient & tls, Session * s1, const vespalib::string & nam
auto visitor = tls.createVisitor(name, ca);
ASSERT_TRUE(visitor);
EXPECT_TRUE( visitor->visit(0, 1) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- EXPECT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_TRUE( ! ca.hasSerial(0) );
EXPECT_TRUE( ca.hasSerial(1) );
EXPECT_TRUE( ! ca.hasSerial(2) );
@@ -419,8 +442,7 @@ visitDomainTest(TransLogClient & tls, Session * s1, const vespalib::string & nam
visitor = tls.createVisitor(name, ca);
ASSERT_TRUE(visitor.get());
EXPECT_TRUE( visitor->visit(1, 2) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- EXPECT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_TRUE( ! ca.hasSerial(0) );
EXPECT_TRUE( ! ca.hasSerial(1) );
EXPECT_TRUE( ca.hasSerial(2) );
@@ -430,8 +452,7 @@ visitDomainTest(TransLogClient & tls, Session * s1, const vespalib::string & nam
visitor = tls.createVisitor(name, ca);
EXPECT_TRUE(visitor.get());
EXPECT_TRUE( visitor->visit(0, 3) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- EXPECT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_TRUE( ! ca.hasSerial(0) );
EXPECT_TRUE( ca.hasSerial(1) );
EXPECT_TRUE( ca.hasSerial(2) );
@@ -441,8 +462,7 @@ visitDomainTest(TransLogClient & tls, Session * s1, const vespalib::string & nam
visitor = tls.createVisitor(name, ca);
ASSERT_TRUE(visitor.get());
EXPECT_TRUE( visitor->visit(2, 3) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- EXPECT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_TRUE( ! ca.hasSerial(0) );
EXPECT_TRUE( !ca.hasSerial(1) );
EXPECT_TRUE( !ca.hasSerial(2) );
@@ -554,8 +574,7 @@ partialUpdateTest(const vespalib::string & testDir) {
auto visitor = tls.createVisitor("test1", ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(5, 7) );
- for (size_t i(0); ! ca._eof && (i < 1000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
ASSERT_EQUAL(1u, ca.map().size());
ASSERT_TRUE( ca.hasSerial(7) );
@@ -563,24 +582,21 @@ partialUpdateTest(const vespalib::string & testDir) {
auto visitor1 = tls.createVisitor("test1", ca1);
ASSERT_TRUE(visitor1);
ASSERT_TRUE( visitor1->visit(4, 5) );
- for (size_t i(0); ! ca1._eof && (i < 1000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca1._eof );
+ ASSERT_TRUE( ca1.wait_for_eof() );
ASSERT_TRUE( ca1.map().empty());
CallBackUpdate ca2;
auto visitor2 = tls.createVisitor("test1", ca2);
ASSERT_TRUE(visitor2);
ASSERT_TRUE( visitor2->visit(5, 6) );
- for (size_t i(0); ! ca2._eof && (i < 1000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca2._eof );
+ ASSERT_TRUE( ca2.wait_for_eof() );
ASSERT_TRUE( ca2.map().empty());
CallBackUpdate ca3;
auto visitor3 = tls.createVisitor("test1", ca3);
ASSERT_TRUE(visitor3);
ASSERT_TRUE( visitor3->visit(5, 1000) );
- for (size_t i(0); ! ca3._eof && (i < 1000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca3._eof );
+ ASSERT_TRUE( ca3.wait_for_eof() );
ASSERT_TRUE( ca3.map().size() == 1);
ASSERT_TRUE( ca3.hasSerial(7) );
}
@@ -634,10 +650,7 @@ assertVisitStats(TransLogClient &tls, const vespalib::string &domain,
auto visitor = tls.createVisitor(domain, ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(visitStart, visitEnd) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) {
- std::this_thread::sleep_for(10ms);
- }
- ASSERT_TRUE(ca._eof);
+ ASSERT_TRUE(ca.wait_for_eof());
EXPECT_EQUAL(expFirstSerial, ca._firstSerial);
EXPECT_EQUAL(expLastSerial, ca._lastSerial);
EXPECT_EQUAL(expCount, ca._count);
@@ -682,8 +695,7 @@ testSendingAlotOfDataSync(const vespalib::string & testDir) {
auto visitor = tls.createVisitor("many", ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(2, TOTAL_NUM_ENTRIES) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_EQUAL(ca._count, TOTAL_NUM_ENTRIES);
EXPECT_EQUAL(ca._value, TOTAL_NUM_ENTRIES);
}
@@ -703,8 +715,7 @@ testSendingAlotOfDataSync(const vespalib::string & testDir) {
auto visitor = tls.createVisitor(MANY, ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(2, TOTAL_NUM_ENTRIES) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_EQUAL(ca._count, TOTAL_NUM_ENTRIES);
EXPECT_EQUAL(ca._value, TOTAL_NUM_ENTRIES);
}
@@ -724,8 +735,7 @@ testSendingAlotOfDataSync(const vespalib::string & testDir) {
auto visitor = tls.createVisitor(MANY, ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(2, TOTAL_NUM_ENTRIES) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_EQUAL(ca._count, TOTAL_NUM_ENTRIES);
EXPECT_EQUAL(ca._value, TOTAL_NUM_ENTRIES);
}
@@ -753,8 +763,7 @@ void testSendingAlotOfDataAsync(const vespalib::string & testDir) {
auto visitor = tls.createVisitor(MANY, ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(2, TOTAL_NUM_ENTRIES) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_EQUAL(ca._count, TOTAL_NUM_ENTRIES);
EXPECT_EQUAL(ca._value, TOTAL_NUM_ENTRIES);
}
@@ -774,8 +783,7 @@ void testSendingAlotOfDataAsync(const vespalib::string & testDir) {
auto visitor = tls.createVisitor(MANY, ca);
ASSERT_TRUE(visitor);
ASSERT_TRUE( visitor->visit(2, TOTAL_NUM_ENTRIES) );
- for (size_t i(0); ! ca._eof && (i < 60000); i++ ) { std::this_thread::sleep_for(10ms); }
- ASSERT_TRUE( ca._eof );
+ ASSERT_TRUE( ca.wait_for_eof() );
EXPECT_EQUAL(ca._count, TOTAL_NUM_ENTRIES);
EXPECT_EQUAL(ca._value, TOTAL_NUM_ENTRIES);
}
diff --git a/searchlib/src/vespa/searchlib/parsequery/parse.h b/searchlib/src/vespa/searchlib/parsequery/parse.h
index 7db9f0e43ea..c9b7940b887 100644
--- a/searchlib/src/vespa/searchlib/parsequery/parse.h
+++ b/searchlib/src/vespa/searchlib/parsequery/parse.h
@@ -56,12 +56,12 @@ public:
ITEM_GEO_LOCATION_TERM = 27,
ITEM_TRUE = 28,
ITEM_FALSE = 29,
- ITEM_MAX = 30, // Indicates how long tables must be.
+ ITEM_MULTI_TERM = 30,
ITEM_UNDEF = 31,
};
/** A tag identifying the origin of this query node.
- * Note that descendants may origin from elsewhere.
+ * Note that descendants may originate from elsewhere.
* If changes necessary:
* NB! Append at end of list - corresponding type
* used in Juniper and updates of these two types must be synchronized.
diff --git a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp
index c28446cf01f..b31173c74c2 100644
--- a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp
+++ b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp
@@ -187,7 +187,7 @@ SimpleQueryStackItem::AppendBuffer(RawBuf *buf) const
buf->appendCompressedPositiveNumber(_arg3); // explore_additional_hits
break;
case ITEM_PREDICATE_QUERY: // not handled at all here
- case ITEM_MAX:
+ case ITEM_MULTI_TERM: // TODO: handle
case ITEM_UNDEF:
abort();
break;
diff --git a/vespajlib/src/main/java/com/yahoo/collections/CopyOnWriteHashMap.java b/vespajlib/src/main/java/com/yahoo/collections/CopyOnWriteHashMap.java
index 424e850426c..218d0c407ec 100644
--- a/vespajlib/src/main/java/com/yahoo/collections/CopyOnWriteHashMap.java
+++ b/vespajlib/src/main/java/com/yahoo/collections/CopyOnWriteHashMap.java
@@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* A hashmap wrapper which defers cloning of the enclosed map until it is written to.
@@ -21,8 +22,8 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
private Map<K,V> map;
- /** True when this class is allowed to write to the map */
- private boolean writable = true;
+ /** This class may write to the map if it is the sole owner */
+ private AtomicInteger owners = new AtomicInteger(1);
/** Lazily initialized view */
private transient Set<Map.Entry<K,V>> entrySet = null;
@@ -40,13 +41,18 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
}
private void makeReadOnly() {
- writable = false;
+ owners.incrementAndGet();
+ }
+
+ private boolean isWritable() {
+ return owners.get() == 1;
}
private void makeWritable() {
- if (writable) return;
+ if (isWritable()) return;
map = copyMap(map);
- writable = true;
+ owners.decrementAndGet();
+ owners = new AtomicInteger(1);
entrySet = null;
}
@@ -62,8 +68,7 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
public CopyOnWriteHashMap<K,V> clone() {
try {
CopyOnWriteHashMap<K,V> clone = (CopyOnWriteHashMap<K,V>)super.clone();
- this.makeReadOnly();
- clone.makeReadOnly();
+ makeReadOnly(); // owners shared with clone
return clone;
}
catch (CloneNotSupportedException e) {
@@ -94,7 +99,7 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
@Override
public boolean equals(Object other) {
if ( ! (other instanceof CopyOnWriteHashMap)) return false;
- return this.map.equals(((CopyOnWriteHashMap)other).map);
+ return this.map.equals(((CopyOnWriteHashMap<?, ?>)other).map);
}
@Override
@@ -137,7 +142,7 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
private class EntryIterator implements Iterator<Map.Entry<K,V>> {
/** Wrapped iterator */
- private Iterator<Map.Entry<K,V>> mapIterator;
+ private final Iterator<Map.Entry<K,V>> mapIterator;
public EntryIterator() {
mapIterator = map.entrySet().iterator();
@@ -152,7 +157,7 @@ public class CopyOnWriteHashMap<K,V> extends AbstractMap<K,V> implements Cloneab
}
public void remove() {
- if ( ! writable)
+ if ( ! isWritable())
throw new UnsupportedOperationException("Cannot perform the copy-on-write operation during iteration");
mapIterator.remove();
}
diff --git a/vespajlib/src/main/java/com/yahoo/text/Utf8.java b/vespajlib/src/main/java/com/yahoo/text/Utf8.java
index 91bbb86d3fc..b2b6fa13b70 100644
--- a/vespajlib/src/main/java/com/yahoo/text/Utf8.java
+++ b/vespajlib/src/main/java/com/yahoo/text/Utf8.java
@@ -111,7 +111,7 @@ public final class Utf8 {
* @return Utf8 encoded array
*/
public static byte[] toBytes(String string) {
- // This is just wrapper for String::getBytes. Pre-Java 9 this had an more efficient approach for ASCII-only strings.
+ // This is just wrapper for String::getBytes. Pre-Java 9 this had a more efficient approach for ASCII-only strings.
return string.getBytes(StandardCharsets.UTF_8);
}
/**
@@ -121,7 +121,7 @@ public final class Utf8 {
* @return Utf8 encoded array
*/
public static String toString(byte [] utf8) {
- // This is just wrapper for String::new. Pre-Java 9 this had an more efficient approach for ASCII-onlu strings.
+ // This is just wrapper for String::new. Pre-Java 9 this had a more efficient approach for ASCII-onlu strings.
return new String(utf8, StandardCharsets.UTF_8);
}
diff --git a/vespajlib/src/test/java/com/yahoo/collections/CopyOnWriteHashMapTestCase.java b/vespajlib/src/test/java/com/yahoo/collections/CopyOnWriteHashMapTestCase.java
index 2072247bf96..35401a0cb19 100644
--- a/vespajlib/src/test/java/com/yahoo/collections/CopyOnWriteHashMapTestCase.java
+++ b/vespajlib/src/test/java/com/yahoo/collections/CopyOnWriteHashMapTestCase.java
@@ -2,7 +2,8 @@
package com.yahoo.collections;
import org.junit.Test;
-import static org.junit.Assert.*;
+
+import static org.junit.Assert.assertEquals;
/**
* @author bratseth
diff --git a/vespalib/src/tests/text/lowercase/lowercase_test.cpp b/vespalib/src/tests/text/lowercase/lowercase_test.cpp
index 8117dc20666..ffc6dce427c 100644
--- a/vespalib/src/tests/text/lowercase/lowercase_test.cpp
+++ b/vespalib/src/tests/text/lowercase/lowercase_test.cpp
@@ -9,13 +9,8 @@ LOG_SETUP("lowercase_test");
using namespace vespalib;
-TEST_SETUP(Test);
-
-int
-Test::Main()
+TEST("test basic lowercase")
{
- TEST_INIT("lowercase_test");
-
EXPECT_EQUAL('a', LowerCase::convert('A'));
EXPECT_EQUAL((int8_t)'a', LowerCase::convert((int8_t)'A'));
EXPECT_EQUAL((uint8_t)'a', LowerCase::convert((uint8_t)'A'));
@@ -34,5 +29,15 @@ Test::Main()
}
// printf("lowercase( %d )= %d\n", hi, lo);
}
- TEST_DONE();
}
+
+TEST("lowercase utf8 string to ucs4")
+{
+ auto res = LowerCase::convert_to_ucs4(std::string_view("ABC"));
+ EXPECT_EQUAL(3u, res.size());
+ EXPECT_EQUAL((uint32_t)'a', res[0]);
+ EXPECT_EQUAL((uint32_t)'b', res[1]);
+ EXPECT_EQUAL((uint32_t)'c', res[2]);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/vespalib/src/vespa/vespalib/text/lowercase.cpp b/vespalib/src/vespa/vespalib/text/lowercase.cpp
index 604027d2687..de6c5956fcb 100644
--- a/vespalib/src/vespa/vespalib/text/lowercase.cpp
+++ b/vespalib/src/vespa/vespalib/text/lowercase.cpp
@@ -20,6 +20,18 @@ LowerCase::convert(vespalib::stringref input)
return output;
}
+std::vector<uint32_t>
+LowerCase::convert_to_ucs4(vespalib::stringref input)
+{
+ std::vector<uint32_t> result;
+ result.reserve(input.size());
+ Utf8Reader reader(input.data());
+ while (reader.hasMore()) {
+ result.emplace_back(convert(reader.getChar()));
+ }
+ return result;
+}
+
/*
NOTE: the tables below are generated from Java code to
diff --git a/vespalib/src/vespa/vespalib/text/lowercase.h b/vespalib/src/vespa/vespalib/text/lowercase.h
index e0ed742c3c5..dc081c6ba2d 100644
--- a/vespalib/src/vespa/vespalib/text/lowercase.h
+++ b/vespalib/src/vespa/vespalib/text/lowercase.h
@@ -5,6 +5,7 @@
#pragma once
#include <vespa/vespalib/stllike/string.h>
+#include <vector>
namespace vespalib {
@@ -103,6 +104,15 @@ public:
* CHARACTER (U+FFFD).
**/
static vespalib::string convert(vespalib::stringref input);
+
+ /**
+ * Lowercase a string in UTF-8 format while converting it to UCS-4 codepoints.
+ */
+ static std::vector<uint32_t> convert_to_ucs4(vespalib::stringref input);
+ static std::vector<uint32_t> convert_to_ucs4(std::string_view input) {
+ return convert_to_ucs4(vespalib::stringref(input.data(), input.size()));
+ }
+
};