by default, index metadata to be stored in smile format and store binary format mapping and alias filter to improve the cost it takes to persist them
This commit is contained in:
parent
01d8305af3
commit
68bb5d1434
|
@ -139,6 +139,11 @@ public class AliasMetaData {
|
||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder filter(CompressedString filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder filter(String filter) {
|
public Builder filter(String filter) {
|
||||||
if (!Strings.hasLength(filter)) {
|
if (!Strings.hasLength(filter)) {
|
||||||
this.filter = null;
|
this.filter = null;
|
||||||
|
@ -201,12 +206,18 @@ public class AliasMetaData {
|
||||||
public static void toXContent(AliasMetaData aliasMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
public static void toXContent(AliasMetaData aliasMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||||
builder.startObject(aliasMetaData.alias(), XContentBuilder.FieldCaseConversion.NONE);
|
builder.startObject(aliasMetaData.alias(), XContentBuilder.FieldCaseConversion.NONE);
|
||||||
|
|
||||||
|
boolean binary = params.paramAsBoolean("binary", false);
|
||||||
|
|
||||||
if (aliasMetaData.filter() != null) {
|
if (aliasMetaData.filter() != null) {
|
||||||
byte[] data = aliasMetaData.filter().uncompressed();
|
if (binary) {
|
||||||
XContentParser parser = XContentFactory.xContent(data).createParser(data);
|
builder.field("filter", aliasMetaData.filter.compressed());
|
||||||
Map<String, Object> filter = parser.mapOrdered();
|
} else {
|
||||||
parser.close();
|
byte[] data = aliasMetaData.filter().uncompressed();
|
||||||
builder.field("filter", filter);
|
XContentParser parser = XContentFactory.xContent(data).createParser(data);
|
||||||
|
Map<String, Object> filter = parser.mapOrdered();
|
||||||
|
parser.close();
|
||||||
|
builder.field("filter", filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (aliasMetaData.indexRouting() != null) {
|
if (aliasMetaData.indexRouting() != null) {
|
||||||
builder.field("index_routing", aliasMetaData.indexRouting());
|
builder.field("index_routing", aliasMetaData.indexRouting());
|
||||||
|
@ -235,6 +246,10 @@ public class AliasMetaData {
|
||||||
Map<String, Object> filter = parser.mapOrdered();
|
Map<String, Object> filter = parser.mapOrdered();
|
||||||
builder.filter(filter);
|
builder.filter(filter);
|
||||||
}
|
}
|
||||||
|
} else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
|
||||||
|
if ("filter".equals(currentFieldName)) {
|
||||||
|
builder.filter(new CompressedString(parser.binaryValue()));
|
||||||
|
}
|
||||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||||
if ("routing".equals(currentFieldName)) {
|
if ("routing".equals(currentFieldName)) {
|
||||||
builder.routing(parser.text());
|
builder.routing(parser.text());
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodeFilters;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.Preconditions;
|
import org.elasticsearch.common.Preconditions;
|
||||||
import org.elasticsearch.common.collect.MapBuilder;
|
import org.elasticsearch.common.collect.MapBuilder;
|
||||||
|
import org.elasticsearch.common.compress.CompressedString;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.regex.Regex;
|
import org.elasticsearch.common.regex.Regex;
|
||||||
|
@ -346,7 +347,7 @@ public class IndexMetaData {
|
||||||
public Builder putMapping(String type, String source) throws IOException {
|
public Builder putMapping(String type, String source) throws IOException {
|
||||||
XContentParser parser = XContentFactory.xContent(source).createParser(source);
|
XContentParser parser = XContentFactory.xContent(source).createParser(source);
|
||||||
try {
|
try {
|
||||||
putMapping(new MappingMetaData(type, parser.map()));
|
putMapping(new MappingMetaData(type, parser.mapOrdered()));
|
||||||
} finally {
|
} finally {
|
||||||
parser.close();
|
parser.close();
|
||||||
}
|
}
|
||||||
|
@ -413,6 +414,8 @@ public class IndexMetaData {
|
||||||
builder.field("version", indexMetaData.version());
|
builder.field("version", indexMetaData.version());
|
||||||
builder.field("state", indexMetaData.state().toString().toLowerCase());
|
builder.field("state", indexMetaData.state().toString().toLowerCase());
|
||||||
|
|
||||||
|
boolean binary = params.paramAsBoolean("binary", false);
|
||||||
|
|
||||||
builder.startObject("settings");
|
builder.startObject("settings");
|
||||||
for (Map.Entry<String, String> entry : indexMetaData.settings().getAsMap().entrySet()) {
|
for (Map.Entry<String, String> entry : indexMetaData.settings().getAsMap().entrySet()) {
|
||||||
builder.field(entry.getKey(), entry.getValue());
|
builder.field(entry.getKey(), entry.getValue());
|
||||||
|
@ -421,11 +424,15 @@ public class IndexMetaData {
|
||||||
|
|
||||||
builder.startArray("mappings");
|
builder.startArray("mappings");
|
||||||
for (Map.Entry<String, MappingMetaData> entry : indexMetaData.mappings().entrySet()) {
|
for (Map.Entry<String, MappingMetaData> entry : indexMetaData.mappings().entrySet()) {
|
||||||
byte[] data = entry.getValue().source().uncompressed();
|
if (binary) {
|
||||||
XContentParser parser = XContentFactory.xContent(data).createParser(data);
|
builder.value(entry.getValue().source().compressed());
|
||||||
Map<String, Object> mapping = parser.mapOrdered();
|
} else {
|
||||||
parser.close();
|
byte[] data = entry.getValue().source().uncompressed();
|
||||||
builder.map(mapping);
|
XContentParser parser = XContentFactory.xContent(data).createParser(data);
|
||||||
|
Map<String, Object> mapping = parser.mapOrdered();
|
||||||
|
parser.close();
|
||||||
|
builder.map(mapping);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
builder.endArray();
|
builder.endArray();
|
||||||
|
|
||||||
|
@ -462,10 +469,14 @@ public class IndexMetaData {
|
||||||
builder.settings(settingsBuilder.build());
|
builder.settings(settingsBuilder.build());
|
||||||
} else if ("mappings".equals(currentFieldName)) {
|
} else if ("mappings".equals(currentFieldName)) {
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
Map<String, Object> mapping = parser.mapOrdered();
|
if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
|
||||||
if (mapping.size() == 1) {
|
builder.putMapping(new MappingMetaData(new CompressedString(parser.binaryValue())));
|
||||||
String mappingType = mapping.keySet().iterator().next();
|
} else {
|
||||||
builder.putMapping(new MappingMetaData(mappingType, mapping));
|
Map<String, Object> mapping = parser.mapOrdered();
|
||||||
|
if (mapping.size() == 1) {
|
||||||
|
String mappingType = mapping.keySet().iterator().next();
|
||||||
|
builder.putMapping(new MappingMetaData(mappingType, mapping));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ("aliases".equals(currentFieldName)) {
|
} else if ("aliases".equals(currentFieldName)) {
|
||||||
|
@ -473,6 +484,20 @@ public class IndexMetaData {
|
||||||
builder.putAlias(AliasMetaData.Builder.fromXContent(parser));
|
builder.putAlias(AliasMetaData.Builder.fromXContent(parser));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
|
if ("mappings".equals(currentFieldName)) {
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
|
||||||
|
builder.putMapping(new MappingMetaData(new CompressedString(parser.binaryValue())));
|
||||||
|
} else {
|
||||||
|
Map<String, Object> mapping = parser.mapOrdered();
|
||||||
|
if (mapping.size() == 1) {
|
||||||
|
String mappingType = mapping.keySet().iterator().next();
|
||||||
|
builder.putMapping(new MappingMetaData(mappingType, mapping));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (token.isValue()) {
|
} else if (token.isValue()) {
|
||||||
if ("state".equals(currentFieldName)) {
|
if ("state".equals(currentFieldName)) {
|
||||||
builder.state(State.fromString(parser.text()));
|
builder.state(State.fromString(parser.text()));
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.cluster.metadata;
|
package org.elasticsearch.cluster.metadata;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticSearchIllegalStateException;
|
||||||
import org.elasticsearch.action.TimestampParsingException;
|
import org.elasticsearch.action.TimestampParsingException;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
|
@ -250,9 +251,9 @@ public class MappingMetaData {
|
||||||
|
|
||||||
private final CompressedString source;
|
private final CompressedString source;
|
||||||
|
|
||||||
private final Id id;
|
private Id id;
|
||||||
private final Routing routing;
|
private Routing routing;
|
||||||
private final Timestamp timestamp;
|
private Timestamp timestamp;
|
||||||
|
|
||||||
public MappingMetaData(DocumentMapper docMapper) {
|
public MappingMetaData(DocumentMapper docMapper) {
|
||||||
this.type = docMapper.type();
|
this.type = docMapper.type();
|
||||||
|
@ -262,6 +263,20 @@ public class MappingMetaData {
|
||||||
this.timestamp = new Timestamp(docMapper.timestampFieldMapper().enabled(), docMapper.timestampFieldMapper().path(), docMapper.timestampFieldMapper().dateTimeFormatter().format());
|
this.timestamp = new Timestamp(docMapper.timestampFieldMapper().enabled(), docMapper.timestampFieldMapper().path(), docMapper.timestampFieldMapper().dateTimeFormatter().format());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MappingMetaData(CompressedString mapping) throws IOException {
|
||||||
|
this.source = mapping;
|
||||||
|
Map<String, Object> mappingMap = XContentHelper.createParser(mapping.compressed(), 0, mapping.compressed().length).mapOrderedAndClose();
|
||||||
|
if (mappingMap.size() != 1) {
|
||||||
|
throw new ElasticSearchIllegalStateException("Can't derive type from mapping, no root type: " + mapping.string());
|
||||||
|
}
|
||||||
|
this.type = mappingMap.keySet().iterator().next();
|
||||||
|
initMappers((Map<String, Object>) mappingMap.get(this.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingMetaData(Map<String, Object> mapping) throws IOException {
|
||||||
|
this(mapping.keySet().iterator().next(), mapping);
|
||||||
|
}
|
||||||
|
|
||||||
public MappingMetaData(String type, Map<String, Object> mapping) throws IOException {
|
public MappingMetaData(String type, Map<String, Object> mapping) throws IOException {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.source = new CompressedString(XContentFactory.jsonBuilder().map(mapping).string());
|
this.source = new CompressedString(XContentFactory.jsonBuilder().map(mapping).string());
|
||||||
|
@ -269,6 +284,10 @@ public class MappingMetaData {
|
||||||
if (mapping.size() == 1 && mapping.containsKey(type)) {
|
if (mapping.size() == 1 && mapping.containsKey(type)) {
|
||||||
withoutType = (Map<String, Object>) mapping.get(type);
|
withoutType = (Map<String, Object>) mapping.get(type);
|
||||||
}
|
}
|
||||||
|
initMappers(withoutType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMappers(Map<String, Object> withoutType) {
|
||||||
if (withoutType.containsKey("_id")) {
|
if (withoutType.containsKey("_id")) {
|
||||||
String path = null;
|
String path = null;
|
||||||
Map<String, Object> routingNode = (Map<String, Object>) withoutType.get("_id");
|
Map<String, Object> routingNode = (Map<String, Object>) withoutType.get("_id");
|
||||||
|
|
|
@ -40,6 +40,10 @@ public class CompressedString implements Streamable {
|
||||||
CompressedString() {
|
CompressedString() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompressedString(byte[] compressed) {
|
||||||
|
this.bytes = compressed;
|
||||||
|
}
|
||||||
|
|
||||||
public CompressedString(String str) throws IOException {
|
public CompressedString(String str) throws IOException {
|
||||||
UnicodeUtil.UTF8Result result = Unicode.unsafeFromStringAsUtf8(str);
|
UnicodeUtil.UTF8Result result = Unicode.unsafeFromStringAsUtf8(str);
|
||||||
this.bytes = LZFEncoder.encode(result.result, result.length);
|
this.bytes = LZFEncoder.encode(result.result, result.length);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.gateway.local.state.meta;
|
package org.elasticsearch.gateway.local.state.meta;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||||
|
@ -42,6 +43,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,13 +55,24 @@ public class LocalGatewayMetaState extends AbstractComponent implements ClusterS
|
||||||
|
|
||||||
private volatile MetaData currentMetaData;
|
private volatile MetaData currentMetaData;
|
||||||
|
|
||||||
|
private final XContentType format;
|
||||||
|
private final ToXContent.Params formatParams;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public LocalGatewayMetaState(Settings settings, NodeEnvironment nodeEnv, TransportNodesListGatewayMetaState nodesListGatewayMetaState) throws Exception {
|
public LocalGatewayMetaState(Settings settings, NodeEnvironment nodeEnv, TransportNodesListGatewayMetaState nodesListGatewayMetaState) throws Exception {
|
||||||
super(settings);
|
super(settings);
|
||||||
this.nodeEnv = nodeEnv;
|
this.nodeEnv = nodeEnv;
|
||||||
|
this.format = XContentType.fromRestContentType(settings.get("format", "smile"));
|
||||||
nodesListGatewayMetaState.init(this);
|
nodesListGatewayMetaState.init(this);
|
||||||
|
|
||||||
|
if (this.format == XContentType.SMILE) {
|
||||||
|
Map<String, String> params = Maps.newHashMap();
|
||||||
|
params.put("binary", "true");
|
||||||
|
formatParams = new ToXContent.MapParams(params);
|
||||||
|
} else {
|
||||||
|
formatParams = ToXContent.EMPTY_PARAMS;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pre019Upgrade();
|
pre019Upgrade();
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
|
@ -150,9 +163,9 @@ public class LocalGatewayMetaState extends AbstractComponent implements ClusterS
|
||||||
logger.trace("[{}] writing state, reason [{}]", indexMetaData.index(), reason);
|
logger.trace("[{}] writing state, reason [{}]", indexMetaData.index(), reason);
|
||||||
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
|
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
|
||||||
try {
|
try {
|
||||||
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, cachedEntry.cachedBytes());
|
XContentBuilder builder = XContentFactory.contentBuilder(format, cachedEntry.cachedBytes());
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
IndexMetaData.Builder.toXContent(indexMetaData, builder, ToXContent.EMPTY_PARAMS);
|
IndexMetaData.Builder.toXContent(indexMetaData, builder, formatParams);
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
builder.flush();
|
builder.flush();
|
||||||
|
|
||||||
|
@ -201,9 +214,9 @@ public class LocalGatewayMetaState extends AbstractComponent implements ClusterS
|
||||||
|
|
||||||
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
|
CachedStreamOutput.Entry cachedEntry = CachedStreamOutput.popEntry();
|
||||||
try {
|
try {
|
||||||
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, cachedEntry.cachedBytes());
|
XContentBuilder builder = XContentFactory.contentBuilder(format, cachedEntry.cachedBytes());
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
MetaData.Builder.toXContent(globalMetaData, builder, ToXContent.EMPTY_PARAMS);
|
MetaData.Builder.toXContent(globalMetaData, builder, formatParams);
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
builder.flush();
|
builder.flush();
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.gateway.Gateway;
|
import org.elasticsearch.gateway.Gateway;
|
||||||
|
import org.elasticsearch.index.query.FilterBuilders;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
import org.elasticsearch.node.Node;
|
import org.elasticsearch.node.Node;
|
||||||
import org.elasticsearch.node.internal.InternalNode;
|
import org.elasticsearch.node.internal.InternalNode;
|
||||||
|
@ -295,6 +296,7 @@ public class SimpleRecoveryLocalGatewayTests extends AbstractNodesTests {
|
||||||
.startObject("field2").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
|
.startObject("field2").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
|
||||||
.endObject().endObject().endObject())
|
.endObject().endObject().endObject())
|
||||||
.execute().actionGet();
|
.execute().actionGet();
|
||||||
|
node2.client().admin().indices().prepareAliases().addAlias("test", "test_alias", FilterBuilders.termFilter("field", "value")).execute().actionGet();
|
||||||
|
|
||||||
|
|
||||||
logger.info("--> closing the second node");
|
logger.info("--> closing the second node");
|
||||||
|
@ -318,6 +320,8 @@ public class SimpleRecoveryLocalGatewayTests extends AbstractNodesTests {
|
||||||
ClusterState state = node1.client().admin().cluster().prepareState().execute().actionGet().state();
|
ClusterState state = node1.client().admin().cluster().prepareState().execute().actionGet().state();
|
||||||
assertThat(state.metaData().index("test").mapping("type2"), notNullValue());
|
assertThat(state.metaData().index("test").mapping("type2"), notNullValue());
|
||||||
assertThat(state.metaData().templates().get("template_1").template(), equalTo("te*"));
|
assertThat(state.metaData().templates().get("template_1").template(), equalTo("te*"));
|
||||||
|
assertThat(state.metaData().index("test").aliases().get("test_alias"), notNullValue());
|
||||||
|
assertThat(state.metaData().index("test").aliases().get("test_alias").filter(), notNullValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue