aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@yahooinc.com>2024-05-06 15:31:23 +0200
committerHåkon Hallingstad <hakon@yahooinc.com>2024-05-06 15:31:23 +0200
commitcf8d2ef5e0c0355245d22e5de87c645f114e68f6 (patch)
treea04ab449074a39398b2edfb108c8affb05f1d52b
parent51746a57f5d146fdd0fe1f22bbc4de0df2ef1afe (diff)
parent76554d31b3b865ed6095aee8fe67168ea0571368 (diff)
Merge branch 'master' into hakon/remove-unused-flags
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java20
-rw-r--r--container-core/src/main/java/com/yahoo/processing/request/CompoundName.java70
-rw-r--r--container-core/src/test/java/com/yahoo/processing/request/CompoundNameTestCase.java63
-rw-r--r--container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java8
-rw-r--r--container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java2
-rw-r--r--dependency-versions/pom.xml2
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonReader.java4
-rw-r--r--document/src/main/java/com/yahoo/document/json/LazyTokenBuffer.java4
-rw-r--r--document/src/main/java/com/yahoo/document/json/TokenBuffer.java2
-rw-r--r--document/src/main/java/com/yahoo/document/json/document/DocumentParser.java13
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/MetricsParser.java33
-rw-r--r--model-integration/abi-spec.json2
-rw-r--r--model-integration/src/main/java/ai/vespa/llm/clients/LocalLLM.java38
-rw-r--r--model-integration/src/main/java/ai/vespa/rankingexpression/importer/lightgbm/LightGBMImporter.java4
-rwxr-xr-xmodel-integration/src/main/resources/configdefinitions/llm-local-client.def7
-rw-r--r--model-integration/src/test/java/ai/vespa/llm/clients/LocalLLMTest.java23
-rw-r--r--predicate-search-core/src/main/java/com/yahoo/search/predicate/PredicateQueryParser.java11
-rw-r--r--vespa-feed-client-api/src/main/java/ai/vespa/feed/client/JsonFeeder.java14
-rw-r--r--vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java4
-rw-r--r--vespajlib/src/test/java/com/yahoo/slime/JsonBenchmark.java2
20 files changed, 201 insertions, 125 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
index 02a6b243054..40c9a03b126 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
@@ -132,7 +132,7 @@ public class ConstantTensorJsonValidator {
private void consumeTopObject() throws IOException {
for (var cur = parser.nextToken(); cur != JsonToken.END_OBJECT; cur = parser.nextToken()) {
assertCurrentTokenIs(JsonToken.FIELD_NAME);
- String fieldName = parser.currentName();
+ String fieldName = parser.getCurrentName();
switch (fieldName) {
case FIELD_TYPE -> consumeTypeField();
case FIELD_VALUES -> consumeValuesField();
@@ -189,7 +189,7 @@ public class ConstantTensorJsonValidator {
}
for (var cur = parser.nextToken(); cur != JsonToken.END_OBJECT; cur = parser.nextToken()) {
assertCurrentTokenIs(JsonToken.FIELD_NAME);
- validateNumeric(parser.currentName(), parser.nextToken());
+ validateNumeric(parser.getCurrentName(), parser.nextToken());
}
}
@@ -199,7 +199,7 @@ public class ConstantTensorJsonValidator {
boolean seenValue = false;
for (int i = 0; i < 2; i++) {
assertNextTokenIs(JsonToken.FIELD_NAME);
- String fieldName = parser.currentName();
+ String fieldName = parser.getCurrentName();
switch (fieldName) {
case FIELD_ADDRESS -> {
validateTensorAddress(new HashSet<>(tensorDimensions.keySet()));
@@ -228,13 +228,13 @@ public class ConstantTensorJsonValidator {
// Iterate within the address key, value pairs
while ((parser.nextToken() != JsonToken.END_OBJECT)) {
assertCurrentTokenIs(JsonToken.FIELD_NAME);
- String dimensionName = parser.currentName();
+ String dimensionName = parser.getCurrentName();
TensorType.Dimension dimension = tensorDimensions.get(dimensionName);
if (dimension == null) {
- throw new InvalidConstantTensorException(parser, String.format("Tensor dimension '%s' does not exist", dimensionName));
+ throw new InvalidConstantTensorException(parser, String.format("Tensor dimension '%s' does not exist", parser.getCurrentName()));
}
if (!cellDimensions.contains(dimensionName)) {
- throw new InvalidConstantTensorException(parser, String.format("Duplicate tensor dimension '%s'", dimensionName));
+ throw new InvalidConstantTensorException(parser, String.format("Duplicate tensor dimension '%s'", parser.getCurrentName()));
}
cellDimensions.remove(dimensionName);
validateLabel(dimension);
@@ -300,7 +300,7 @@ public class ConstantTensorJsonValidator {
}
private void assertCurrentTokenIs(JsonToken wantedToken) {
- assertTokenIs(parser.currentToken(), wantedToken);
+ assertTokenIs(parser.getCurrentToken(), wantedToken);
}
private void assertNextTokenIs(JsonToken wantedToken) throws IOException {
@@ -316,11 +316,11 @@ public class ConstantTensorJsonValidator {
static class InvalidConstantTensorException extends IllegalArgumentException {
InvalidConstantTensorException(JsonParser parser, String message) {
- super(message + " " + parser.currentLocation().toString());
+ super(message + " " + parser.getCurrentLocation().toString());
}
InvalidConstantTensorException(JsonParser parser, Exception base) {
- super("Failed to parse JSON stream " + parser.currentLocation().toString(), base);
+ super("Failed to parse JSON stream " + parser.getCurrentLocation().toString(), base);
}
InvalidConstantTensorException(IOException base) {
@@ -412,7 +412,7 @@ public class ConstantTensorJsonValidator {
boolean seenValues = false;
for (int i = 0; i < 2; i++) {
assertNextTokenIs(JsonToken.FIELD_NAME);
- String fieldName = parser.currentName();
+ String fieldName = parser.getCurrentName();
switch (fieldName) {
case FIELD_ADDRESS -> {
validateTensorAddress(new HashSet<>(mappedDims));
diff --git a/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java b/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java
index b4536a1c56b..440df4f9be9 100644
--- a/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java
+++ b/container-core/src/main/java/com/yahoo/processing/request/CompoundName.java
@@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import static com.yahoo.text.Lowercase.toLowerCase;
@@ -74,41 +75,52 @@ public final class CompoundName {
* @param compounds the compounds of this name
*/
private CompoundName(String name, String [] compounds, boolean useCache) {
- if (name == null) throw new NullPointerException("Name can not be null");
-
- this.name = name;
+ this.name = Objects.requireNonNull(name, "Name can not be null");
this.lowerCasedName = toLowerCase(name);
- if (compounds.length == 1 && compounds[0].isEmpty()) {
- this.compounds = List.of();
- this.hashCode = 0;
- rest = this;
- first = this;
+ if (compounds.length == 1) {
+ if (compounds[0].isEmpty()) {
+ this.compounds = List.of();
+ this.hashCode = 0;
+ rest = first = this;
+ return;
+ }
+ this.compounds = new ImmutableArrayList(compounds);
+ this.hashCode = this.compounds.hashCode();
+ rest = first = empty;
return;
}
- this.compounds = new ImmutableArrayList(compounds);
- this.hashCode = this.compounds.hashCode();
-
- if (compounds.length > 1) {
- String restName = name.substring(compounds[0].length()+1);
- if (useCache) {
- rest = cache.computeIfAbsent(restName, (key) -> new CompoundName(key, Arrays.copyOfRange(compounds, 1, compounds.length), useCache));
- } else {
- rest = new CompoundName(restName, Arrays.copyOfRange(compounds, 1, compounds.length), useCache);
+ CompoundName[] children = new CompoundName[compounds.length];
+ for (int i = 0; i + 1 < children.length; i++) {
+ int start = 0, end = i == 0 ? -1 : children[0].name.length();
+ for (int j = 0; j + i < children.length; j++) {
+ end += compounds[j + i].length() + 1;
+ if (end == start) throw new IllegalArgumentException("'" + name + "' is not a legal compound name. " +
+ "Consecutive, leading or trailing dots are not allowed.");
+ String subName = this.name.substring(start, end);
+ CompoundName cached = cache.get(subName);
+ children[j] = cached != null ? cached
+ : new CompoundName(subName,
+ this.lowerCasedName.substring(start, end),
+ Arrays.copyOfRange(compounds, j, j + i + 1),
+ i == 0 ? empty : children[j + 1],
+ i == 0 ? empty : children[j]);
+ if (useCache && cached == null) cache.put(subName, children[j]);
+ start += compounds[j].length() + 1;
}
- } else {
- rest = empty;
}
+ this.compounds = new ImmutableArrayList(compounds);
+ this.hashCode = this.compounds.hashCode();
+ this.rest = children[1];
+ this.first = children[0];
+ }
- if (compounds.length > 1) {
- String firstName = name.substring(0, name.length() - (compounds[compounds.length-1].length()+1));
- if (useCache) {
- first = cache.computeIfAbsent(firstName, (key) -> new CompoundName(key, Arrays.copyOfRange(compounds, 0, compounds.length-1), useCache));
- } else {
- first = new CompoundName(firstName, Arrays.copyOfRange(compounds, 0, compounds.length-1), useCache);
- }
- } else {
- first = empty;
- }
+ private CompoundName(String name, String lowerCasedName, String[] compounds, CompoundName rest, CompoundName first) {
+ this.name = name;
+ this.lowerCasedName = lowerCasedName;
+ this.compounds = new ImmutableArrayList(compounds);
+ this.hashCode = this.compounds.hashCode();
+ this.rest = rest;
+ this.first = first;
}
private static List<String> parse(String s) {
diff --git a/container-core/src/test/java/com/yahoo/processing/request/CompoundNameTestCase.java b/container-core/src/test/java/com/yahoo/processing/request/CompoundNameTestCase.java
index b5143f89c78..7523a68501f 100644
--- a/container-core/src/test/java/com/yahoo/processing/request/CompoundNameTestCase.java
+++ b/container-core/src/test/java/com/yahoo/processing/request/CompoundNameTestCase.java
@@ -13,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.*;
/**
* Module local test of the basic property name building block.
*
- * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
+ * @author Steinar Knutsen
*/
public class CompoundNameTestCase {
@@ -30,22 +30,22 @@ public class CompoundNameTestCase {
}
@Test
- final void testLast() {
+ void testLast() {
assertEquals(NAME.substring(NAME.lastIndexOf('.') + 1), C_NAME.last());
}
@Test
- final void testFirst() {
+ void testFirst() {
assertEquals(NAME.substring(0, NAME.indexOf('.')), C_NAME.first());
}
@Test
- final void testRest() {
+ void testRest() {
verifyStrict(NAME.substring(NAME.indexOf('.') + 1), C_NAME.rest());
}
@Test
- final void testRestN() {
+ void testRestN() {
verifyStrict("a.b.c.d.e", C_abcde.rest(0));
verifyStrict("b.c.d.e", C_abcde.rest(1));
verifyStrict("c.d.e", C_abcde.rest(2));
@@ -53,8 +53,9 @@ public class CompoundNameTestCase {
verifyStrict("e", C_abcde.rest(4));
verifyStrict(CompoundName.empty, C_abcde.rest(5));
}
+
@Test
- final void testFirstN() {
+ void testFirstN() {
verifyStrict("a.b.c.d.e", C_abcde.first(5));
verifyStrict("a.b.c.d", C_abcde.first(4));
verifyStrict("a.b.c", C_abcde.first(3));
@@ -64,15 +65,32 @@ public class CompoundNameTestCase {
}
@Test
- final void testPrefix() {
- CompoundName abc = CompoundName.from("a.b.c");
- assertTrue(abc.hasPrefix(CompoundName.empty));
- assertTrue(abc.hasPrefix(CompoundName.from("a")));
- assertTrue(abc.hasPrefix(CompoundName.from("a.b")));
- assertTrue(abc.hasPrefix(CompoundName.from("a.b.c")));
+ void testPrefix() {
+ CompoundName abcc = CompoundName.from("a.b.cc");
+ assertTrue(abcc.hasPrefix(CompoundName.empty));
+ assertTrue(abcc.hasPrefix(CompoundName.from("a")));
+ assertTrue(abcc.hasPrefix(CompoundName.from("a.b")));
+ assertTrue(abcc.hasPrefix(CompoundName.from("a.b.cc")));
- assertFalse(abc.hasPrefix(CompoundName.from("a.b.c.d")));
- assertFalse(abc.hasPrefix(CompoundName.from("a.b.d")));
+ assertFalse(abcc.hasPrefix(CompoundName.from("a.b.c")));
+ assertFalse(abcc.hasPrefix(CompoundName.from("a.b.c.d")));
+ assertFalse(abcc.hasPrefix(CompoundName.from("a.b.d")));
+ }
+
+ @Test
+ void testIllegalCompound() {
+ assertEquals("'a.' is not a legal compound name. Names can not end with a dot.",
+ assertThrows(IllegalArgumentException.class,
+ () -> CompoundName.from("a."))
+ .getMessage());
+ assertEquals("'.b' is not a legal compound name. Consecutive, leading or trailing dots are not allowed.",
+ assertThrows(IllegalArgumentException.class,
+ () -> CompoundName.from(".b"))
+ .getMessage());
+ assertEquals("'a..b' is not a legal compound name. Consecutive, leading or trailing dots are not allowed.",
+ assertThrows(IllegalArgumentException.class,
+ () -> CompoundName.from("a..b"))
+ .getMessage());
}
@Test
@@ -82,7 +100,7 @@ public class CompoundNameTestCase {
}
@Test
- final void testSize() {
+ void testSize() {
Splitter s = Splitter.on('.');
Iterable<String> i = s.split(NAME);
int n = 0;
@@ -93,23 +111,23 @@ public class CompoundNameTestCase {
}
@Test
- final void testGet() {
+ void testGet() {
String s = C_NAME.get(0);
assertEquals(NAME.substring(0, NAME.indexOf('.')), s);
}
@Test
- final void testIsCompound() {
+ void testIsCompound() {
assertTrue(C_NAME.isCompound());
}
@Test
- final void testIsEmpty() {
+ void testIsEmpty() {
assertFalse(C_NAME.isEmpty());
}
@Test
- final void testAsList() {
+ void testAsList() {
List<String> l = C_NAME.asList();
Splitter peoplesFront = Splitter.on('.');
Iterable<String> answer = peoplesFront.split(NAME);
@@ -121,7 +139,7 @@ public class CompoundNameTestCase {
}
@Test
- final void testEqualsObject() {
+ void testEqualsObject() {
assertNotEquals(C_NAME, NAME);
assertNotEquals(C_NAME, null);
verifyStrict(C_NAME, C_NAME);
@@ -129,7 +147,7 @@ public class CompoundNameTestCase {
}
@Test
- final void testEmptyNonEmpty() {
+ void testEmptyNonEmpty() {
assertTrue(CompoundName.empty.isEmpty());
assertEquals(0, CompoundName.empty.size());
assertFalse(CompoundName.from("a").isEmpty());
@@ -140,7 +158,7 @@ public class CompoundNameTestCase {
}
@Test
- final void testGetLowerCasedName() {
+ void testGetLowerCasedName() {
assertEquals(Lowercase.toLowerCase(NAME), C_NAME.getLowerCasedName());
}
@@ -223,4 +241,5 @@ public class CompoundNameTestCase {
assertEquals("[one]", CompoundName.from("one").asList().toString());
assertEquals("[one, two, three]", CompoundName.from("one.two.three").asList().toString());
}
+
}
diff --git a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java
index fdedbdc2fd9..01167be6b8b 100644
--- a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java
+++ b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java
@@ -64,8 +64,8 @@ class Json2SingleLevelMap {
}
void parse(Map<String, String> map, String parent) throws IOException {
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parent + parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parent + parser.getCurrentName();
JsonToken token = parser.nextToken();
if ((token == JsonToken.VALUE_STRING) ||
(token == JsonToken.VALUE_NUMBER_FLOAT) ||
@@ -89,9 +89,9 @@ class Json2SingleLevelMap {
}
private String skipChildren(JsonParser parser, byte [] input) throws IOException {
- JsonLocation start = parser.currentLocation();
+ JsonLocation start = parser.getCurrentLocation();
parser.skipChildren();
- JsonLocation end = parser.currentLocation();
+ JsonLocation end = parser.getCurrentLocation();
int offset = (int)start.getByteOffset() - 1;
return new String(input, offset, (int)(end.getByteOffset() - offset), StandardCharsets.UTF_8);
}
diff --git a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
index 611df6ad284..ffa6c82e941 100644
--- a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
@@ -1532,7 +1532,7 @@ public class JsonRendererTestCase {
+ "}";
assertEquals(
"Unexpected character ('a' (code 97)): was expecting comma to separate Object entries\n" +
- " at [Source: (String)\"{ \"root\": { \"invalidvalue\": 1adsf, }}\"; line: 1, column: 40]",
+ " at [Source: (String)\"{ \"root\": { \"invalidvalue\": 1adsf, }}\"; line: 1, column: 41]",
validateJSON(json));
}
diff --git a/dependency-versions/pom.xml b/dependency-versions/pom.xml
index d27318aaaf9..0876674e8c6 100644
--- a/dependency-versions/pom.xml
+++ b/dependency-versions/pom.xml
@@ -37,7 +37,7 @@
<guava.vespa.version>33.2.0-jre</guava.vespa.version>
<guice.vespa.version>6.0.0</guice.vespa.version>
<j2objc-annotations.vespa.version>3.0.0</j2objc-annotations.vespa.version>
- <jackson2.vespa.version>2.17.1</jackson2.vespa.version>
+ <jackson2.vespa.version>2.16.2</jackson2.vespa.version>
<jackson-databind.vespa.version>${jackson2.vespa.version}</jackson-databind.vespa.version>
<jakarta.inject.vespa.version>2.0.1</jakarta.inject.vespa.version>
<javax.activation-api.vespa.version>1.2.0</javax.activation-api.vespa.version>
diff --git a/document/src/main/java/com/yahoo/document/json/JsonReader.java b/document/src/main/java/com/yahoo/document/json/JsonReader.java
index 9c621c033bd..358c0cb65e4 100644
--- a/document/src/main/java/com/yahoo/document/json/JsonReader.java
+++ b/document/src/main/java/com/yahoo/document/json/JsonReader.java
@@ -105,7 +105,7 @@ public class JsonReader {
String condition = null;
ParsedDocumentOperation operation = null;
while (JsonToken.END_OBJECT != parser.nextValue()) {
- switch (parser.currentName()) {
+ switch (parser.getCurrentName()) {
case FIELDS -> {
documentParseInfo.fieldsBuffer = new LazyTokenBuffer(parser);
VespaJsonDocumentReader vespaJsonDocumentReader = new VespaJsonDocumentReader(typeManager.getIgnoreUndefinedFields());
@@ -177,7 +177,7 @@ public class JsonReader {
state = END_OF_FEED;
throw new IllegalArgumentException(r);
}
- if (documentParseInfo.isEmpty()) {
+ if ( ! documentParseInfo.isPresent()) {
state = END_OF_FEED;
return null;
}
diff --git a/document/src/main/java/com/yahoo/document/json/LazyTokenBuffer.java b/document/src/main/java/com/yahoo/document/json/LazyTokenBuffer.java
index 53ddacf6cc3..0fbdd0b28c7 100644
--- a/document/src/main/java/com/yahoo/document/json/LazyTokenBuffer.java
+++ b/document/src/main/java/com/yahoo/document/json/LazyTokenBuffer.java
@@ -33,7 +33,7 @@ public class LazyTokenBuffer extends TokenBuffer {
public Supplier<Token> lookahead() {
return new Supplier<>() {
int localNesting = nesting();
- final Supplier<Token> buffered = LazyTokenBuffer.super.lookahead();
+ Supplier<Token> buffered = LazyTokenBuffer.super.lookahead();
@Override public Token get() {
if (localNesting == 0)
return null;
@@ -54,7 +54,7 @@ public class LazyTokenBuffer extends TokenBuffer {
JsonToken token = parser.nextValue();
if (token == null)
throw new IllegalStateException("no more JSON tokens");
- return new Token(token, parser.currentName(), parser.getText());
+ return new Token(token, parser.getCurrentName(), parser.getText());
}
catch (IOException e) {
throw new IllegalArgumentException("failed reading document JSON", e);
diff --git a/document/src/main/java/com/yahoo/document/json/TokenBuffer.java b/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
index c5c022370bf..3a48f71c4cd 100644
--- a/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
+++ b/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
@@ -99,7 +99,7 @@ public class TokenBuffer {
}
int addFromParser(JsonParser tokens) throws IOException {
- add(tokens.currentToken(), tokens.currentName(), tokens.getText());
+ add(tokens.currentToken(), tokens.getCurrentName(), tokens.getText());
return nestingOffset(tokens.currentToken());
}
diff --git a/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java b/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java
index c5bcd356c94..77e11dcf2a8 100644
--- a/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java
+++ b/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java
@@ -61,7 +61,7 @@ public class DocumentParser {
private boolean parseOneItem(DocumentParseInfo documentParseInfo, boolean docIdAndOperationIsSetExternally) throws IOException {
parser.nextValue();
processIndent();
- if (parser.currentName() == null) return false;
+ if (parser.getCurrentName() == null) return false;
if (indentLevel == 1L) {
handleIdentLevelOne(documentParseInfo, docIdAndOperationIsSetExternally);
} else if (indentLevel == 2L) {
@@ -85,18 +85,17 @@ public class DocumentParser {
private void handleIdentLevelOne(DocumentParseInfo documentParseInfo, boolean docIdAndOperationIsSetExternally)
throws IOException {
- JsonToken currentToken = parser.currentToken();
- String currentName = parser.currentName();
+ JsonToken currentToken = parser.getCurrentToken();
if ((currentToken == JsonToken.VALUE_TRUE || currentToken == JsonToken.VALUE_FALSE) &&
- CREATE_IF_NON_EXISTENT.equals(currentName)) {
+ CREATE_IF_NON_EXISTENT.equals(parser.getCurrentName())) {
documentParseInfo.create = Optional.of(currentToken == JsonToken.VALUE_TRUE);
- } else if (currentToken == JsonToken.VALUE_STRING && CONDITION.equals(currentName)) {
+ } else if (currentToken == JsonToken.VALUE_STRING && CONDITION.equals(parser.getCurrentName())) {
documentParseInfo.condition = Optional.of(parser.getText());
} else if (currentToken == JsonToken.VALUE_STRING) {
// Value is expected to be set in the header not in the document. Ignore any unknown field
// as well.
if (! docIdAndOperationIsSetExternally) {
- documentParseInfo.operationType = operationNameToOperationType(currentName);
+ documentParseInfo.operationType = operationNameToOperationType(parser.getCurrentName());
documentParseInfo.documentId = new DocumentId(parser.getText());
}
}
@@ -105,7 +104,7 @@ public class DocumentParser {
private void handleIdentLevelTwo(DocumentParseInfo documentParseInfo) {
try {
// "fields" opens a dictionary and is therefore on level two which might be surprising.
- if (parser.currentToken() == JsonToken.START_OBJECT && FIELDS.equals(parser.currentName())) {
+ if (parser.currentToken() == JsonToken.START_OBJECT && FIELDS.equals(parser.getCurrentName())) {
documentParseInfo.fieldsBuffer.bufferObject(parser);
processIndent();
}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/MetricsParser.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/MetricsParser.java
index 052b8425a45..0e33d7dbf2f 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/MetricsParser.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/MetricsParser.java
@@ -53,8 +53,8 @@ public class MetricsParser {
throw new IOException("Expected start of object, got " + parser.currentToken());
}
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
if (fieldName.equals("metrics")) {
parseMetrics(parser, consumer);
@@ -67,12 +67,12 @@ public class MetricsParser {
}
static private Instant parseSnapshot(JsonParser parser) throws IOException {
- if (parser.currentToken() != JsonToken.START_OBJECT) {
+ if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Expected start of 'snapshot' object, got " + parser.currentToken());
}
Instant timestamp = Instant.now();
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
if (fieldName.equals("to")) {
timestamp = Instant.ofEpochSecond(parser.getLongValue());
@@ -88,12 +88,12 @@ public class MetricsParser {
// 'metrics' object with 'snapshot' and 'values' arrays
static private void parseMetrics(JsonParser parser, Collector consumer) throws IOException {
- if (parser.currentToken() != JsonToken.START_OBJECT) {
+ if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Expected start of 'metrics' object, got " + parser.currentToken());
}
Instant timestamp = Instant.now();
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
if (fieldName.equals("snapshot")) {
timestamp = parseSnapshot(parser);
@@ -109,7 +109,7 @@ public class MetricsParser {
// 'values' array
static private void parseMetricValues(JsonParser parser, Instant timestamp, Collector consumer) throws IOException {
- if (parser.currentToken() != JsonToken.START_ARRAY) {
+ if (parser.getCurrentToken() != JsonToken.START_ARRAY) {
throw new IOException("Expected start of 'metrics:values' array, got " + parser.currentToken());
}
@@ -126,8 +126,8 @@ public class MetricsParser {
String description = "";
Map<DimensionId, String> dim = Map.of();
List<Map.Entry<String, Number>> values = List.of();
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
switch (fieldName) {
case "name" -> name = parser.getText();
@@ -154,8 +154,8 @@ public class MetricsParser {
Set<Dimension> dimensions = new HashSet<>();
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String fieldName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
if (token == JsonToken.VALUE_STRING){
@@ -180,16 +180,17 @@ public class MetricsParser {
private static List<Map.Entry<String, Number>> parseValues(JsonParser parser) throws IOException {
List<Map.Entry<String, Number>> metrics = new ArrayList<>();
- for (parser.nextToken(); parser.currentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
- String metricName = parser.currentName();
+ for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) {
+ String fieldName = parser.getCurrentName();
JsonToken token = parser.nextToken();
+ String metricName = fieldName;
if (token == JsonToken.VALUE_NUMBER_INT) {
metrics.add(Map.entry(metricName, parser.getLongValue()));
} else if (token == JsonToken.VALUE_NUMBER_FLOAT) {
double value = parser.getValueAsDouble();
metrics.add(Map.entry(metricName, value == ZERO_DOUBLE ? ZERO_DOUBLE : value));
} else {
- throw new IllegalArgumentException("Value for aggregator '" + metricName + "' is not a number");
+ throw new IllegalArgumentException("Value for aggregator '" + fieldName + "' is not a number");
}
}
return metrics;
diff --git a/model-integration/abi-spec.json b/model-integration/abi-spec.json
index e7130d9c777..31f2b64d728 100644
--- a/model-integration/abi-spec.json
+++ b/model-integration/abi-spec.json
@@ -94,6 +94,7 @@
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder model(com.yahoo.config.ModelReference)",
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder parallelRequests(int)",
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder maxQueueSize(int)",
+ "public ai.vespa.llm.clients.LlmLocalClientConfig$Builder maxQueueWait(int)",
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder useGpu(boolean)",
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder gpuLayers(int)",
"public ai.vespa.llm.clients.LlmLocalClientConfig$Builder threads(int)",
@@ -139,6 +140,7 @@
"public java.nio.file.Path model()",
"public int parallelRequests()",
"public int maxQueueSize()",
+ "public int maxQueueWait()",
"public boolean useGpu()",
"public int gpuLayers()",
"public int threads()",
diff --git a/model-integration/src/main/java/ai/vespa/llm/clients/LocalLLM.java b/model-integration/src/main/java/ai/vespa/llm/clients/LocalLLM.java
index aa7c071b93a..b6409b5466d 100644
--- a/model-integration/src/main/java/ai/vespa/llm/clients/LocalLLM.java
+++ b/model-integration/src/main/java/ai/vespa/llm/clients/LocalLLM.java
@@ -3,6 +3,7 @@ package ai.vespa.llm.clients;
import ai.vespa.llm.InferenceParameters;
import ai.vespa.llm.LanguageModel;
+import ai.vespa.llm.LanguageModelException;
import ai.vespa.llm.completion.Completion;
import ai.vespa.llm.completion.Prompt;
import com.yahoo.component.AbstractComponent;
@@ -14,10 +15,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.logging.Logger;
@@ -29,14 +34,19 @@ import java.util.logging.Logger;
public class LocalLLM extends AbstractComponent implements LanguageModel {
private final static Logger logger = Logger.getLogger(LocalLLM.class.getName());
+
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
private final LlamaModel model;
private final ThreadPoolExecutor executor;
+ private final long queueTimeoutMilliseconds;
private final int contextSize;
private final int maxTokens;
@Inject
public LocalLLM(LlmLocalClientConfig config) {
executor = createExecutor(config);
+ queueTimeoutMilliseconds = config.maxQueueWait();
// Maximum number of tokens to generate - need this since some models can just generate infinitely
maxTokens = config.maxTokens();
@@ -74,6 +84,7 @@ public class LocalLLM extends AbstractComponent implements LanguageModel {
logger.info("Closing LLM model...");
model.close();
executor.shutdownNow();
+ scheduler.shutdownNow();
}
@Override
@@ -104,22 +115,39 @@ public class LocalLLM extends AbstractComponent implements LanguageModel {
// Todo: more options?
var completionFuture = new CompletableFuture<Completion.FinishReason>();
+ var hasStarted = new AtomicBoolean(false);
try {
- executor.submit(() -> {
+ Future<?> future = executor.submit(() -> {
+ hasStarted.set(true);
for (LlamaModel.Output output : model.generate(inferParams)) {
consumer.accept(Completion.from(output.text, Completion.FinishReason.none));
}
completionFuture.complete(Completion.FinishReason.stop);
});
+
+ if (queueTimeoutMilliseconds > 0) {
+ scheduler.schedule(() -> {
+ if ( ! hasStarted.get()) {
+ future.cancel(false);
+ String error = rejectedExecutionReason("Rejected completion due to timeout waiting to start");
+ completionFuture.completeExceptionally(new LanguageModelException(504, error));
+ }
+ }, queueTimeoutMilliseconds, TimeUnit.MILLISECONDS);
+ }
+
} catch (RejectedExecutionException e) {
// If we have too many requests (active + any waiting in queue), we reject the completion
- int activeCount = executor.getActiveCount();
- int queueSize = executor.getQueue().size();
- String error = String.format("Rejected completion due to too many requests, " +
- "%d active, %d in queue", activeCount, queueSize);
+ String error = rejectedExecutionReason("Rejected completion due to too many requests");
throw new RejectedExecutionException(error);
}
return completionFuture;
}
+ private String rejectedExecutionReason(String prepend) {
+ int activeCount = executor.getActiveCount();
+ int queueSize = executor.getQueue().size();
+ return String.format("%s, %d active, %d in queue", prepend, activeCount, queueSize);
+ }
+
+
}
diff --git a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/lightgbm/LightGBMImporter.java b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/lightgbm/LightGBMImporter.java
index 6a1e2f2562a..e1d2f8802a6 100644
--- a/model-integration/src/main/java/ai/vespa/rankingexpression/importer/lightgbm/LightGBMImporter.java
+++ b/model-integration/src/main/java/ai/vespa/rankingexpression/importer/lightgbm/LightGBMImporter.java
@@ -34,9 +34,9 @@ public class LightGBMImporter extends ModelImporter {
private boolean probe(File modelFile) {
try (JsonParser parser = Jackson.mapper().createParser(modelFile)) {
while (parser.nextToken() != null) {
- JsonToken token = parser.currentToken();
+ JsonToken token = parser.getCurrentToken();
if (token == JsonToken.FIELD_NAME) {
- if ("tree_info".equals(parser.currentName())) return true;
+ if ("tree_info".equals(parser.getCurrentName())) return true;
}
}
return false;
diff --git a/model-integration/src/main/resources/configdefinitions/llm-local-client.def b/model-integration/src/main/resources/configdefinitions/llm-local-client.def
index 4823a53ec46..6b83ffd0751 100755
--- a/model-integration/src/main/resources/configdefinitions/llm-local-client.def
+++ b/model-integration/src/main/resources/configdefinitions/llm-local-client.def
@@ -8,7 +8,10 @@ model model
parallelRequests int default=1
# Additional number of requests to put in queue for processing before starting to reject new requests
-maxQueueSize int default=10
+maxQueueSize int default=100
+
+# Max number of milliseoncds to wait in the queue before rejecting a request
+maxQueueWait int default=10000
# Use GPU
useGpu bool default=true
@@ -24,6 +27,6 @@ threads int default=-1
# Context is divided between parallel requests. So for 10 parallel requests, each "slot" gets 1/10 of the context
contextSize int default=4096
-# Maximum number of tokens to process in one request - overriden by inference parameters
+# Maximum number of tokens to process in one request - overridden by inference parameters
maxTokens int default=512
diff --git a/model-integration/src/test/java/ai/vespa/llm/clients/LocalLLMTest.java b/model-integration/src/test/java/ai/vespa/llm/clients/LocalLLMTest.java
index a3b260f3fb5..4db1140d171 100644
--- a/model-integration/src/test/java/ai/vespa/llm/clients/LocalLLMTest.java
+++ b/model-integration/src/test/java/ai/vespa/llm/clients/LocalLLMTest.java
@@ -2,6 +2,7 @@
package ai.vespa.llm.clients;
import ai.vespa.llm.InferenceParameters;
+import ai.vespa.llm.LanguageModelException;
import ai.vespa.llm.completion.Completion;
import ai.vespa.llm.completion.Prompt;
import ai.vespa.llm.completion.StringPrompt;
@@ -96,7 +97,6 @@ public class LocalLLMTest {
try {
for (int i = 0; i < promptsToUse; i++) {
final var seq = i;
-
completions.set(seq, new StringBuilder());
futures.set(seq, llm.completeAsync(StringPrompt.from(prompts.get(seq)), defaultOptions(), completion -> {
completions.get(seq).append(completion.text());
@@ -122,8 +122,9 @@ public class LocalLLMTest {
var prompts = testPrompts();
var promptsToUse = prompts.size();
var parallelRequests = 2;
- var additionalQueue = 1;
- // 7 should be rejected
+ var additionalQueue = 100;
+ var queueWaitTime = 10;
+ // 8 should be rejected due to queue wait time
var futures = new ArrayList<CompletableFuture<Completion.FinishReason>>(Collections.nCopies(promptsToUse, null));
var completions = new ArrayList<StringBuilder>(Collections.nCopies(promptsToUse, null));
@@ -131,10 +132,12 @@ public class LocalLLMTest {
var config = new LlmLocalClientConfig.Builder()
.parallelRequests(parallelRequests)
.maxQueueSize(additionalQueue)
+ .maxQueueWait(queueWaitTime)
.model(ModelReference.valueOf(model));
var llm = new LocalLLM(config.build());
var rejected = new AtomicInteger(0);
+ var timedOut = new AtomicInteger(0);
try {
for (int i = 0; i < promptsToUse; i++) {
final var seq = i;
@@ -143,7 +146,14 @@ public class LocalLLMTest {
try {
var future = llm.completeAsync(StringPrompt.from(prompts.get(seq)), defaultOptions(), completion -> {
completions.get(seq).append(completion.text());
- }).exceptionally(exception -> Completion.FinishReason.error);
+ }).exceptionally(exception -> {
+ if (exception instanceof LanguageModelException lme) {
+ if (lme.code() == 504) {
+ timedOut.incrementAndGet();
+ }
+ }
+ return Completion.FinishReason.error;
+ });
futures.set(seq, future);
} catch (RejectedExecutionException e) {
rejected.incrementAndGet();
@@ -151,13 +161,14 @@ public class LocalLLMTest {
}
for (int i = 0; i < promptsToUse; i++) {
if (futures.get(i) != null) {
- assertNotEquals(futures.get(i).join(), Completion.FinishReason.error);
+ futures.get(i).join();
}
}
} finally {
llm.deconstruct();
}
- assertEquals(7, rejected.get());
+ assertEquals(0, rejected.get());
+ assertEquals(8, timedOut.get());
}
private static InferenceParameters defaultOptions() {
diff --git a/predicate-search-core/src/main/java/com/yahoo/search/predicate/PredicateQueryParser.java b/predicate-search-core/src/main/java/com/yahoo/search/predicate/PredicateQueryParser.java
index 42b6195549e..09487506ffe 100644
--- a/predicate-search-core/src/main/java/com/yahoo/search/predicate/PredicateQueryParser.java
+++ b/predicate-search-core/src/main/java/com/yahoo/search/predicate/PredicateQueryParser.java
@@ -10,6 +10,7 @@ import java.util.Arrays;
/**
* Parses predicate queries from JSON.
+ *
* Input JSON is assumed to have the following format:
* {
* "features": [
@@ -45,7 +46,7 @@ public class PredicateQueryParser {
try (JsonParser parser = factory.createParser(json)) {
skipToken(parser, JsonToken.START_OBJECT);
while (parser.nextToken() != JsonToken.END_OBJECT) {
- String fieldName = parser.currentName();
+ String fieldName = parser.getCurrentName();
switch (fieldName) {
case "features":
parseFeatures(parser, JsonParser::getText, featureHandler);
@@ -81,7 +82,7 @@ public class PredicateQueryParser {
long subqueryBitmap = SubqueryBitmap.DEFAULT_VALUE; // Specifying subquery bitmap is optional.
while (parser.nextToken() != JsonToken.END_OBJECT) {
- String fieldName = parser.currentName();
+ String fieldName = parser.getCurrentName();
skipToken(parser, JsonToken.VALUE_STRING, JsonToken.VALUE_NUMBER_INT);
switch (fieldName) {
case "k":
@@ -99,11 +100,11 @@ public class PredicateQueryParser {
}
if (key == null) {
throw new IllegalArgumentException(
- String.format("Feature key is missing! (%s)", parser.currentLocation()));
+ String.format("Feature key is missing! (%s)", parser.getCurrentLocation()));
}
if (value == null) {
throw new IllegalArgumentException(
- String.format("Feature value is missing! (%s)", parser.currentLocation()));
+ String.format("Feature value is missing! (%s)", parser.getCurrentLocation()));
}
featureHandler.accept(key, value, subqueryBitmap);
}
@@ -113,7 +114,7 @@ public class PredicateQueryParser {
if (Arrays.stream(expected).noneMatch(e -> e.equals(actual))) {
throw new IllegalArgumentException(
String.format("Expected a token in %s, got %s (%s).",
- Arrays.toString(expected), actual, parser.currentTokenLocation()));
+ Arrays.toString(expected), actual, parser.getTokenLocation()));
}
}
diff --git a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/JsonFeeder.java b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/JsonFeeder.java
index 3111815b332..11fb6526210 100644
--- a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/JsonFeeder.java
+++ b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/JsonFeeder.java
@@ -414,7 +414,7 @@ public class JsonFeeder implements Closeable {
abstract String getDocumentJson(long start, long end);
OperationParseException parseException(String error) {
- JsonLocation location = parser.currentLocation();
+ JsonLocation location = parser.getTokenLocation();
return new OperationParseException(error + " at offset " + location.getByteOffset() +
" (line " + location.getLineNr() + ", column " + location.getColumnNr() + ")");
}
@@ -444,13 +444,13 @@ public class JsonFeeder implements Closeable {
case "create": parameters = parameters.createIfNonExistent(readBoolean()); break;
case "fields": {
expect(START_OBJECT);
- start = parser.currentTokenLocation().getByteOffset();
+ start = parser.getTokenLocation().getByteOffset();
int depth = 1;
while (depth > 0) switch (parser.nextToken()) {
case START_OBJECT: ++depth; break;
case END_OBJECT: --depth; break;
}
- end = parser.currentTokenLocation().getByteOffset() + 1;
+ end = parser.getTokenLocation().getByteOffset() + 1;
break;
}
default: throw parseException("Unexpected field name '" + parser.getText() + "'");
@@ -470,7 +470,7 @@ public class JsonFeeder implements Closeable {
if (end >= start)
throw parseException("Illegal 'fields' object for remove operation");
else
- start = end = parser.currentTokenLocation().getByteOffset(); // getDocumentJson advances buffer overwrite head.
+ start = end = parser.getTokenLocation().getByteOffset(); // getDocumentJson advances buffer overwrite head.
}
else if (end < start)
throw parseException("No 'fields' object for document");
@@ -486,14 +486,14 @@ public class JsonFeeder implements Closeable {
private void expect(JsonToken token) throws IOException {
if (parser.nextToken() != token)
- throw new OperationParseException("Expected '" + token + "' at offset " + parser.currentTokenLocation().getByteOffset() +
+ throw new OperationParseException("Expected '" + token + "' at offset " + parser.getTokenLocation().getByteOffset() +
", but found '" + parser.currentToken() + "' (" + parser.getText() + ")");
}
private String readString() throws IOException {
String value = parser.nextTextValue();
if (value == null)
- throw new OperationParseException("Expected '" + JsonToken.VALUE_STRING + "' at offset " + parser.currentTokenLocation().getByteOffset() +
+ throw new OperationParseException("Expected '" + JsonToken.VALUE_STRING + "' at offset " + parser.getTokenLocation().getByteOffset() +
", but found '" + parser.currentToken() + "' (" + parser.getText() + ")");
return value;
@@ -502,7 +502,7 @@ public class JsonFeeder implements Closeable {
private boolean readBoolean() throws IOException {
Boolean value = parser.nextBooleanValue();
if (value == null)
- throw new OperationParseException("Expected '" + JsonToken.VALUE_FALSE + "' or '" + JsonToken.VALUE_TRUE + "' at offset " + parser.currentTokenLocation().getByteOffset() +
+ throw new OperationParseException("Expected '" + JsonToken.VALUE_FALSE + "' or '" + JsonToken.VALUE_TRUE + "' at offset " + parser.getTokenLocation().getByteOffset() +
", but found '" + parser.currentToken() + "' (" + parser.getText() + ")");
return value;
diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java
index 9dd11113c0b..a30cfd5ec39 100644
--- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java
+++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java
@@ -219,13 +219,13 @@ class HttpFeedClient implements FeedClient {
throw new ResultParseException(documentId,
"Expected 'trace' to be an array, but got '" + parser.currentToken() + "' in: " +
new String(json, UTF_8));
- int start = (int) parser.currentTokenLocation().getByteOffset();
+ int start = (int) parser.getTokenLocation().getByteOffset();
int depth = 1;
while (depth > 0) switch (parser.nextToken()) {
case START_ARRAY: ++depth; break;
case END_ARRAY: --depth; break;
}
- int end = (int) parser.currentTokenLocation().getByteOffset() + 1;
+ int end = (int) parser.getTokenLocation().getByteOffset() + 1;
trace = new String(json, start, end - start, UTF_8);
break;
default:
diff --git a/vespajlib/src/test/java/com/yahoo/slime/JsonBenchmark.java b/vespajlib/src/test/java/com/yahoo/slime/JsonBenchmark.java
index cccc9667e11..ee755a44010 100644
--- a/vespajlib/src/test/java/com/yahoo/slime/JsonBenchmark.java
+++ b/vespajlib/src/test/java/com/yahoo/slime/JsonBenchmark.java
@@ -43,7 +43,7 @@ public class JsonBenchmark {
try (JsonParser jsonParser = jsonFactory.createParser(json)) {
JsonToken array = jsonParser.nextToken();
for (JsonToken token = jsonParser.nextToken(); !JsonToken.END_ARRAY.equals(token); token = jsonParser.nextToken()) {
- if (JsonToken.FIELD_NAME.equals(token) && "weight".equals(jsonParser.currentName())) {
+ if (JsonToken.FIELD_NAME.equals(token) && "weight".equals(jsonParser.getCurrentName())) {
token = jsonParser.nextToken();
count += jsonParser.getLongValue();
}