Skip to content

Commit a564af7

Browse files
jordan-powersjfreden
authored andcommitted
Update Text class to use native java ByteBuffer (elastic#127666)
This PR is a precursor to elastic#126492. It does three things: - Move org.elasticsearch.common.text.Text from :server to org.elasticsearch.xcontent.Text in :libs:x-content. - Refactor the Text class to use a java-native ByteBuffer instead of the elasticsearch BytesReference. - Add the XContentString interface, with the Text class implementing that interface.
1 parent df47187 commit a564af7

39 files changed

+132
-71
lines changed

server/src/main/java/org/elasticsearch/common/text/Text.java renamed to libs/x-content/src/main/java/org/elasticsearch/xcontent/Text.java

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,17 @@
66
* your election, the "Elastic License 2.0", the "GNU Affero General Public
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
9-
package org.elasticsearch.common.text;
10-
11-
import org.apache.lucene.util.BytesRef;
12-
import org.elasticsearch.common.bytes.BytesArray;
13-
import org.elasticsearch.common.bytes.BytesReference;
14-
import org.elasticsearch.xcontent.ToXContentFragment;
15-
import org.elasticsearch.xcontent.XContentBuilder;
9+
package org.elasticsearch.xcontent;
1610

1711
import java.io.IOException;
12+
import java.nio.ByteBuffer;
1813
import java.nio.charset.StandardCharsets;
1914

2015
/**
21-
* Both {@link String} and {@link BytesReference} representation of the text. Starts with one of those, and if
16+
* Both {@link String} and {@link ByteBuffer} representation of the text. Starts with one of those, and if
2217
* the other is requests, caches the other one in a local reference so no additional conversion will be needed.
2318
*/
24-
public final class Text implements Comparable<Text>, ToXContentFragment {
19+
public final class Text implements XContentString, Comparable<Text>, ToXContentFragment {
2520

2621
public static final Text[] EMPTY_ARRAY = new Text[0];
2722

@@ -36,31 +31,43 @@ public static Text[] convertFromStringArray(String[] strings) {
3631
return texts;
3732
}
3833

39-
private BytesReference bytes;
34+
private ByteBuffer bytes;
4035
private String text;
4136
private int hash;
37+
private int stringLength = -1;
38+
39+
/**
40+
* Construct a Text from a UTF-8 encoded ByteBuffer. Since no string length is specified, {@link #stringLength()}
41+
* will perform a string conversion to measure the string length.
42+
*/
43+
public Text(ByteBuffer bytes) {
44+
this.bytes = bytes;
45+
}
4246

43-
public Text(BytesReference bytes) {
47+
/**
48+
* Construct a Text from a UTF-8 encoded ByteBuffer and an explicit string length. Used to avoid string conversion
49+
* in {@link #stringLength()}.
50+
*/
51+
public Text(ByteBuffer bytes, int stringLength) {
4452
this.bytes = bytes;
53+
this.stringLength = stringLength;
4554
}
4655

4756
public Text(String text) {
4857
this.text = text;
4958
}
5059

5160
/**
52-
* Whether a {@link BytesReference} view of the data is already materialized.
61+
* Whether a {@link ByteBuffer} view of the data is already materialized.
5362
*/
5463
public boolean hasBytes() {
5564
return bytes != null;
5665
}
5766

58-
/**
59-
* Returns a {@link BytesReference} view of the data.
60-
*/
61-
public BytesReference bytes() {
67+
@Override
68+
public ByteBuffer bytes() {
6269
if (bytes == null) {
63-
bytes = new BytesArray(text.getBytes(StandardCharsets.UTF_8));
70+
bytes = StandardCharsets.UTF_8.encode(text);
6471
}
6572
return bytes;
6673
}
@@ -72,11 +79,20 @@ public boolean hasString() {
7279
return text != null;
7380
}
7481

75-
/**
76-
* Returns a {@link String} view of the data.
77-
*/
82+
@Override
7883
public String string() {
79-
return text == null ? bytes.utf8ToString() : text;
84+
if (text == null) {
85+
text = StandardCharsets.UTF_8.decode(bytes).toString();
86+
}
87+
return text;
88+
}
89+
90+
@Override
91+
public int stringLength() {
92+
if (stringLength < 0) {
93+
stringLength = string().length();
94+
}
95+
return stringLength;
8096
}
8197

8298
@Override
@@ -115,8 +131,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
115131
} else {
116132
// TODO: TextBytesOptimization we can use a buffer here to convert it? maybe add a
117133
// request to jackson to support InputStream as well?
118-
BytesRef br = this.bytes().toBytesRef();
119-
return builder.utf8Value(br.bytes, br.offset, br.length);
134+
assert bytes.hasArray();
135+
return builder.utf8Value(bytes.array(), bytes.arrayOffset() + bytes.position(), bytes.remaining());
120136
}
121137
}
122138
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.xcontent;
11+
12+
import java.nio.ByteBuffer;
13+
14+
public interface XContentString {
15+
/**
16+
* Returns a {@link String} view of the data.
17+
*/
18+
String string();
19+
20+
/**
21+
* Returns a UTF8-encoded {@link ByteBuffer} view of the data.
22+
*/
23+
ByteBuffer bytes();
24+
25+
/**
26+
* Returns the number of characters in the represented string.
27+
*/
28+
int stringLength();
29+
}

server/src/main/java/org/elasticsearch/cluster/service/MasterService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import org.elasticsearch.common.settings.ClusterSettings;
3737
import org.elasticsearch.common.settings.Setting;
3838
import org.elasticsearch.common.settings.Settings;
39-
import org.elasticsearch.common.text.Text;
4039
import org.elasticsearch.common.util.CollectionUtils;
4140
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
4241
import org.elasticsearch.common.util.concurrent.CountDown;
@@ -56,6 +55,7 @@
5655
import org.elasticsearch.tasks.TaskManager;
5756
import org.elasticsearch.threadpool.Scheduler;
5857
import org.elasticsearch.threadpool.ThreadPool;
58+
import org.elasticsearch.xcontent.Text;
5959

6060
import java.util.ArrayList;
6161
import java.util.Collections;

server/src/main/java/org/elasticsearch/cluster/service/PendingClusterTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import org.elasticsearch.common.io.stream.StreamInput;
1414
import org.elasticsearch.common.io.stream.StreamOutput;
1515
import org.elasticsearch.common.io.stream.Writeable;
16-
import org.elasticsearch.common.text.Text;
1716
import org.elasticsearch.core.TimeValue;
17+
import org.elasticsearch.xcontent.Text;
1818

1919
import java.io.IOException;
2020

server/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
import org.elasticsearch.common.collect.ImmutableOpenMap;
2424
import org.elasticsearch.common.geo.GeoPoint;
2525
import org.elasticsearch.common.settings.SecureString;
26-
import org.elasticsearch.common.text.Text;
2726
import org.elasticsearch.common.util.Maps;
2827
import org.elasticsearch.common.util.set.Sets;
2928
import org.elasticsearch.core.CharArrays;
3029
import org.elasticsearch.core.Nullable;
3130
import org.elasticsearch.core.TimeValue;
31+
import org.elasticsearch.xcontent.Text;
3232

3333
import java.io.EOFException;
3434
import java.io.FilterInputStream;
@@ -391,13 +391,23 @@ public Text readOptionalText() throws IOException {
391391
if (length == -1) {
392392
return null;
393393
}
394-
return new Text(readBytesReference(length));
394+
byte[] bytes = new byte[length];
395+
if (length > 0) {
396+
readBytes(bytes, 0, length);
397+
}
398+
var byteBuff = ByteBuffer.wrap(bytes);
399+
return new Text(byteBuff);
395400
}
396401

397402
public Text readText() throws IOException {
398-
// use StringAndBytes so we can cache the string if it's ever converted to it
403+
// use Text so we can cache the string if it's ever converted to it
399404
int length = readInt();
400-
return new Text(readBytesReference(length));
405+
byte[] bytes = new byte[length];
406+
if (length > 0) {
407+
readBytes(bytes, 0, length);
408+
}
409+
var byteBuff = ByteBuffer.wrap(bytes);
410+
return new Text(byteBuff);
401411
}
402412

403413
@Nullable

server/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
import org.elasticsearch.common.geo.GeoPoint;
2323
import org.elasticsearch.common.io.stream.Writeable.Writer;
2424
import org.elasticsearch.common.settings.SecureString;
25-
import org.elasticsearch.common.text.Text;
2625
import org.elasticsearch.common.util.ByteUtils;
2726
import org.elasticsearch.core.CharArrays;
2827
import org.elasticsearch.core.Nullable;
2928
import org.elasticsearch.core.TimeValue;
29+
import org.elasticsearch.xcontent.Text;
3030
import org.elasticsearch.xcontent.XContentType;
3131

3232
import java.io.IOException;
@@ -419,7 +419,7 @@ public void writeText(Text text) throws IOException {
419419
writeInt(spare.length());
420420
write(spare.bytes(), 0, spare.length());
421421
} else {
422-
BytesReference bytes = text.bytes();
422+
BytesReference bytes = BytesReference.fromByteBuffer(text.bytes());
423423
writeInt(bytes.length());
424424
bytes.writeTo(this);
425425
}

server/src/main/java/org/elasticsearch/search/SearchHit.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.elasticsearch.common.io.stream.StreamInput;
2121
import org.elasticsearch.common.io.stream.StreamOutput;
2222
import org.elasticsearch.common.io.stream.Writeable;
23-
import org.elasticsearch.common.text.Text;
2423
import org.elasticsearch.common.util.Maps;
2524
import org.elasticsearch.common.xcontent.ChunkedToXContent;
2625
import org.elasticsearch.common.xcontent.XContentHelper;
@@ -39,6 +38,7 @@
3938
import org.elasticsearch.search.lookup.Source;
4039
import org.elasticsearch.transport.LeakTracker;
4140
import org.elasticsearch.transport.RemoteClusterAware;
41+
import org.elasticsearch.xcontent.Text;
4242
import org.elasticsearch.xcontent.ToXContentFragment;
4343
import org.elasticsearch.xcontent.ToXContentObject;
4444
import org.elasticsearch.xcontent.XContentBuilder;

server/src/main/java/org/elasticsearch/search/SearchShardTarget.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.common.io.stream.StreamOutput;
1414
import org.elasticsearch.common.io.stream.Writeable;
15-
import org.elasticsearch.common.text.Text;
1615
import org.elasticsearch.core.Nullable;
1716
import org.elasticsearch.index.shard.ShardId;
1817
import org.elasticsearch.transport.RemoteClusterAware;
18+
import org.elasticsearch.xcontent.Text;
1919

2020
import java.io.IOException;
2121
import java.util.Objects;

server/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/DefaultHighlighter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.elasticsearch.common.CheckedSupplier;
2222
import org.elasticsearch.common.Strings;
2323
import org.elasticsearch.common.lucene.Lucene;
24-
import org.elasticsearch.common.text.Text;
2524
import org.elasticsearch.index.IndexSettings;
2625
import org.elasticsearch.index.mapper.IdFieldMapper;
2726
import org.elasticsearch.index.mapper.MappedFieldType;
@@ -34,6 +33,7 @@
3433
import org.elasticsearch.lucene.search.uhighlight.Snippet;
3534
import org.elasticsearch.search.fetch.FetchContext;
3635
import org.elasticsearch.search.fetch.FetchSubPhase;
36+
import org.elasticsearch.xcontent.Text;
3737

3838
import java.io.IOException;
3939
import java.text.BreakIterator;

server/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/FastVectorHighlighter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.apache.lucene.search.vectorhighlight.SingleFragListBuilder;
2424
import org.elasticsearch.common.settings.Setting;
2525
import org.elasticsearch.common.settings.Settings;
26-
import org.elasticsearch.common.text.Text;
2726
import org.elasticsearch.common.util.CollectionUtils;
2827
import org.elasticsearch.index.mapper.MappedFieldType;
2928
import org.elasticsearch.index.mapper.TextSearchInfo;
@@ -33,6 +32,7 @@
3332
import org.elasticsearch.search.fetch.subphase.highlight.SearchHighlightContext.Field;
3433
import org.elasticsearch.search.fetch.subphase.highlight.SearchHighlightContext.FieldOptions;
3534
import org.elasticsearch.search.lookup.Source;
35+
import org.elasticsearch.xcontent.Text;
3636

3737
import java.io.IOException;
3838
import java.text.BreakIterator;

server/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/HighlightField.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.common.io.stream.StreamOutput;
1414
import org.elasticsearch.common.io.stream.Writeable;
15-
import org.elasticsearch.common.text.Text;
15+
import org.elasticsearch.xcontent.Text;
1616
import org.elasticsearch.xcontent.ToXContentFragment;
1717
import org.elasticsearch.xcontent.XContentBuilder;
1818

server/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/PlainHighlighter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
import org.apache.lucene.search.highlight.TextFragment;
2525
import org.apache.lucene.util.BytesRefHash;
2626
import org.elasticsearch.common.lucene.Lucene;
27-
import org.elasticsearch.common.text.Text;
2827
import org.elasticsearch.index.IndexSettings;
2928
import org.elasticsearch.index.mapper.MappedFieldType;
3029
import org.elasticsearch.lucene.search.uhighlight.QueryMaxAnalyzedOffset;
3130
import org.elasticsearch.search.fetch.FetchContext;
3231
import org.elasticsearch.search.fetch.FetchSubPhase;
32+
import org.elasticsearch.xcontent.Text;
3333

3434
import java.io.IOException;
3535
import java.util.ArrayList;

server/src/main/java/org/elasticsearch/search/searchafter/SearchAfterBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
import org.elasticsearch.common.io.stream.StreamInput;
2020
import org.elasticsearch.common.io.stream.StreamOutput;
2121
import org.elasticsearch.common.io.stream.Writeable;
22-
import org.elasticsearch.common.text.Text;
2322
import org.elasticsearch.core.Nullable;
2423
import org.elasticsearch.index.fielddata.IndexFieldData;
2524
import org.elasticsearch.search.DocValueFormat;
2625
import org.elasticsearch.search.sort.SortAndFormats;
2726
import org.elasticsearch.xcontent.ParseField;
27+
import org.elasticsearch.xcontent.Text;
2828
import org.elasticsearch.xcontent.ToXContentObject;
2929
import org.elasticsearch.xcontent.XContentBuilder;
3030
import org.elasticsearch.xcontent.XContentParser;

server/src/main/java/org/elasticsearch/search/suggest/Suggest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
import org.elasticsearch.common.io.stream.StreamInput;
1515
import org.elasticsearch.common.io.stream.StreamOutput;
1616
import org.elasticsearch.common.io.stream.Writeable;
17-
import org.elasticsearch.common.text.Text;
1817
import org.elasticsearch.rest.action.search.RestSearchAction;
1918
import org.elasticsearch.search.aggregations.Aggregation;
2019
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry;
2120
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option;
2221
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
2322
import org.elasticsearch.xcontent.ParseField;
23+
import org.elasticsearch.xcontent.Text;
2424
import org.elasticsearch.xcontent.ToXContentFragment;
2525
import org.elasticsearch.xcontent.XContentBuilder;
2626

server/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggester.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import org.apache.lucene.search.suggest.document.TopSuggestDocs;
2020
import org.apache.lucene.search.suggest.document.TopSuggestDocsCollector;
2121
import org.apache.lucene.util.CharsRefBuilder;
22-
import org.elasticsearch.common.text.Text;
2322
import org.elasticsearch.index.mapper.CompletionFieldMapper;
2423
import org.elasticsearch.search.suggest.Suggest;
2524
import org.elasticsearch.search.suggest.Suggester;
25+
import org.elasticsearch.xcontent.Text;
2626

2727
import java.io.IOException;
2828
import java.util.Collections;

server/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
import org.elasticsearch.common.io.stream.StreamInput;
1515
import org.elasticsearch.common.io.stream.StreamOutput;
1616
import org.elasticsearch.common.lucene.Lucene;
17-
import org.elasticsearch.common.text.Text;
1817
import org.elasticsearch.common.util.Maps;
1918
import org.elasticsearch.common.util.set.Sets;
2019
import org.elasticsearch.search.SearchHit;
2120
import org.elasticsearch.search.suggest.Suggest;
2221
import org.elasticsearch.xcontent.ParseField;
22+
import org.elasticsearch.xcontent.Text;
2323
import org.elasticsearch.xcontent.XContentBuilder;
2424

2525
import java.io.IOException;

server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggester.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.apache.lucene.util.BytesRefBuilder;
2020
import org.apache.lucene.util.CharsRefBuilder;
2121
import org.elasticsearch.common.lucene.Lucene;
22-
import org.elasticsearch.common.text.Text;
2322
import org.elasticsearch.index.query.AbstractQueryBuilder;
2423
import org.elasticsearch.index.query.ParsedQuery;
2524
import org.elasticsearch.index.query.QueryBuilder;
@@ -31,6 +30,7 @@
3130
import org.elasticsearch.search.suggest.Suggester;
3231
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
3332
import org.elasticsearch.search.suggest.phrase.NoisyChannelSpellChecker.Result;
33+
import org.elasticsearch.xcontent.Text;
3434
import org.elasticsearch.xcontent.XContentFactory;
3535
import org.elasticsearch.xcontent.XContentParser;
3636

server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.common.io.stream.StreamOutput;
14-
import org.elasticsearch.common.text.Text;
1514
import org.elasticsearch.search.suggest.Suggest;
1615
import org.elasticsearch.search.suggest.Suggest.Suggestion;
16+
import org.elasticsearch.xcontent.Text;
1717

1818
import java.io.IOException;
1919
import java.util.Objects;

0 commit comments

Comments
 (0)