Java API: XContentFactory creation of XContentBuilder to always be "safe", closes #1291.

This commit is contained in:
Shay Banon 2011-08-31 21:10:50 +03:00
parent d1d3340aa2
commit bc1dd108d1
34 changed files with 114 additions and 183 deletions

View File

@ -60,10 +60,11 @@ public class BulkRequest implements ActionRequest {
* (for example, if no id is provided, one will be generated, or usage of the create flag). * (for example, if no id is provided, one will be generated, or usage of the create flag).
*/ */
public BulkRequest add(IndexRequest request) { public BulkRequest add(IndexRequest request) {
// if the source is from a builder, we need to copy it over before adding the next one, which can come from a builder as well... request.beforeLocalFork();
if (request.sourceFromBuilder()) { return internalAdd(request);
request.beforeLocalFork(); }
}
private BulkRequest internalAdd(IndexRequest request) {
requests.add(request); requests.add(request);
return this; return this;
} }
@ -155,19 +156,21 @@ public class BulkRequest implements ActionRequest {
break; break;
} }
// order is important, we set parent after routing, so routing will be set to parent if not set explicitly // order is important, we set parent after routing, so routing will be set to parent if not set explicitly
// we use internalAdd so we don't fork here, this allows us not to copy over the big byte array to small chunks
// of index request. All index requests are still unsafe if applicable.
if ("index".equals(action)) { if ("index".equals(action)) {
if (opType == null) { if (opType == null) {
add(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType) internalAdd(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType)
.source(data, from, nextMarker - from, contentUnsafe) .source(data, from, nextMarker - from, contentUnsafe)
.percolate(percolate)); .percolate(percolate));
} else { } else {
add(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType) internalAdd(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType)
.create("create".equals(opType)) .create("create".equals(opType))
.source(data, from, nextMarker - from, contentUnsafe) .source(data, from, nextMarker - from, contentUnsafe)
.percolate(percolate)); .percolate(percolate));
} }
} else if ("create".equals(action)) { } else if ("create".equals(action)) {
add(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType) internalAdd(new IndexRequest(index, type, id).routing(routing).parent(parent).timestamp(timestamp).version(version).versionType(versionType)
.create(true) .create(true)
.source(data, from, nextMarker - from, contentUnsafe) .source(data, from, nextMarker - from, contentUnsafe)
.percolate(percolate)); .percolate(percolate));

View File

@ -171,7 +171,7 @@ public class CountRequest extends BroadcastOperationRequest {
*/ */
@Required public CountRequest query(QueryBuilder queryBuilder) { @Required public CountRequest query(QueryBuilder queryBuilder) {
BytesStream bos = queryBuilder.buildAsUnsafeBytes(); BytesStream bos = queryBuilder.buildAsUnsafeBytes();
this.querySource = bos.unsafeByteArray(); this.querySource = bos.underlyingBytes();
this.querySourceOffset = 0; this.querySourceOffset = 0;
this.querySourceLength = bos.size(); this.querySourceLength = bos.size();
this.querySourceUnsafe = true; this.querySourceUnsafe = true;
@ -193,10 +193,10 @@ public class CountRequest extends BroadcastOperationRequest {
@Required public CountRequest query(XContentBuilder builder) { @Required public CountRequest query(XContentBuilder builder) {
try { try {
this.querySource = builder.unsafeBytes(); this.querySource = builder.underlyingBytes();
this.querySourceOffset = 0; this.querySourceOffset = 0;
this.querySourceLength = builder.unsafeBytesLength(); this.querySourceLength = builder.underlyingBytesLength();
this.querySourceUnsafe = true; this.querySourceUnsafe = false;
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);

View File

@ -123,7 +123,7 @@ public class DeleteByQueryRequest extends IndicesReplicationOperationRequest {
*/ */
@Required public DeleteByQueryRequest query(QueryBuilder queryBuilder) { @Required public DeleteByQueryRequest query(QueryBuilder queryBuilder) {
BytesStream bos = queryBuilder.buildAsUnsafeBytes(); BytesStream bos = queryBuilder.buildAsUnsafeBytes();
this.querySource = bos.unsafeByteArray(); this.querySource = bos.underlyingBytes();
this.querySourceOffset = 0; this.querySourceOffset = 0;
this.querySourceLength = bos.size(); this.querySourceLength = bos.size();
this.querySourceUnsafe = true; this.querySourceUnsafe = true;
@ -158,10 +158,10 @@ public class DeleteByQueryRequest extends IndicesReplicationOperationRequest {
@Required public DeleteByQueryRequest query(XContentBuilder builder) { @Required public DeleteByQueryRequest query(XContentBuilder builder) {
try { try {
this.querySource = builder.unsafeBytes(); this.querySource = builder.underlyingBytes();
this.querySourceOffset = 0; this.querySourceOffset = 0;
this.querySourceLength = builder.unsafeBytesLength(); this.querySourceLength = builder.underlyingBytesLength();
this.querySourceUnsafe = true; this.querySourceUnsafe = false;
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);

View File

@ -124,7 +124,6 @@ public class IndexRequest extends ShardReplicationOperationRequest {
private int sourceOffset; private int sourceOffset;
private int sourceLength; private int sourceLength;
private boolean sourceUnsafe; private boolean sourceUnsafe;
private boolean sourceFromBuilder;
private OpType opType = OpType.INDEX; private OpType opType = OpType.INDEX;
@ -174,14 +173,10 @@ public class IndexRequest extends ShardReplicationOperationRequest {
* Before we fork on a local thread, make sure we copy over the bytes if they are unsafe * Before we fork on a local thread, make sure we copy over the bytes if they are unsafe
*/ */
@Override public void beforeLocalFork() { @Override public void beforeLocalFork() {
source(); // only fork if copy over if source is unsafe
} if (sourceUnsafe) {
source();
/** }
* Need this in case builders are used, we need to copy after adding...
*/
public boolean sourceFromBuilder() {
return sourceFromBuilder;
} }
/** /**
@ -296,7 +291,7 @@ public class IndexRequest extends ShardReplicationOperationRequest {
* The source of the document to index, recopied to a new array if it has an offset or unsafe. * The source of the document to index, recopied to a new array if it has an offset or unsafe.
*/ */
public byte[] source() { public byte[] source() {
if (sourceUnsafe || sourceOffset > 0) { if (sourceUnsafe || sourceOffset > 0 || source.length != sourceLength) {
source = Arrays.copyOfRange(source, sourceOffset, sourceOffset + sourceLength); source = Arrays.copyOfRange(source, sourceOffset, sourceOffset + sourceLength);
sourceOffset = 0; sourceOffset = 0;
sourceUnsafe = false; sourceUnsafe = false;
@ -304,18 +299,6 @@ public class IndexRequest extends ShardReplicationOperationRequest {
return source; return source;
} }
public byte[] unsafeSource() {
return this.source;
}
public int unsafeSourceOffset() {
return this.sourceOffset;
}
public int unsafeSourceLength() {
return this.sourceLength;
}
/** /**
* Index the Map as a {@link org.elasticsearch.client.Requests#INDEX_CONTENT_TYPE}. * Index the Map as a {@link org.elasticsearch.client.Requests#INDEX_CONTENT_TYPE}.
* *
@ -360,11 +343,10 @@ public class IndexRequest extends ShardReplicationOperationRequest {
*/ */
@Required public IndexRequest source(XContentBuilder sourceBuilder) { @Required public IndexRequest source(XContentBuilder sourceBuilder) {
try { try {
source = sourceBuilder.unsafeBytes(); source = sourceBuilder.underlyingBytes();
sourceOffset = 0; sourceOffset = 0;
sourceLength = sourceBuilder.unsafeBytesLength(); sourceLength = sourceBuilder.underlyingBytesLength();
sourceUnsafe = true; sourceUnsafe = false;
this.sourceFromBuilder = true;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + sourceBuilder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + sourceBuilder + "]", e);
} }

View File

@ -326,7 +326,7 @@ public class MoreLikeThisRequest implements ActionRequest {
*/ */
public MoreLikeThisRequest searchSource(SearchSourceBuilder sourceBuilder) { public MoreLikeThisRequest searchSource(SearchSourceBuilder sourceBuilder) {
BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE); BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE);
this.searchSource = bos.unsafeByteArray(); this.searchSource = bos.underlyingBytes();
this.searchSourceOffset = 0; this.searchSourceOffset = 0;
this.searchSourceLength = bos.size(); this.searchSourceLength = bos.size();
this.searchSourceUnsafe = true; this.searchSourceUnsafe = true;
@ -358,10 +358,10 @@ public class MoreLikeThisRequest implements ActionRequest {
public MoreLikeThisRequest searchSource(XContentBuilder builder) { public MoreLikeThisRequest searchSource(XContentBuilder builder) {
try { try {
this.searchSource = builder.unsafeBytes(); this.searchSource = builder.underlyingBytes();
this.searchSourceOffset = 0; this.searchSourceOffset = 0;
this.searchSourceLength = builder.unsafeBytesLength(); this.searchSourceLength = builder.underlyingBytesLength();
this.searchSourceUnsafe = true; this.searchSourceUnsafe = false;
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);

View File

@ -87,11 +87,13 @@ public class PercolateRequest extends SingleCustomOperationRequest {
* Before we fork on a local thread, make sure we copy over the bytes if they are unsafe * Before we fork on a local thread, make sure we copy over the bytes if they are unsafe
*/ */
@Override public void beforeLocalFork() { @Override public void beforeLocalFork() {
source(); if (sourceUnsafe) {
source();
}
} }
public byte[] source() { public byte[] source() {
if (sourceUnsafe || sourceOffset > 0) { if (sourceUnsafe || sourceOffset > 0 || source.length != sourceLength) {
source = Arrays.copyOfRange(source, sourceOffset, sourceOffset + sourceLength); source = Arrays.copyOfRange(source, sourceOffset, sourceOffset + sourceLength);
sourceOffset = 0; sourceOffset = 0;
sourceUnsafe = false; sourceUnsafe = false;
@ -99,15 +101,15 @@ public class PercolateRequest extends SingleCustomOperationRequest {
return source; return source;
} }
public byte[] unsafeSource() { public byte[] underlyingSource() {
return this.source; return this.source;
} }
public int unsafeSourceOffset() { public int underlyingSourceOffset() {
return this.sourceOffset; return this.sourceOffset;
} }
public int unsafeSourceLength() { public int underlyingSourceLength() {
return this.sourceLength; return this.sourceLength;
} }
@ -136,10 +138,10 @@ public class PercolateRequest extends SingleCustomOperationRequest {
@Required public PercolateRequest source(XContentBuilder sourceBuilder) { @Required public PercolateRequest source(XContentBuilder sourceBuilder) {
try { try {
source = sourceBuilder.unsafeBytes(); source = sourceBuilder.underlyingBytes();
sourceOffset = 0; sourceOffset = 0;
sourceLength = sourceBuilder.unsafeBytesLength(); sourceLength = sourceBuilder.underlyingBytesLength();
sourceUnsafe = true; sourceUnsafe = false;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + sourceBuilder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + sourceBuilder + "]", e);
} }

View File

@ -76,7 +76,7 @@ public class TransportPercolateAction extends TransportSingleCustomOperationActi
IndexService indexService = indicesService.indexServiceSafe(request.index()); IndexService indexService = indicesService.indexServiceSafe(request.index());
PercolatorService percolatorService = indexService.percolateService(); PercolatorService percolatorService = indexService.percolateService();
PercolatorExecutor.Response percolate = percolatorService.percolate(new PercolatorExecutor.SourceRequest(request.type(), request.source())); PercolatorExecutor.Response percolate = percolatorService.percolate(new PercolatorExecutor.SourceRequest(request.type(), request.underlyingSource(), request.underlyingSourceOffset(), request.underlyingSourceLength()));
return new PercolateResponse(percolate.matches()); return new PercolateResponse(percolate.matches());
} }
} }

View File

@ -257,7 +257,7 @@ public class SearchRequest implements ActionRequest {
*/ */
public SearchRequest source(SearchSourceBuilder sourceBuilder) { public SearchRequest source(SearchSourceBuilder sourceBuilder) {
BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE); BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE);
this.source = bos.unsafeByteArray(); this.source = bos.underlyingBytes();
this.sourceOffset = 0; this.sourceOffset = 0;
this.sourceLength = bos.size(); this.sourceLength = bos.size();
this.sourceUnsafe = true; this.sourceUnsafe = true;
@ -292,10 +292,10 @@ public class SearchRequest implements ActionRequest {
public SearchRequest source(XContentBuilder builder) { public SearchRequest source(XContentBuilder builder) {
try { try {
this.source = builder.unsafeBytes(); this.source = builder.underlyingBytes();
this.sourceOffset = 0; this.sourceOffset = 0;
this.sourceLength = builder.unsafeBytesLength(); this.sourceLength = builder.underlyingBytesLength();
this.sourceUnsafe = true; this.sourceUnsafe = false;
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);
@ -348,7 +348,7 @@ public class SearchRequest implements ActionRequest {
*/ */
public SearchRequest extraSource(SearchSourceBuilder sourceBuilder) { public SearchRequest extraSource(SearchSourceBuilder sourceBuilder) {
BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE); BytesStream bos = sourceBuilder.buildAsUnsafeBytes(Requests.CONTENT_TYPE);
this.extraSource = bos.unsafeByteArray(); this.extraSource = bos.underlyingBytes();
this.extraSourceOffset = 0; this.extraSourceOffset = 0;
this.extraSourceLength = bos.size(); this.extraSourceLength = bos.size();
this.extraSourceUnsafe = true; this.extraSourceUnsafe = true;
@ -367,10 +367,10 @@ public class SearchRequest implements ActionRequest {
public SearchRequest extraSource(XContentBuilder builder) { public SearchRequest extraSource(XContentBuilder builder) {
try { try {
this.extraSource = builder.unsafeBytes(); this.extraSource = builder.underlyingBytes();
this.extraSourceOffset = 0; this.extraSourceOffset = 0;
this.extraSourceLength = builder.unsafeBytesLength(); this.extraSourceLength = builder.underlyingBytesLength();
this.extraSourceUnsafe = true; this.extraSourceUnsafe = false;
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e); throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);

View File

@ -21,7 +21,7 @@ package org.elasticsearch.common.io;
public interface BytesStream { public interface BytesStream {
byte[] unsafeByteArray(); byte[] underlyingBytes();
int size(); int size();

View File

@ -25,7 +25,6 @@ import org.elasticsearch.common.io.stream.CachedStreamOutput;
public class CachedStreams { public class CachedStreams {
public static void clear() { public static void clear() {
FastByteArrayOutputStream.Cached.clear();
CachedStreamInput.clear(); CachedStreamInput.clear();
CachedStreamOutput.clear(); CachedStreamOutput.clear();
} }

View File

@ -22,7 +22,6 @@ package org.elasticsearch.common.io;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.util.Arrays; import java.util.Arrays;
/** /**
@ -32,32 +31,6 @@ import java.util.Arrays;
*/ */
public class FastByteArrayOutputStream extends OutputStream implements BytesStream { public class FastByteArrayOutputStream extends OutputStream implements BytesStream {
/**
* A thread local based cache of {@link FastByteArrayOutputStream}.
*/
public static class Cached {
private static final ThreadLocal<SoftReference<FastByteArrayOutputStream>> cache = new ThreadLocal<SoftReference<FastByteArrayOutputStream>>();
/**
* Returns the cached thread local byte stream, with its internal stream cleared.
*/
public static FastByteArrayOutputStream cached() {
SoftReference<FastByteArrayOutputStream> ref = cache.get();
FastByteArrayOutputStream fos = ref == null ? null : ref.get();
if (fos == null) {
fos = new FastByteArrayOutputStream();
cache.set(new SoftReference(fos));
}
fos.reset();
return fos;
}
public static void clear() {
cache.remove();
}
}
/** /**
* The buffer where data is stored. * The buffer where data is stored.
*/ */
@ -70,10 +43,13 @@ public class FastByteArrayOutputStream extends OutputStream implements BytesStre
/** /**
* Creates a new byte array output stream. The buffer capacity is * Creates a new byte array output stream. The buffer capacity is
* initially 32 bytes, though its size increases if necessary. * initially 1024 bytes, though its size increases if necessary.
*
* ES: We use 1024 bytes since we mainly use this to build json/smile
* content in memory, and rarely does the 32 byte default in ByteArrayOutputStream fits...
*/ */
public FastByteArrayOutputStream() { public FastByteArrayOutputStream() {
this(32); this(1024);
} }
/** /**
@ -167,7 +143,7 @@ public class FastByteArrayOutputStream extends OutputStream implements BytesStre
* Returns the underlying byte array. Note, use {@link #size()} in order to know * Returns the underlying byte array. Note, use {@link #size()} in order to know
* the length of it. * the length of it.
*/ */
public byte[] unsafeByteArray() { public byte[] underlyingBytes() {
return buf; return buf;
} }

View File

@ -34,7 +34,7 @@ public final class Serializers {
ThrowableObjectOutputStream oos = new ThrowableObjectOutputStream(os); ThrowableObjectOutputStream oos = new ThrowableObjectOutputStream(os);
oos.writeObject(t); oos.writeObject(t);
oos.close(); oos.close();
return os.unsafeByteArray(); return os.underlyingBytes();
} }
public static Throwable throwableFromBytes(byte[] bytes) throws IOException, ClassNotFoundException { public static Throwable throwableFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
@ -62,7 +62,7 @@ public final class Serializers {
CompactObjectOutputStream oos = new CompactObjectOutputStream(os); CompactObjectOutputStream oos = new CompactObjectOutputStream(os);
oos.writeObject(obj); oos.writeObject(obj);
oos.close(); oos.close();
return os.unsafeByteArray(); return os.underlyingBytes();
} }
public static Object objectFromBytes(byte[] bytes) throws IOException, ClassNotFoundException { public static Object objectFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {

View File

@ -100,7 +100,7 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream {
* Returns the underlying byte array. Note, use {@link #size()} in order to know * Returns the underlying byte array. Note, use {@link #size()} in order to know
* the length of it. * the length of it.
*/ */
public byte[] unsafeByteArray() { public byte[] underlyingBytes() {
return buf; return buf;
} }

View File

@ -122,7 +122,7 @@ public class CachedStreamOutput {
} }
public static void pushEntry(Entry entry) { public static void pushEntry(Entry entry) {
if (entry.bytes().unsafeByteArray().length > BYTES_LIMIT) { if (entry.bytes().underlyingBytes().length > BYTES_LIMIT) {
return; return;
} }
Queue<Entry> ref = cache.get(); Queue<Entry> ref = cache.get();

View File

@ -65,13 +65,6 @@ public final class XContentBuilder {
XContentBuilder.globalFieldCaseConversion = globalFieldCaseConversion; XContentBuilder.globalFieldCaseConversion = globalFieldCaseConversion;
} }
/**
* Constructs a new cached builder over a cached (thread local) {@link FastByteArrayOutputStream}.
*/
public static XContentBuilder cachedBuilder(XContent xContent) throws IOException {
return new XContentBuilder(xContent, FastByteArrayOutputStream.Cached.cached());
}
/** /**
* Constructs a new builder using a fresh {@link FastByteArrayOutputStream}. * Constructs a new builder using a fresh {@link FastByteArrayOutputStream}.
*/ */
@ -945,22 +938,22 @@ public final class XContentBuilder {
/** /**
* Returns the unsafe bytes (thread local bound). Make sure to use it with * Returns the unsafe bytes (thread local bound). Make sure to use it with
* {@link #unsafeBytesLength()}. * {@link #underlyingBytesLength()}.
* *
* <p>Only applicable when the builder is constructed with {@link FastByteArrayOutputStream}. * <p>Only applicable when the builder is constructed with {@link FastByteArrayOutputStream}.
*/ */
public byte[] unsafeBytes() throws IOException { public byte[] underlyingBytes() throws IOException {
close(); close();
return ((BytesStream) bos).unsafeByteArray(); return ((BytesStream) bos).underlyingBytes();
} }
/** /**
* Returns the unsafe bytes length (thread local bound). Make sure to use it with * Returns the unsafe bytes length (thread local bound). Make sure to use it with
* {@link #unsafeBytes()}. * {@link #underlyingBytes()}.
* *
* <p>Only applicable when the builder is constructed with {@link FastByteArrayOutputStream}. * <p>Only applicable when the builder is constructed with {@link FastByteArrayOutputStream}.
*/ */
public int unsafeBytesLength() throws IOException { public int underlyingBytesLength() throws IOException {
close(); close();
return ((BytesStream) bos).size(); return ((BytesStream) bos).size();
} }
@ -968,7 +961,7 @@ public final class XContentBuilder {
/** /**
* Returns the actual stream used. * Returns the actual stream used.
*/ */
public BytesStream unsafeStream() throws IOException { public BytesStream underlyingStream() throws IOException {
close(); close();
return (BytesStream) bos; return (BytesStream) bos;
} }
@ -990,6 +983,6 @@ public final class XContentBuilder {
*/ */
public String string() throws IOException { public String string() throws IOException {
close(); close();
return Unicode.fromBytes(unsafeBytes(), 0, unsafeBytesLength()); return Unicode.fromBytes(underlyingBytes(), 0, underlyingBytesLength());
} }
} }

View File

@ -49,9 +49,6 @@ public class XContentFactory {
/** /**
* Returns a content builder using JSON format ({@link org.elasticsearch.common.xcontent.XContentType#JSON}. * Returns a content builder using JSON format ({@link org.elasticsearch.common.xcontent.XContentType#JSON}.
*
* <p>Note, this should be passed directly to an API, if its going to be used around, make sure you use
* {@link #safeJsonBuilder()}.
*/ */
public static XContentBuilder jsonBuilder() throws IOException { public static XContentBuilder jsonBuilder() throws IOException {
return contentBuilder(XContentType.JSON); return contentBuilder(XContentType.JSON);
@ -64,19 +61,8 @@ public class XContentFactory {
return new XContentBuilder(JsonXContent.jsonXContent, os); return new XContentBuilder(JsonXContent.jsonXContent, os);
} }
/**
* Returns a content builder using JSON format ({@link org.elasticsearch.common.xcontent.XContentType#JSON}
* that can be used outside of the scope of passing it directly to an API call.
*/
public static XContentBuilder safeJsonBuilder() throws IOException {
return unCachedContentBuilder(XContentType.JSON);
}
/** /**
* Returns a content builder using SMILE format ({@link org.elasticsearch.common.xcontent.XContentType#SMILE}. * Returns a content builder using SMILE format ({@link org.elasticsearch.common.xcontent.XContentType#SMILE}.
*
* <p>Note, this should be passed directly to an API, if its going to be used around, make sure you use
* {@link #safeSmileBuilder()}.
*/ */
public static XContentBuilder smileBuilder() throws IOException { public static XContentBuilder smileBuilder() throws IOException {
return contentBuilder(XContentType.SMILE); return contentBuilder(XContentType.SMILE);
@ -89,14 +75,6 @@ public class XContentFactory {
return new XContentBuilder(SmileXContent.smileXContent, os); return new XContentBuilder(SmileXContent.smileXContent, os);
} }
/**
* Returns a content builder using SMILE format ({@link org.elasticsearch.common.xcontent.XContentType#SMILE}
* that can be used outside of the scope of passing it directly to an API call.
*/
public static XContentBuilder safeSmileBuilder() throws IOException {
return unCachedContentBuilder(XContentType.SMILE);
}
/** /**
* Constructs a xcontent builder that will output the result into the provided output stream. * Constructs a xcontent builder that will output the result into the provided output stream.
*/ */
@ -121,18 +99,6 @@ public class XContentFactory {
throw new ElasticSearchIllegalArgumentException("No matching content type for " + type); throw new ElasticSearchIllegalArgumentException("No matching content type for " + type);
} }
/**
* Returns a binary content builder for the provided content type.
*/
public static XContentBuilder unCachedContentBuilder(XContentType type) throws IOException {
if (type == XContentType.JSON) {
return JsonXContent.unCachedContentBuilder();
} else if (type == XContentType.SMILE) {
return SmileXContent.unCachedContentBuilder();
}
throw new ElasticSearchIllegalArgumentException("No matching content type for " + type);
}
/** /**
* Returns the {@link org.elasticsearch.common.xcontent.XContent} for the provided content type. * Returns the {@link org.elasticsearch.common.xcontent.XContent} for the provided content type.
*/ */

View File

@ -24,9 +24,17 @@ import org.elasticsearch.common.jackson.JsonEncoding;
import org.elasticsearch.common.jackson.JsonFactory; import org.elasticsearch.common.jackson.JsonFactory;
import org.elasticsearch.common.jackson.JsonGenerator; import org.elasticsearch.common.jackson.JsonGenerator;
import org.elasticsearch.common.jackson.JsonParser; import org.elasticsearch.common.jackson.JsonParser;
import org.elasticsearch.common.xcontent.*; import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentGenerator;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.*; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
/** /**
* A JSON based content implementation using Jackson. * A JSON based content implementation using Jackson.
@ -36,10 +44,6 @@ import java.io.*;
public class JsonXContent implements XContent { public class JsonXContent implements XContent {
public static XContentBuilder contentBuilder() throws IOException { public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.cachedBuilder(jsonXContent);
}
public static XContentBuilder unCachedContentBuilder() throws IOException {
return XContentBuilder.builder(jsonXContent); return XContentBuilder.builder(jsonXContent);
} }

View File

@ -23,10 +23,18 @@ import org.elasticsearch.common.io.FastStringReader;
import org.elasticsearch.common.jackson.JsonEncoding; import org.elasticsearch.common.jackson.JsonEncoding;
import org.elasticsearch.common.jackson.smile.SmileFactory; import org.elasticsearch.common.jackson.smile.SmileFactory;
import org.elasticsearch.common.jackson.smile.SmileGenerator; import org.elasticsearch.common.jackson.smile.SmileGenerator;
import org.elasticsearch.common.xcontent.*; import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentGenerator;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContentParser; import org.elasticsearch.common.xcontent.json.JsonXContentParser;
import java.io.*; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
/** /**
* A JSON based content implementation using Jackson. * A JSON based content implementation using Jackson.
@ -36,10 +44,6 @@ import java.io.*;
public class SmileXContent implements XContent { public class SmileXContent implements XContent {
public static XContentBuilder contentBuilder() throws IOException { public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.cachedBuilder(smileXContent);
}
public static XContentBuilder unCachedContentBuilder() throws IOException {
return XContentBuilder.builder(smileXContent); return XContentBuilder.builder(smileXContent);
} }

View File

@ -163,7 +163,7 @@ public abstract class BlobStoreGateway extends SharedStorageGateway {
MetaData.Builder.toXContent(metaData, builder, ToXContent.EMPTY_PARAMS); MetaData.Builder.toXContent(metaData, builder, ToXContent.EMPTY_PARAMS);
builder.endObject(); builder.endObject();
builder.close(); builder.close();
metaDataBlobContainer.writeBlob(newMetaData, new ByteArrayInputStream(out.unsafeByteArray(), 0, out.size()), out.size()); metaDataBlobContainer.writeBlob(newMetaData, new ByteArrayInputStream(out.underlyingBytes(), 0, out.size()), out.size());
} catch (IOException e) { } catch (IOException e) {
throw new GatewayException("Failed to write metadata [" + newMetaData + "]", e); throw new GatewayException("Failed to write metadata [" + newMetaData + "]", e);
} }

View File

@ -104,7 +104,7 @@ public class NettyHttpChannel implements HttpChannel {
XContentBuilder builder = ((XContentRestResponse) response).builder(); XContentBuilder builder = ((XContentRestResponse) response).builder();
if (builder.payload() instanceof CachedStreamOutput.Entry) { if (builder.payload() instanceof CachedStreamOutput.Entry) {
releaseContentListener = new NettyTransport.CacheFutureListener((CachedStreamOutput.Entry) builder.payload()); releaseContentListener = new NettyTransport.CacheFutureListener((CachedStreamOutput.Entry) builder.payload());
buf = ChannelBuffers.wrappedBuffer(builder.unsafeBytes(), 0, builder.unsafeBytesLength()); buf = ChannelBuffers.wrappedBuffer(builder.underlyingBytes(), 0, builder.underlyingBytesLength());
} else if (response.contentThreadSafe()) { } else if (response.contentThreadSafe()) {
buf = ChannelBuffers.wrappedBuffer(response.content(), 0, response.contentLength()); buf = ChannelBuffers.wrappedBuffer(response.content(), 0, response.contentLength());
} else { } else {

View File

@ -462,7 +462,7 @@ public abstract class BlobStoreIndexShardGateway extends AbstractIndexShardCompo
if (bos.size() < 4) { if (bos.size() < 4) {
return; return;
} }
BytesStreamInput si = new BytesStreamInput(bos.unsafeByteArray(), 0, bos.size()); BytesStreamInput si = new BytesStreamInput(bos.underlyingBytes(), 0, bos.size());
int position; int position;
while (true) { while (true) {
try { try {
@ -497,7 +497,7 @@ public abstract class BlobStoreIndexShardGateway extends AbstractIndexShardCompo
int leftOver = bos.size() - position; int leftOver = bos.size() - position;
if (leftOver > 0) { if (leftOver > 0) {
newBos.write(bos.unsafeByteArray(), position, leftOver); newBos.write(bos.underlyingBytes(), position, leftOver);
} }
bos = newBos; bos = newBos;

View File

@ -198,8 +198,8 @@ public class PercolatorExecutor extends AbstractIndexComponent {
try { try {
XContentBuilder builder = XContentFactory.smileBuilder() XContentBuilder builder = XContentFactory.smileBuilder()
.startObject().field("query", queryBuilder).endObject(); .startObject().field("query", queryBuilder).endObject();
BytesStream unsafeBytes = builder.unsafeStream(); BytesStream unsafeBytes = builder.underlyingStream();
addQuery(name, unsafeBytes.unsafeByteArray(), 0, unsafeBytes.size()); addQuery(name, unsafeBytes.underlyingBytes(), 0, unsafeBytes.size());
} catch (IOException e) { } catch (IOException e) {
throw new ElasticSearchException("Failed to add query [" + name + "]", e); throw new ElasticSearchException("Failed to add query [" + name + "]", e);
} }

View File

@ -33,7 +33,7 @@ public abstract class BaseQueryBuilder implements QueryBuilder {
@Override public String toString() { @Override public String toString() {
try { try {
XContentBuilder builder = XContentFactory.safeJsonBuilder(); XContentBuilder builder = XContentFactory.jsonBuilder();
builder.prettyPrint(); builder.prettyPrint();
toXContent(builder, EMPTY_PARAMS); toXContent(builder, EMPTY_PARAMS);
return builder.string(); return builder.string();
@ -50,7 +50,7 @@ public abstract class BaseQueryBuilder implements QueryBuilder {
try { try {
XContentBuilder builder = XContentFactory.contentBuilder(contentType); XContentBuilder builder = XContentFactory.contentBuilder(contentType);
toXContent(builder, EMPTY_PARAMS); toXContent(builder, EMPTY_PARAMS);
return builder.unsafeStream(); return builder.underlyingStream();
} catch (Exception e) { } catch (Exception e) {
throw new QueryBuilderException("Failed to build query", e); throw new QueryBuilderException("Failed to build query", e);
} }

View File

@ -158,7 +158,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
XContentParser parser = null; XContentParser parser = null;
try { try {
BytesStream unsafeBytes = queryBuilder.buildAsUnsafeBytes(); BytesStream unsafeBytes = queryBuilder.buildAsUnsafeBytes();
parser = XContentFactory.xContent(unsafeBytes.unsafeByteArray(), 0, unsafeBytes.size()).createParser(unsafeBytes.unsafeByteArray(), 0, unsafeBytes.size()); parser = XContentFactory.xContent(unsafeBytes.underlyingBytes(), 0, unsafeBytes.size()).createParser(unsafeBytes.underlyingBytes(), 0, unsafeBytes.size());
return parse(cache.get(), parser); return parse(cache.get(), parser);
} catch (QueryParsingException e) { } catch (QueryParsingException e) {
throw e; throw e;

View File

@ -731,13 +731,13 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
// ignore if closed.... // ignore if closed....
return; return;
} }
logger.warn("check index [failure]\n{}", new String(os.unsafeByteArray(), 0, os.size())); logger.warn("check index [failure]\n{}", new String(os.underlyingBytes(), 0, os.size()));
if (throwException) { if (throwException) {
throw new IndexShardException(shardId, "index check failure"); throw new IndexShardException(shardId, "index check failure");
} }
} else { } else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("check index [success]\n{}", new String(os.unsafeByteArray(), 0, os.size())); logger.debug("check index [success]\n{}", new String(os.underlyingBytes(), 0, os.size()));
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -218,14 +218,14 @@ public class FsTranslog extends AbstractIndexShardComponent implements Translog
out.seek(0); out.seek(0);
out.writeInt(size - 4); out.writeInt(size - 4);
Location location = current.add(out.unsafeByteArray(), 0, size); Location location = current.add(out.underlyingBytes(), 0, size);
if (syncOnEachOperation) { if (syncOnEachOperation) {
current.sync(); current.sync();
} }
FsTranslogFile trans = this.trans; FsTranslogFile trans = this.trans;
if (trans != null) { if (trans != null) {
try { try {
location = trans.add(out.unsafeByteArray(), 0, size); location = trans.add(out.underlyingBytes(), 0, size);
} catch (ClosedChannelException e) { } catch (ClosedChannelException e) {
// ignore // ignore
} }

View File

@ -70,11 +70,11 @@ public class XContentRestResponse extends AbstractRestResponse {
} }
@Override public byte[] content() throws IOException { @Override public byte[] content() throws IOException {
return builder.unsafeBytes(); return builder.underlyingBytes();
} }
@Override public int contentLength() throws IOException { @Override public int contentLength() throws IOException {
return builder.unsafeBytesLength(); return builder.underlyingBytesLength();
} }
@Override public RestStatus status() { @Override public RestStatus status() {

View File

@ -384,7 +384,7 @@ public class SearchSourceBuilder implements ToXContent {
try { try {
XContentBuilder builder = XContentFactory.contentBuilder(contentType); XContentBuilder builder = XContentFactory.contentBuilder(contentType);
toXContent(builder, ToXContent.EMPTY_PARAMS); toXContent(builder, ToXContent.EMPTY_PARAMS);
return builder.unsafeStream(); return builder.underlyingStream();
} catch (Exception e) { } catch (Exception e) {
throw new SearchSourceBuilderException("Failed to build search source", e); throw new SearchSourceBuilderException("Failed to build search source", e);
} }

View File

@ -455,7 +455,7 @@ public class NettyTransport extends AbstractLifecycleComponent<Transport> implem
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry(); CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
TransportStreams.buildRequest(cachedEntry, requestId, action, message, options); TransportStreams.buildRequest(cachedEntry, requestId, action, message, options);
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(cachedEntry.bytes().unsafeByteArray(), 0, cachedEntry.bytes().size()); ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(cachedEntry.bytes().underlyingBytes(), 0, cachedEntry.bytes().size());
ChannelFuture future = targetChannel.write(buffer); ChannelFuture future = targetChannel.write(buffer);
future.addListener(new CacheFutureListener(cachedEntry)); future.addListener(new CacheFutureListener(cachedEntry));
// We handle close connection exception in the #exceptionCaught method, which is the main reason we want to add this future // We handle close connection exception in the #exceptionCaught method, which is the main reason we want to add this future

View File

@ -72,7 +72,7 @@ public class NettyTransportChannel implements TransportChannel {
} }
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry(); CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
TransportStreams.buildResponse(cachedEntry, requestId, message, options); TransportStreams.buildResponse(cachedEntry, requestId, message, options);
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(cachedEntry.bytes().unsafeByteArray(), 0, cachedEntry.bytes().size()); ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(cachedEntry.bytes().underlyingBytes(), 0, cachedEntry.bytes().size());
ChannelFuture future = channel.write(buffer); ChannelFuture future = channel.write(buffer);
future.addListener(new NettyTransport.CacheFutureListener(cachedEntry)); future.addListener(new NettyTransport.CacheFutureListener(cachedEntry));
} }
@ -95,7 +95,7 @@ public class NettyTransportChannel implements TransportChannel {
too.writeObject(tx); too.writeObject(tx);
too.close(); too.close();
} }
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(stream.unsafeByteArray(), 0, stream.size()); ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(stream.underlyingBytes(), 0, stream.size());
buffer.setInt(0, buffer.writerIndex() - 4); // update real size. buffer.setInt(0, buffer.writerIndex() - 4); // update real size.
ChannelFuture future = channel.write(buffer); ChannelFuture future = channel.write(buffer);
future.addListener(new NettyTransport.CacheFutureListener(cachedEntry)); future.addListener(new NettyTransport.CacheFutureListener(cachedEntry));

View File

@ -117,7 +117,7 @@ public class TransportStreams {
message.writeTo(stream); message.writeTo(stream);
stream.flush(); stream.flush();
} }
TransportStreams.writeHeader(cachedEntry.bytes().unsafeByteArray(), cachedEntry.bytes().size(), requestId, status); TransportStreams.writeHeader(cachedEntry.bytes().underlyingBytes(), cachedEntry.bytes().size(), requestId, status);
} }
public static void buildResponse(CachedStreamOutput.Entry cachedEntry, final long requestId, Streamable message, TransportResponseOptions options) throws IOException { public static void buildResponse(CachedStreamOutput.Entry cachedEntry, final long requestId, Streamable message, TransportResponseOptions options) throws IOException {
@ -136,6 +136,6 @@ public class TransportStreams {
message.writeTo(stream); message.writeTo(stream);
stream.flush(); stream.flush();
} }
TransportStreams.writeHeader(cachedEntry.bytes().unsafeByteArray(), cachedEntry.bytes().size(), requestId, status); TransportStreams.writeHeader(cachedEntry.bytes().underlyingBytes(), cachedEntry.bytes().size(), requestId, status);
} }
} }

View File

@ -47,7 +47,7 @@ public class BuilderRawFieldTests {
XContentBuilder builder = XContentFactory.contentBuilder(type); XContentBuilder builder = XContentFactory.contentBuilder(type);
builder.startObject(); builder.startObject();
builder.field("field1", "value1"); builder.field("field1", "value1");
builder.rawField("_source", XContentFactory.unCachedContentBuilder(type).startObject().field("s_field", "s_value").endObject().copiedBytes()); builder.rawField("_source", XContentFactory.contentBuilder(type).startObject().field("s_field", "s_value").endObject().copiedBytes());
builder.field("field2", "value2"); builder.field("field2", "value2");
builder.endObject(); builder.endObject();

View File

@ -199,7 +199,9 @@ public class DocumentActionsTests extends AbstractNodesTests {
assertThat(getResult.index(), equalTo(getConcreteIndexName())); assertThat(getResult.index(), equalTo(getConcreteIndexName()));
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test").string())); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test").string()));
getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test2").string())); String ste1 = getResult.sourceAsString();
String ste2 = source("2", "test2").string();
assertThat("cycle #" + i, ste1, equalTo(ste2));
assertThat(getResult.index(), equalTo(getConcreteIndexName())); assertThat(getResult.index(), equalTo(getConcreteIndexName()));
} }

View File

@ -117,10 +117,10 @@ public class MemcachedRestChannel implements RestChannel {
XContentBuilder builder = ((XContentRestResponse) response).builder(); XContentBuilder builder = ((XContentRestResponse) response).builder();
if (builder.payload() instanceof CachedStreamOutput.Entry) { if (builder.payload() instanceof CachedStreamOutput.Entry) {
releaseContentListener = new NettyTransport.CacheFutureListener((CachedStreamOutput.Entry) builder.payload()); releaseContentListener = new NettyTransport.CacheFutureListener((CachedStreamOutput.Entry) builder.payload());
ChannelBuffer buf = ChannelBuffers.wrappedBuffer(builder.unsafeBytes(), 0, builder.unsafeBytesLength()); ChannelBuffer buf = ChannelBuffers.wrappedBuffer(builder.underlyingBytes(), 0, builder.underlyingBytesLength());
writeBuffer = ChannelBuffers.wrappedBuffer(writeBuffer, buf); writeBuffer = ChannelBuffers.wrappedBuffer(writeBuffer, buf);
} else if (response.contentThreadSafe()) { } else if (response.contentThreadSafe()) {
ChannelBuffer buf = ChannelBuffers.wrappedBuffer(builder.unsafeBytes(), 0, builder.unsafeBytesLength()); ChannelBuffer buf = ChannelBuffers.wrappedBuffer(builder.underlyingBytes(), 0, builder.underlyingBytesLength());
writeBuffer = ChannelBuffers.wrappedBuffer(writeBuffer, buf); writeBuffer = ChannelBuffers.wrappedBuffer(writeBuffer, buf);
} else { } else {
writeBuffer.writeBytes(response.content(), 0, response.contentLength()); writeBuffer.writeBytes(response.content(), 0, response.contentLength());