mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-25 06:16:40 +00:00
improve allocation of shards based on existing work location, wait with index creation on other nodes, so listing their respective existing location will work
This commit is contained in:
parent
6722e05418
commit
fe50a6f64e
@ -63,13 +63,15 @@ public class ElasticSearchException extends RuntimeException {
|
|||||||
public String getDetailedMessage() {
|
public String getDetailedMessage() {
|
||||||
if (getCause() != null) {
|
if (getCause() != null) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (super.getMessage() != null) {
|
sb.append(toString()).append("; ");
|
||||||
sb.append(super.getMessage()).append("; ");
|
if (getCause() instanceof ElasticSearchException) {
|
||||||
|
sb.append(((ElasticSearchException) getCause()).getDetailedMessage());
|
||||||
|
} else {
|
||||||
|
sb.append(getCause());
|
||||||
}
|
}
|
||||||
sb.append("nested exception is ").append(getCause());
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
} else {
|
} else {
|
||||||
return super.getMessage();
|
return super.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,8 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
|
|
||||||
private final NodeMappingCreatedAction nodeMappingCreatedAction;
|
private final NodeMappingCreatedAction nodeMappingCreatedAction;
|
||||||
|
|
||||||
|
private final Object mutex = new Object();
|
||||||
|
|
||||||
@Inject public MetaDataService(Settings settings, Environment environment, ClusterService clusterService, IndicesService indicesService, ShardsRoutingStrategy shardsRoutingStrategy,
|
@Inject public MetaDataService(Settings settings, Environment environment, ClusterService clusterService, IndicesService indicesService, ShardsRoutingStrategy shardsRoutingStrategy,
|
||||||
NodeIndexCreatedAction nodeIndexCreatedAction, NodeIndexDeletedAction nodeIndexDeletedAction,
|
NodeIndexCreatedAction nodeIndexCreatedAction, NodeIndexDeletedAction nodeIndexDeletedAction,
|
||||||
NodeMappingCreatedAction nodeMappingCreatedAction) {
|
NodeMappingCreatedAction nodeMappingCreatedAction) {
|
||||||
@ -102,94 +104,46 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
|
|
||||||
// TODO should find nicer solution than sync here, since we block for timeout (same for other ops)
|
// TODO should find nicer solution than sync here, since we block for timeout (same for other ops)
|
||||||
|
|
||||||
public synchronized IndicesAliasesResult indicesAliases(final List<AliasAction> aliasActions) {
|
public IndicesAliasesResult indicesAliases(final List<AliasAction> aliasActions) {
|
||||||
ClusterState clusterState = clusterService.state();
|
synchronized (mutex) {
|
||||||
|
ClusterState clusterState = clusterService.state();
|
||||||
|
|
||||||
for (AliasAction aliasAction : aliasActions) {
|
for (AliasAction aliasAction : aliasActions) {
|
||||||
if (!clusterState.metaData().hasIndex(aliasAction.index())) {
|
if (!clusterState.metaData().hasIndex(aliasAction.index())) {
|
||||||
throw new IndexMissingException(new Index(aliasAction.index()));
|
throw new IndexMissingException(new Index(aliasAction.index()));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clusterService.submitStateUpdateTask("index-aliases", new ClusterStateUpdateTask() {
|
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
|
||||||
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
|
||||||
for (AliasAction aliasAction : aliasActions) {
|
|
||||||
IndexMetaData indexMetaData = builder.get(aliasAction.index());
|
|
||||||
if (indexMetaData == null) {
|
|
||||||
throw new IndexMissingException(new Index(aliasAction.index()));
|
|
||||||
}
|
|
||||||
Set<String> indexAliases = newHashSet(indexMetaData.settings().getAsArray("index.aliases"));
|
|
||||||
if (aliasAction.actionType() == AliasAction.Type.ADD) {
|
|
||||||
indexAliases.add(aliasAction.alias());
|
|
||||||
} else if (aliasAction.actionType() == AliasAction.Type.REMOVE) {
|
|
||||||
indexAliases.remove(aliasAction.alias());
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings settings = settingsBuilder().put(indexMetaData.settings())
|
|
||||||
.putArray("index.aliases", indexAliases.toArray(new String[indexAliases.size()]))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
builder.put(newIndexMetaDataBuilder(indexMetaData).settings(settings));
|
|
||||||
}
|
}
|
||||||
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return new IndicesAliasesResult();
|
clusterService.submitStateUpdateTask("index-aliases", new ClusterStateUpdateTask() {
|
||||||
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
||||||
|
for (AliasAction aliasAction : aliasActions) {
|
||||||
|
IndexMetaData indexMetaData = builder.get(aliasAction.index());
|
||||||
|
if (indexMetaData == null) {
|
||||||
|
throw new IndexMissingException(new Index(aliasAction.index()));
|
||||||
|
}
|
||||||
|
Set<String> indexAliases = newHashSet(indexMetaData.settings().getAsArray("index.aliases"));
|
||||||
|
if (aliasAction.actionType() == AliasAction.Type.ADD) {
|
||||||
|
indexAliases.add(aliasAction.alias());
|
||||||
|
} else if (aliasAction.actionType() == AliasAction.Type.REMOVE) {
|
||||||
|
indexAliases.remove(aliasAction.alias());
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings settings = settingsBuilder().put(indexMetaData.settings())
|
||||||
|
.putArray("index.aliases", indexAliases.toArray(new String[indexAliases.size()]))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
builder.put(newIndexMetaDataBuilder(indexMetaData).settings(settings));
|
||||||
|
}
|
||||||
|
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new IndicesAliasesResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized CreateIndexResult createIndex(final String cause, final String index, final Settings indexSettings, Map<String, String> mappings, TimeValue timeout) throws IndexAlreadyExistsException {
|
public CreateIndexResult createIndex(final String cause, final String index, final Settings indexSettings, Map<String, String> mappings, TimeValue timeout) throws IndexAlreadyExistsException {
|
||||||
ClusterState clusterState = clusterService.state();
|
|
||||||
|
|
||||||
if (clusterState.routingTable().hasIndex(index)) {
|
|
||||||
throw new IndexAlreadyExistsException(new Index(index));
|
|
||||||
}
|
|
||||||
if (clusterState.metaData().hasIndex(index)) {
|
|
||||||
throw new IndexAlreadyExistsException(new Index(index));
|
|
||||||
}
|
|
||||||
if (index.contains(" ")) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must not contain whitespace");
|
|
||||||
}
|
|
||||||
if (index.contains(",")) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must not contain ',");
|
|
||||||
}
|
|
||||||
if (index.contains("#")) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must not contain '#");
|
|
||||||
}
|
|
||||||
if (index.charAt(0) == '_') {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must not start with '_'");
|
|
||||||
}
|
|
||||||
if (!index.toLowerCase().equals(index)) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must be lowercase");
|
|
||||||
}
|
|
||||||
if (!Strings.validFileName(index)) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "must not contain the following characters " + Strings.INVALID_FILENAME_CHARS);
|
|
||||||
}
|
|
||||||
if (clusterState.metaData().aliases().contains(index)) {
|
|
||||||
throw new InvalidIndexNameException(new Index(index), index, "an alias with the same name already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to the mappings files that exists within the config/mappings location
|
|
||||||
if (mappings == null) {
|
|
||||||
mappings = Maps.newHashMap();
|
|
||||||
} else {
|
|
||||||
mappings = Maps.newHashMap(mappings);
|
|
||||||
}
|
|
||||||
File mappingsDir = new File(environment.configFile(), "mappings");
|
|
||||||
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
|
||||||
File defaultMappingsDir = new File(mappingsDir, "_default");
|
|
||||||
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
|
||||||
addMappings(mappings, defaultMappingsDir);
|
|
||||||
}
|
|
||||||
File indexMappingsDir = new File(mappingsDir, index);
|
|
||||||
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
|
||||||
addMappings(mappings, indexMappingsDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Map<String, String> fMappings = mappings;
|
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size());
|
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size());
|
||||||
NodeIndexCreatedAction.Listener nodeCreatedListener = new NodeIndexCreatedAction.Listener() {
|
NodeIndexCreatedAction.Listener nodeCreatedListener = new NodeIndexCreatedAction.Listener() {
|
||||||
@Override public void onNodeIndexCreated(String mIndex, String nodeId) {
|
@Override public void onNodeIndexCreated(String mIndex, String nodeId) {
|
||||||
@ -198,31 +152,83 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
nodeIndexCreatedAction.add(nodeCreatedListener);
|
synchronized (mutex) {
|
||||||
clusterService.submitStateUpdateTask("create-index [" + index + "], cause [" + cause + "]", new ClusterStateUpdateTask() {
|
ClusterState clusterState = clusterService.state();
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
|
||||||
ImmutableSettings.Builder indexSettingsBuilder = settingsBuilder().put(indexSettings);
|
|
||||||
if (indexSettings.get(SETTING_NUMBER_OF_SHARDS) == null) {
|
|
||||||
indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 5));
|
|
||||||
}
|
|
||||||
if (indexSettings.get(SETTING_NUMBER_OF_REPLICAS) == null) {
|
|
||||||
indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 1));
|
|
||||||
}
|
|
||||||
Settings actualIndexSettings = indexSettingsBuilder.build();
|
|
||||||
|
|
||||||
IndexMetaData.Builder indexMetaData = newIndexMetaDataBuilder(index).settings(actualIndexSettings);
|
if (clusterState.routingTable().hasIndex(index)) {
|
||||||
for (Map.Entry<String, String> entry : fMappings.entrySet()) {
|
throw new IndexAlreadyExistsException(new Index(index));
|
||||||
indexMetaData.putMapping(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
MetaData newMetaData = newMetaDataBuilder()
|
|
||||||
.metaData(currentState.metaData())
|
|
||||||
.put(indexMetaData)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
logger.info("[{}] creating index, cause [{}], shards [{}]/[{}], mappings {}", index, cause, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), fMappings.keySet());
|
|
||||||
return newClusterStateBuilder().state(currentState).metaData(newMetaData).build();
|
|
||||||
}
|
}
|
||||||
});
|
if (clusterState.metaData().hasIndex(index)) {
|
||||||
|
throw new IndexAlreadyExistsException(new Index(index));
|
||||||
|
}
|
||||||
|
if (index.contains(" ")) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must not contain whitespace");
|
||||||
|
}
|
||||||
|
if (index.contains(",")) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must not contain ',");
|
||||||
|
}
|
||||||
|
if (index.contains("#")) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must not contain '#");
|
||||||
|
}
|
||||||
|
if (index.charAt(0) == '_') {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must not start with '_'");
|
||||||
|
}
|
||||||
|
if (!index.toLowerCase().equals(index)) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must be lowercase");
|
||||||
|
}
|
||||||
|
if (!Strings.validFileName(index)) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "must not contain the following characters " + Strings.INVALID_FILENAME_CHARS);
|
||||||
|
}
|
||||||
|
if (clusterState.metaData().aliases().contains(index)) {
|
||||||
|
throw new InvalidIndexNameException(new Index(index), index, "an alias with the same name already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to the mappings files that exists within the config/mappings location
|
||||||
|
if (mappings == null) {
|
||||||
|
mappings = Maps.newHashMap();
|
||||||
|
} else {
|
||||||
|
mappings = Maps.newHashMap(mappings);
|
||||||
|
}
|
||||||
|
File mappingsDir = new File(environment.configFile(), "mappings");
|
||||||
|
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
||||||
|
File defaultMappingsDir = new File(mappingsDir, "_default");
|
||||||
|
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
||||||
|
addMappings(mappings, defaultMappingsDir);
|
||||||
|
}
|
||||||
|
File indexMappingsDir = new File(mappingsDir, index);
|
||||||
|
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
|
||||||
|
addMappings(mappings, indexMappingsDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> fMappings = mappings;
|
||||||
|
|
||||||
|
nodeIndexCreatedAction.add(nodeCreatedListener);
|
||||||
|
clusterService.submitStateUpdateTask("create-index [" + index + "], cause [" + cause + "]", new ClusterStateUpdateTask() {
|
||||||
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
ImmutableSettings.Builder indexSettingsBuilder = settingsBuilder().put(indexSettings);
|
||||||
|
if (indexSettings.get(SETTING_NUMBER_OF_SHARDS) == null) {
|
||||||
|
indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 5));
|
||||||
|
}
|
||||||
|
if (indexSettings.get(SETTING_NUMBER_OF_REPLICAS) == null) {
|
||||||
|
indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 1));
|
||||||
|
}
|
||||||
|
Settings actualIndexSettings = indexSettingsBuilder.build();
|
||||||
|
|
||||||
|
IndexMetaData.Builder indexMetaData = newIndexMetaDataBuilder(index).settings(actualIndexSettings);
|
||||||
|
for (Map.Entry<String, String> entry : fMappings.entrySet()) {
|
||||||
|
indexMetaData.putMapping(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
MetaData newMetaData = newMetaDataBuilder()
|
||||||
|
.metaData(currentState.metaData())
|
||||||
|
.put(indexMetaData)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
logger.info("[{}] creating index, cause [{}], shards [{}]/[{}], mappings {}", index, cause, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), fMappings.keySet());
|
||||||
|
return newClusterStateBuilder().state(currentState).metaData(newMetaData).build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
boolean acknowledged;
|
boolean acknowledged;
|
||||||
try {
|
try {
|
||||||
@ -279,16 +285,8 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized DeleteIndexResult deleteIndex(final String index, TimeValue timeout) throws IndexMissingException {
|
public DeleteIndexResult deleteIndex(final String index, TimeValue timeout) throws IndexMissingException {
|
||||||
ClusterState clusterState = clusterService.state();
|
ClusterState clusterState = clusterService.state();
|
||||||
|
|
||||||
RoutingTable routingTable = clusterState.routingTable();
|
|
||||||
if (!routingTable.hasIndex(index)) {
|
|
||||||
throw new IndexMissingException(new Index(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("[{}] deleting index", index);
|
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(clusterState.nodes().size());
|
final CountDownLatch latch = new CountDownLatch(clusterState.nodes().size());
|
||||||
NodeIndexDeletedAction.Listener listener = new NodeIndexDeletedAction.Listener() {
|
NodeIndexDeletedAction.Listener listener = new NodeIndexDeletedAction.Listener() {
|
||||||
@Override public void onNodeIndexDeleted(String fIndex, String nodeId) {
|
@Override public void onNodeIndexDeleted(String fIndex, String nodeId) {
|
||||||
@ -298,24 +296,35 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
nodeIndexDeletedAction.add(listener);
|
nodeIndexDeletedAction.add(listener);
|
||||||
clusterService.submitStateUpdateTask("delete-index [" + index + "]", new ClusterStateUpdateTask() {
|
synchronized (mutex) {
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
|
||||||
RoutingTable.Builder routingTableBuilder = new RoutingTable.Builder();
|
|
||||||
for (IndexRoutingTable indexRoutingTable : currentState.routingTable().indicesRouting().values()) {
|
|
||||||
if (!indexRoutingTable.index().equals(index)) {
|
|
||||||
routingTableBuilder.add(indexRoutingTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MetaData newMetaData = newMetaDataBuilder()
|
|
||||||
.metaData(currentState.metaData())
|
|
||||||
.remove(index)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
RoutingTable newRoutingTable = shardsRoutingStrategy.reroute(
|
RoutingTable routingTable = clusterState.routingTable();
|
||||||
newClusterStateBuilder().state(currentState).routingTable(routingTableBuilder).metaData(newMetaData).build());
|
if (!routingTable.hasIndex(index)) {
|
||||||
return newClusterStateBuilder().state(currentState).routingTable(newRoutingTable).metaData(newMetaData).build();
|
throw new IndexMissingException(new Index(index));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
logger.info("[{}] deleting index", index);
|
||||||
|
|
||||||
|
clusterService.submitStateUpdateTask("delete-index [" + index + "]", new ClusterStateUpdateTask() {
|
||||||
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
RoutingTable.Builder routingTableBuilder = new RoutingTable.Builder();
|
||||||
|
for (IndexRoutingTable indexRoutingTable : currentState.routingTable().indicesRouting().values()) {
|
||||||
|
if (!indexRoutingTable.index().equals(index)) {
|
||||||
|
routingTableBuilder.add(indexRoutingTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MetaData newMetaData = newMetaDataBuilder()
|
||||||
|
.metaData(currentState.metaData())
|
||||||
|
.remove(index)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
RoutingTable newRoutingTable = shardsRoutingStrategy.reroute(
|
||||||
|
newClusterStateBuilder().state(currentState).routingTable(routingTableBuilder).metaData(newMetaData).build());
|
||||||
|
return newClusterStateBuilder().state(currentState).routingTable(newRoutingTable).metaData(newMetaData).build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
boolean acknowledged;
|
boolean acknowledged;
|
||||||
try {
|
try {
|
||||||
acknowledged = latch.await(timeout.millis(), TimeUnit.MILLISECONDS);
|
acknowledged = latch.await(timeout.millis(), TimeUnit.MILLISECONDS);
|
||||||
@ -327,102 +336,40 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
return new DeleteIndexResult(acknowledged);
|
return new DeleteIndexResult(acknowledged);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateMapping(final String index, final String type, final String mappingSource) {
|
public void updateMapping(final String index, final String type, final String mappingSource) {
|
||||||
MapperService mapperService = indicesService.indexServiceSafe(index).mapperService();
|
synchronized (mutex) {
|
||||||
|
MapperService mapperService = indicesService.indexServiceSafe(index).mapperService();
|
||||||
|
|
||||||
DocumentMapper existingMapper = mapperService.documentMapper(type);
|
DocumentMapper existingMapper = mapperService.documentMapper(type);
|
||||||
// parse the updated one
|
// parse the updated one
|
||||||
DocumentMapper updatedMapper = mapperService.parse(type, mappingSource);
|
DocumentMapper updatedMapper = mapperService.parse(type, mappingSource);
|
||||||
if (existingMapper == null) {
|
if (existingMapper == null) {
|
||||||
existingMapper = updatedMapper;
|
existingMapper = updatedMapper;
|
||||||
} else {
|
} else {
|
||||||
// merge from the updated into the existing, ignore conflicts (we know we have them, we just want the new ones)
|
// merge from the updated into the existing, ignore conflicts (we know we have them, we just want the new ones)
|
||||||
existingMapper.merge(updatedMapper, mergeFlags().simulate(false));
|
existingMapper.merge(updatedMapper, mergeFlags().simulate(false));
|
||||||
}
|
|
||||||
// build the updated mapping source
|
|
||||||
final String updatedMappingSource = existingMapper.buildSource();
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("[{}] update mapping [{}] (dynamic) with source [{}]", index, type, updatedMappingSource);
|
|
||||||
} else if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("[{}] update mapping [{}] (dynamic)", index, type);
|
|
||||||
}
|
|
||||||
// publish the new mapping
|
|
||||||
clusterService.submitStateUpdateTask("update-mapping [" + index + "][" + type + "]", new ClusterStateUpdateTask() {
|
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
|
||||||
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
|
||||||
IndexMetaData indexMetaData = currentState.metaData().index(index);
|
|
||||||
builder.put(newIndexMetaDataBuilder(indexMetaData).putMapping(type, updatedMappingSource));
|
|
||||||
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
|
||||||
}
|
}
|
||||||
});
|
// build the updated mapping source
|
||||||
|
final String updatedMappingSource = existingMapper.buildSource();
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[{}] update mapping [{}] (dynamic) with source [{}]", index, type, updatedMappingSource);
|
||||||
|
} else if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("[{}] update mapping [{}] (dynamic)", index, type);
|
||||||
|
}
|
||||||
|
// publish the new mapping
|
||||||
|
clusterService.submitStateUpdateTask("update-mapping [" + index + "][" + type + "]", new ClusterStateUpdateTask() {
|
||||||
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
||||||
|
IndexMetaData indexMetaData = currentState.metaData().index(index);
|
||||||
|
builder.put(newIndexMetaDataBuilder(indexMetaData).putMapping(type, updatedMappingSource));
|
||||||
|
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized PutMappingResult putMapping(final String[] indices, String mappingType, final String mappingSource, boolean ignoreConflicts, TimeValue timeout) throws ElasticSearchException {
|
public PutMappingResult putMapping(final String[] indices, String mappingType, final String mappingSource, boolean ignoreConflicts, TimeValue timeout) throws ElasticSearchException {
|
||||||
ClusterState clusterState = clusterService.state();
|
ClusterState clusterState = clusterService.state();
|
||||||
if (indices.length == 0) {
|
|
||||||
throw new IndexMissingException(new Index("_all"));
|
|
||||||
}
|
|
||||||
for (String index : indices) {
|
|
||||||
if (!clusterState.metaData().hasIndex(index)) {
|
|
||||||
throw new IndexMissingException(new Index(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, DocumentMapper> newMappers = newHashMap();
|
|
||||||
Map<String, DocumentMapper> existingMappers = newHashMap();
|
|
||||||
for (String index : indices) {
|
|
||||||
IndexService indexService = indicesService.indexService(index);
|
|
||||||
if (indexService != null) {
|
|
||||||
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
|
|
||||||
DocumentMapper newMapper = indexService.mapperService().parse(mappingType, mappingSource);
|
|
||||||
newMappers.put(index, newMapper);
|
|
||||||
DocumentMapper existingMapper = indexService.mapperService().documentMapper(mappingType);
|
|
||||||
if (existingMapper != null) {
|
|
||||||
// first, simulate
|
|
||||||
DocumentMapper.MergeResult mergeResult = existingMapper.merge(newMapper, mergeFlags().simulate(true));
|
|
||||||
// if we have conflicts, and we are not supposed to ignore them, throw an exception
|
|
||||||
if (!ignoreConflicts && mergeResult.hasConflicts()) {
|
|
||||||
throw new MergeMappingException(mergeResult.conflicts());
|
|
||||||
}
|
|
||||||
existingMappers.put(index, existingMapper);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IndexMissingException(new Index(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mappingType == null) {
|
|
||||||
mappingType = newMappers.values().iterator().next().type();
|
|
||||||
} else if (!mappingType.equals(newMappers.values().iterator().next().type())) {
|
|
||||||
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
|
|
||||||
}
|
|
||||||
if (mappingType.charAt(0) == '_') {
|
|
||||||
throw new InvalidTypeNameException("Document mapping type name can't start with '_'");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Map<String, Tuple<String, String>> mappings = newHashMap();
|
|
||||||
for (Map.Entry<String, DocumentMapper> entry : newMappers.entrySet()) {
|
|
||||||
Tuple<String, String> mapping;
|
|
||||||
String index = entry.getKey();
|
|
||||||
// do the actual merge here on the master, and update the mapping source
|
|
||||||
DocumentMapper newMapper = entry.getValue();
|
|
||||||
if (existingMappers.containsKey(entry.getKey())) {
|
|
||||||
// we have an existing mapping, do the merge here (on the master), it will automatically update the mapping source
|
|
||||||
DocumentMapper existingMapper = existingMappers.get(entry.getKey());
|
|
||||||
existingMapper.merge(newMapper, mergeFlags().simulate(false));
|
|
||||||
// use the merged mapping source
|
|
||||||
mapping = new Tuple<String, String>(existingMapper.type(), existingMapper.buildSource());
|
|
||||||
} else {
|
|
||||||
mapping = new Tuple<String, String>(newMapper.type(), newMapper.buildSource());
|
|
||||||
}
|
|
||||||
mappings.put(index, mapping);
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("[{}] put_mapping [{}] with source [{}]", index, mapping.v1(), mapping.v2());
|
|
||||||
} else if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("[{}] put_mapping [{}]", index, mapping.v1());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size() * indices.length);
|
final CountDownLatch latch = new CountDownLatch(clusterService.state().nodes().size() * indices.length);
|
||||||
final Set<String> indicesSet = newHashSet(indices);
|
final Set<String> indicesSet = newHashSet(indices);
|
||||||
final String fMappingType = mappingType;
|
final String fMappingType = mappingType;
|
||||||
@ -433,22 +380,88 @@ public class MetaDataService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
nodeMappingCreatedAction.add(listener);
|
synchronized (mutex) {
|
||||||
|
if (indices.length == 0) {
|
||||||
clusterService.submitStateUpdateTask("put-mapping [" + mappingType + "]", new ClusterStateUpdateTask() {
|
throw new IndexMissingException(new Index("_all"));
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
|
||||||
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
|
||||||
for (String indexName : indices) {
|
|
||||||
IndexMetaData indexMetaData = currentState.metaData().index(indexName);
|
|
||||||
if (indexMetaData == null) {
|
|
||||||
throw new IndexMissingException(new Index(indexName));
|
|
||||||
}
|
|
||||||
Tuple<String, String> mapping = mappings.get(indexName);
|
|
||||||
builder.put(newIndexMetaDataBuilder(indexMetaData).putMapping(mapping.v1(), mapping.v2()));
|
|
||||||
}
|
|
||||||
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
|
||||||
}
|
}
|
||||||
});
|
for (String index : indices) {
|
||||||
|
if (!clusterState.metaData().hasIndex(index)) {
|
||||||
|
throw new IndexMissingException(new Index(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, DocumentMapper> newMappers = newHashMap();
|
||||||
|
Map<String, DocumentMapper> existingMappers = newHashMap();
|
||||||
|
for (String index : indices) {
|
||||||
|
IndexService indexService = indicesService.indexService(index);
|
||||||
|
if (indexService != null) {
|
||||||
|
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
|
||||||
|
DocumentMapper newMapper = indexService.mapperService().parse(mappingType, mappingSource);
|
||||||
|
newMappers.put(index, newMapper);
|
||||||
|
DocumentMapper existingMapper = indexService.mapperService().documentMapper(mappingType);
|
||||||
|
if (existingMapper != null) {
|
||||||
|
// first, simulate
|
||||||
|
DocumentMapper.MergeResult mergeResult = existingMapper.merge(newMapper, mergeFlags().simulate(true));
|
||||||
|
// if we have conflicts, and we are not supposed to ignore them, throw an exception
|
||||||
|
if (!ignoreConflicts && mergeResult.hasConflicts()) {
|
||||||
|
throw new MergeMappingException(mergeResult.conflicts());
|
||||||
|
}
|
||||||
|
existingMappers.put(index, existingMapper);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IndexMissingException(new Index(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mappingType == null) {
|
||||||
|
mappingType = newMappers.values().iterator().next().type();
|
||||||
|
} else if (!mappingType.equals(newMappers.values().iterator().next().type())) {
|
||||||
|
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
|
||||||
|
}
|
||||||
|
if (mappingType.charAt(0) == '_') {
|
||||||
|
throw new InvalidTypeNameException("Document mapping type name can't start with '_'");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, Tuple<String, String>> mappings = newHashMap();
|
||||||
|
for (Map.Entry<String, DocumentMapper> entry : newMappers.entrySet()) {
|
||||||
|
Tuple<String, String> mapping;
|
||||||
|
String index = entry.getKey();
|
||||||
|
// do the actual merge here on the master, and update the mapping source
|
||||||
|
DocumentMapper newMapper = entry.getValue();
|
||||||
|
if (existingMappers.containsKey(entry.getKey())) {
|
||||||
|
// we have an existing mapping, do the merge here (on the master), it will automatically update the mapping source
|
||||||
|
DocumentMapper existingMapper = existingMappers.get(entry.getKey());
|
||||||
|
existingMapper.merge(newMapper, mergeFlags().simulate(false));
|
||||||
|
// use the merged mapping source
|
||||||
|
mapping = new Tuple<String, String>(existingMapper.type(), existingMapper.buildSource());
|
||||||
|
} else {
|
||||||
|
mapping = new Tuple<String, String>(newMapper.type(), newMapper.buildSource());
|
||||||
|
}
|
||||||
|
mappings.put(index, mapping);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[{}] put_mapping [{}] with source [{}]", index, mapping.v1(), mapping.v2());
|
||||||
|
} else if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("[{}] put_mapping [{}]", index, mapping.v1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeMappingCreatedAction.add(listener);
|
||||||
|
|
||||||
|
clusterService.submitStateUpdateTask("put-mapping [" + mappingType + "]", new ClusterStateUpdateTask() {
|
||||||
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData());
|
||||||
|
for (String indexName : indices) {
|
||||||
|
IndexMetaData indexMetaData = currentState.metaData().index(indexName);
|
||||||
|
if (indexMetaData == null) {
|
||||||
|
throw new IndexMissingException(new Index(indexName));
|
||||||
|
}
|
||||||
|
Tuple<String, String> mapping = mappings.get(indexName);
|
||||||
|
builder.put(newIndexMetaDataBuilder(indexMetaData).putMapping(mapping.v1(), mapping.v2()));
|
||||||
|
}
|
||||||
|
return newClusterStateBuilder().state(currentState).metaData(builder).build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
boolean acknowledged;
|
boolean acknowledged;
|
||||||
try {
|
try {
|
||||||
|
@ -20,14 +20,17 @@
|
|||||||
package org.elasticsearch.cluster.routing.strategy;
|
package org.elasticsearch.cluster.routing.strategy;
|
||||||
|
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
|
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||||
import org.elasticsearch.cluster.routing.MutableShardRouting;
|
import org.elasticsearch.cluster.routing.MutableShardRouting;
|
||||||
import org.elasticsearch.cluster.routing.RoutingNode;
|
import org.elasticsearch.cluster.routing.RoutingNode;
|
||||||
import org.elasticsearch.cluster.routing.RoutingNodes;
|
import org.elasticsearch.cluster.routing.RoutingNodes;
|
||||||
import org.elasticsearch.common.blobstore.BlobMetaData;
|
import org.elasticsearch.common.blobstore.BlobMetaData;
|
||||||
import org.elasticsearch.common.collect.ImmutableMap;
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
|
import org.elasticsearch.common.collect.Sets;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.index.gateway.blobstore.BlobStoreIndexGateway;
|
import org.elasticsearch.index.gateway.blobstore.BlobStoreIndexGateway;
|
||||||
import org.elasticsearch.index.service.InternalIndexService;
|
import org.elasticsearch.index.service.InternalIndexService;
|
||||||
import org.elasticsearch.index.store.IndexStore;
|
import org.elasticsearch.index.store.IndexStore;
|
||||||
@ -36,6 +39,7 @@ import org.elasticsearch.indices.IndicesService;
|
|||||||
import org.elasticsearch.indices.store.TransportNodesListShardStoreMetaData;
|
import org.elasticsearch.indices.store.TransportNodesListShardStoreMetaData;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
@ -53,9 +57,20 @@ public class PreferUnallocatedShardUnassignedStrategy extends AbstractComponent
|
|||||||
this.transportNodesListShardStoreMetaData = transportNodesListShardStoreMetaData;
|
this.transportNodesListShardStoreMetaData = transportNodesListShardStoreMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allocateUnassigned(RoutingNodes routingNodes) {
|
public boolean allocateUnassigned(RoutingNodes routingNodes, DiscoveryNodes nodes) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
|
Set<String> nodesIds = Sets.newHashSet();
|
||||||
|
for (DiscoveryNode node : nodes) {
|
||||||
|
if (node.dataNode()) {
|
||||||
|
nodesIds.add(node.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodesIds.isEmpty()) {
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
Iterator<MutableShardRouting> unassignedIterator = routingNodes.unassigned().iterator();
|
Iterator<MutableShardRouting> unassignedIterator = routingNodes.unassigned().iterator();
|
||||||
while (unassignedIterator.hasNext()) {
|
while (unassignedIterator.hasNext()) {
|
||||||
MutableShardRouting shard = unassignedIterator.next();
|
MutableShardRouting shard = unassignedIterator.next();
|
||||||
@ -68,7 +83,25 @@ public class PreferUnallocatedShardUnassignedStrategy extends AbstractComponent
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransportNodesListShardStoreMetaData.NodesStoreFilesMetaData nodesStoreFilesMetaData = transportNodesListShardStoreMetaData.list(shard.shardId(), false).actionGet();
|
if (!shard.primary()) {
|
||||||
|
// if its a backup, only allocate it if the primary is active
|
||||||
|
MutableShardRouting primary = routingNodes.findPrimaryForBackup(shard);
|
||||||
|
if (primary == null || !primary.active()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportNodesListShardStoreMetaData.NodesStoreFilesMetaData nodesStoreFilesMetaData = transportNodesListShardStoreMetaData.list(shard.shardId(), false, nodesIds.toArray(new String[nodesIds.size()])).actionGet();
|
||||||
|
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
if (nodesStoreFilesMetaData.failures().length > 0) {
|
||||||
|
StringBuilder sb = new StringBuilder(shard + ": failures when trying to list stores on nodes:\n");
|
||||||
|
for (int i = 0; i < nodesStoreFilesMetaData.failures().length; i++) {
|
||||||
|
sb.append(i).append(". ").append(nodesStoreFilesMetaData.failures()[i].getDetailedMessage()).append("\n");
|
||||||
|
}
|
||||||
|
logger.warn(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long lastSizeMatched = 0;
|
long lastSizeMatched = 0;
|
||||||
DiscoveryNode lastDiscoNodeMatched = null;
|
DiscoveryNode lastDiscoNodeMatched = null;
|
||||||
@ -76,6 +109,7 @@ public class PreferUnallocatedShardUnassignedStrategy extends AbstractComponent
|
|||||||
|
|
||||||
for (TransportNodesListShardStoreMetaData.NodeStoreFilesMetaData nodeStoreFilesMetaData : nodesStoreFilesMetaData) {
|
for (TransportNodesListShardStoreMetaData.NodeStoreFilesMetaData nodeStoreFilesMetaData : nodesStoreFilesMetaData) {
|
||||||
DiscoveryNode discoNode = nodeStoreFilesMetaData.node();
|
DiscoveryNode discoNode = nodeStoreFilesMetaData.node();
|
||||||
|
logger.trace("{}: checking node [{}]", shard, discoNode);
|
||||||
IndexStore.StoreFilesMetaData storeFilesMetaData = nodeStoreFilesMetaData.storeFilesMetaData();
|
IndexStore.StoreFilesMetaData storeFilesMetaData = nodeStoreFilesMetaData.storeFilesMetaData();
|
||||||
|
|
||||||
if (storeFilesMetaData == null) {
|
if (storeFilesMetaData == null) {
|
||||||
@ -104,16 +138,39 @@ public class PreferUnallocatedShardUnassignedStrategy extends AbstractComponent
|
|||||||
try {
|
try {
|
||||||
ImmutableMap<String, BlobMetaData> indexBlobsMetaData = indexGateway.listIndexBlobs(shard.id());
|
ImmutableMap<String, BlobMetaData> indexBlobsMetaData = indexGateway.listIndexBlobs(shard.id());
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
StringBuilder sb = new StringBuilder(shard + ": checking for pre_allocation (gateway) on node " + discoNode + "\n");
|
||||||
|
sb.append(" gateway_files:\n");
|
||||||
|
for (BlobMetaData md : indexBlobsMetaData.values()) {
|
||||||
|
sb.append(" [").append(md.name()).append("], size [").append(new ByteSizeValue(md.sizeInBytes())).append("], md5 [").append(md.md5()).append("]\n");
|
||||||
|
}
|
||||||
|
sb.append(" node_files:\n");
|
||||||
|
for (StoreFileMetaData md : storeFilesMetaData) {
|
||||||
|
sb.append(" [").append(md.name()).append("], size [").append(new ByteSizeValue(md.sizeInBytes())).append("], md5 [").append(md.md5()).append("]\n");
|
||||||
|
}
|
||||||
|
logger.debug(sb.toString());
|
||||||
|
}
|
||||||
|
logger.trace("{}: checking for pre_allocation (gateway) on node [{}]\n gateway files", shard, discoNode, indexBlobsMetaData.keySet());
|
||||||
long sizeMatched = 0;
|
long sizeMatched = 0;
|
||||||
for (StoreFileMetaData storeFileMetaData : storeFilesMetaData) {
|
for (StoreFileMetaData storeFileMetaData : storeFilesMetaData) {
|
||||||
if (indexBlobsMetaData.containsKey(storeFileMetaData.name()) && indexBlobsMetaData.get(storeFileMetaData.name()).md5().equals(storeFileMetaData.md5())) {
|
if (indexBlobsMetaData.containsKey(storeFileMetaData.name())) {
|
||||||
sizeMatched += storeFileMetaData.sizeInBytes();
|
if (indexBlobsMetaData.get(storeFileMetaData.name()).md5().equals(storeFileMetaData.md5())) {
|
||||||
|
logger.trace("{}: [{}] reusing file since it exists on remote node and on gateway (same md5) with size [{}]", shard, storeFileMetaData.name(), new ByteSizeValue(storeFileMetaData.sizeInBytes()));
|
||||||
|
sizeMatched += storeFileMetaData.sizeInBytes();
|
||||||
|
} else {
|
||||||
|
logger.trace("{}: [{}] ignore file since it exists on remote node and on gateway but has different md5, remote node [{}], gateway [{}]", shard, storeFileMetaData.name(), storeFileMetaData.md5(), indexBlobsMetaData.get(storeFileMetaData.name()).md5());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.trace("{}: [{}] exists on remote node, does not exists on gateway", shard, storeFileMetaData.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sizeMatched > lastSizeMatched) {
|
if (sizeMatched > lastSizeMatched) {
|
||||||
lastSizeMatched = sizeMatched;
|
lastSizeMatched = sizeMatched;
|
||||||
lastDiscoNodeMatched = discoNode;
|
lastDiscoNodeMatched = discoNode;
|
||||||
lastNodeMatched = node;
|
lastNodeMatched = node;
|
||||||
|
logger.trace("{}: node elected for pre_allocation [{}], total_size_matched [{}]", shard, discoNode, new ByteSizeValue(sizeMatched));
|
||||||
|
} else {
|
||||||
|
logger.trace("{}: node ignored for pre_allocation [{}], total_size_matched [{}] smaller than last_size_matched [{}]", shard, discoNode, new ByteSizeValue(sizeMatched), new ByteSizeValue(lastSizeMatched));
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -152,7 +209,7 @@ public class PreferUnallocatedShardUnassignedStrategy extends AbstractComponent
|
|||||||
|
|
||||||
if (lastNodeMatched != null) {
|
if (lastNodeMatched != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("[{}][{}] allocating to [{}] in order to reuse its unallocated persistent store", shard.index(), shard.id(), lastDiscoNodeMatched);
|
logger.debug("[{}][{}]: allocating [{}] to [{}] in order to reuse its unallocated persistent store with total_size [{}]", shard.index(), shard.id(), shard, lastDiscoNodeMatched, new ByteSizeValue(lastSizeMatched));
|
||||||
}
|
}
|
||||||
// we found a match
|
// we found a match
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -111,7 +111,7 @@ public class ShardsRoutingStrategy extends AbstractComponent {
|
|||||||
// now allocate all the unassigned to available nodes
|
// now allocate all the unassigned to available nodes
|
||||||
if (routingNodes.hasUnassigned()) {
|
if (routingNodes.hasUnassigned()) {
|
||||||
if (preferUnallocatedShardUnassignedStrategy != null) {
|
if (preferUnallocatedShardUnassignedStrategy != null) {
|
||||||
changed |= preferUnallocatedShardUnassignedStrategy.allocateUnassigned(routingNodes);
|
changed |= preferUnallocatedShardUnassignedStrategy.allocateUnassigned(routingNodes, nodes);
|
||||||
}
|
}
|
||||||
changed |= allocateUnassigned(routingNodes);
|
changed |= allocateUnassigned(routingNodes);
|
||||||
// elect primaries again, in case this is needed with unassigned allocation
|
// elect primaries again, in case this is needed with unassigned allocation
|
||||||
|
@ -247,13 +247,17 @@ public class GatewayService extends AbstractLifecycleComponent<GatewayService> i
|
|||||||
// go over the meta data and create indices, we don't really need to copy over
|
// go over the meta data and create indices, we don't really need to copy over
|
||||||
// the meta data per index, since we create the index and it will be added automatically
|
// the meta data per index, since we create the index and it will be added automatically
|
||||||
for (final IndexMetaData indexMetaData : fMetaData) {
|
for (final IndexMetaData indexMetaData : fMetaData) {
|
||||||
try {
|
threadPool.execute(new Runnable() {
|
||||||
metaDataService.createIndex("gateway", indexMetaData.index(), indexMetaData.settings(), indexMetaData.mappings(), timeValueMillis(10));
|
@Override public void run() {
|
||||||
} catch (Exception e) {
|
try {
|
||||||
logger.error("failed to create index [" + indexMetaData.index() + "]", e);
|
metaDataService.createIndex("gateway", indexMetaData.index(), indexMetaData.settings(), indexMetaData.mappings(), timeValueSeconds(30));
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
latch.countDown();
|
logger.error("failed to create index [" + indexMetaData.index() + "]", e);
|
||||||
}
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
clusterService.submitStateUpdateTask("gateway (remove block)", new ClusterStateUpdateTask() {
|
clusterService.submitStateUpdateTask("gateway (remove block)", new ClusterStateUpdateTask() {
|
||||||
@Override public ClusterState execute(ClusterState currentState) {
|
@Override public ClusterState execute(ClusterState currentState) {
|
||||||
|
@ -269,8 +269,8 @@ public class RecoveryAction extends AbstractIndexShardComponent implements Close
|
|||||||
}
|
}
|
||||||
} else if (cause instanceof IgnoreRecoveryException) {
|
} else if (cause instanceof IgnoreRecoveryException) {
|
||||||
throw (IgnoreRecoveryException) cause;
|
throw (IgnoreRecoveryException) cause;
|
||||||
} else if (cause instanceof NodeNotConnectedException) {
|
} else if ((cause instanceof NodeNotConnectedException) || (cause instanceof NodeDisconnectedException)) {
|
||||||
throw new IgnoreRecoveryException("Ignore recovery attemot, remote node not connected", e);
|
throw new IgnoreRecoveryException("Ignore recovery attempt, remote node not connected", e);
|
||||||
}
|
}
|
||||||
throw new RecoveryFailedException(shardId, node, targetNode, e);
|
throw new RecoveryFailedException(shardId, node, targetNode, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -21,14 +21,12 @@ package org.elasticsearch.indices.store;
|
|||||||
|
|
||||||
import org.elasticsearch.ElasticSearchException;
|
import org.elasticsearch.ElasticSearchException;
|
||||||
import org.elasticsearch.action.ActionFuture;
|
import org.elasticsearch.action.ActionFuture;
|
||||||
|
import org.elasticsearch.action.FailedNodeException;
|
||||||
import org.elasticsearch.action.support.nodes.*;
|
import org.elasticsearch.action.support.nodes.*;
|
||||||
import org.elasticsearch.cluster.ClusterName;
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
|
||||||
import org.elasticsearch.common.collect.Lists;
|
import org.elasticsearch.common.collect.Lists;
|
||||||
import org.elasticsearch.common.collect.Sets;
|
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
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;
|
||||||
@ -42,7 +40,6 @@ import org.elasticsearch.transport.TransportService;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,15 +55,8 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio
|
|||||||
this.indicesService = indicesService;
|
this.indicesService = indicesService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionFuture<NodesStoreFilesMetaData> list(ShardId shardId, boolean onlyUnallocated) {
|
public ActionFuture<NodesStoreFilesMetaData> list(ShardId shardId, boolean onlyUnallocated, String[] nodesIds) {
|
||||||
ClusterState state = clusterService.state();
|
return execute(new Request(shardId, onlyUnallocated, nodesIds));
|
||||||
Set<String> nodesIds = Sets.newHashSet();
|
|
||||||
for (DiscoveryNode node : state.nodes()) {
|
|
||||||
if (node.dataNode()) {
|
|
||||||
nodesIds.add(node.id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return execute(new Request(shardId, onlyUnallocated, nodesIds.toArray(new String[nodesIds.size()])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected String transportAction() {
|
@Override protected String transportAction() {
|
||||||
@ -93,27 +83,19 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio
|
|||||||
return new NodeStoreFilesMetaData();
|
return new NodeStoreFilesMetaData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// only list stores on data node
|
|
||||||
|
|
||||||
@Override protected String[] filterNodeIds(DiscoveryNodes nodes, String[] nodesIds) {
|
|
||||||
Set<String> onlyDataNodeIds = Sets.newHashSet();
|
|
||||||
for (String nodeId : nodesIds) {
|
|
||||||
if (nodes.nodeExists(nodeId) && nodes.get(nodeId).dataNode()) {
|
|
||||||
onlyDataNodeIds.add(nodeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return onlyDataNodeIds.toArray(new String[onlyDataNodeIds.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected NodesStoreFilesMetaData newResponse(Request request, AtomicReferenceArray responses) {
|
@Override protected NodesStoreFilesMetaData newResponse(Request request, AtomicReferenceArray responses) {
|
||||||
final List<NodeStoreFilesMetaData> nodeStoreFilesMetaDatas = Lists.newArrayList();
|
final List<NodeStoreFilesMetaData> nodeStoreFilesMetaDatas = Lists.newArrayList();
|
||||||
|
final List<FailedNodeException> failures = Lists.newArrayList();
|
||||||
for (int i = 0; i < responses.length(); i++) {
|
for (int i = 0; i < responses.length(); i++) {
|
||||||
Object resp = responses.get(i);
|
Object resp = responses.get(i);
|
||||||
if (resp instanceof NodeStoreFilesMetaData) { // will also filter out null response for unallocated ones
|
if (resp instanceof NodeStoreFilesMetaData) { // will also filter out null response for unallocated ones
|
||||||
nodeStoreFilesMetaDatas.add((NodeStoreFilesMetaData) resp);
|
nodeStoreFilesMetaDatas.add((NodeStoreFilesMetaData) resp);
|
||||||
|
} else if (resp instanceof FailedNodeException) {
|
||||||
|
failures.add((FailedNodeException) resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new NodesStoreFilesMetaData(clusterName, nodeStoreFilesMetaDatas.toArray(new NodeStoreFilesMetaData[nodeStoreFilesMetaDatas.size()]));
|
return new NodesStoreFilesMetaData(clusterName, nodeStoreFilesMetaDatas.toArray(new NodeStoreFilesMetaData[nodeStoreFilesMetaDatas.size()]),
|
||||||
|
failures.toArray(new FailedNodeException[failures.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected NodeStoreFilesMetaData nodeOperation(NodeRequest request) throws ElasticSearchException {
|
@Override protected NodeStoreFilesMetaData nodeOperation(NodeRequest request) throws ElasticSearchException {
|
||||||
@ -129,7 +111,7 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override protected boolean accumulateExceptions() {
|
@Override protected boolean accumulateExceptions() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Request extends NodesOperationRequest {
|
static class Request extends NodesOperationRequest {
|
||||||
@ -162,11 +144,18 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio
|
|||||||
|
|
||||||
public static class NodesStoreFilesMetaData extends NodesOperationResponse<NodeStoreFilesMetaData> {
|
public static class NodesStoreFilesMetaData extends NodesOperationResponse<NodeStoreFilesMetaData> {
|
||||||
|
|
||||||
|
private FailedNodeException[] failures;
|
||||||
|
|
||||||
NodesStoreFilesMetaData() {
|
NodesStoreFilesMetaData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodesStoreFilesMetaData(ClusterName clusterName, NodeStoreFilesMetaData[] nodes) {
|
public NodesStoreFilesMetaData(ClusterName clusterName, NodeStoreFilesMetaData[] nodes, FailedNodeException[] failures) {
|
||||||
super(clusterName, nodes);
|
super(clusterName, nodes);
|
||||||
|
this.failures = failures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FailedNodeException[] failures() {
|
||||||
|
return failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void readFrom(StreamInput in) throws IOException {
|
@Override public void readFrom(StreamInput in) throws IOException {
|
||||||
|
@ -24,9 +24,9 @@ import org.elasticsearch.cluster.node.DiscoveryNode;
|
|||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
*/
|
*/
|
||||||
public class NodeDisconnectedTransportException extends ConnectTransportException {
|
public class NodeDisconnectedException extends ConnectTransportException {
|
||||||
|
|
||||||
public NodeDisconnectedTransportException(DiscoveryNode node, String action) {
|
public NodeDisconnectedException(DiscoveryNode node, String action) {
|
||||||
super(node, "disconnected", action, null);
|
super(node, "disconnected", action, null);
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ public class TransportService extends AbstractLifecycleComponent<TransportServic
|
|||||||
// want handlers to worry about stack overflows
|
// want handlers to worry about stack overflows
|
||||||
threadPool.execute(new Runnable() {
|
threadPool.execute(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
holderToNotify.handler().handleException(new NodeDisconnectedTransportException(node, holderToNotify.action()));
|
holderToNotify.handler().handleException(new NodeDisconnectedException(node, holderToNotify.action()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler {
|
|||||||
boolean isRequest = isRequest(status);
|
boolean isRequest = isRequest(status);
|
||||||
|
|
||||||
if (isRequest) {
|
if (isRequest) {
|
||||||
TransportRequestHandler handler = handleRequest(event, streamIn, requestId);
|
String action = handleRequest(event, streamIn, requestId);
|
||||||
if (buffer.readerIndex() < expectedIndexReader) {
|
if (buffer.readerIndex() < expectedIndexReader) {
|
||||||
logger.warn("Message not fully read (request) for [{}] and handler {}, resetting", requestId, handler);
|
logger.warn("Message not fully read (request) for [{}] and action [{}], resetting", requestId, action);
|
||||||
buffer.readerIndex(expectedIndexReader);
|
buffer.readerIndex(expectedIndexReader);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -160,7 +160,7 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportRequestHandler handleRequest(MessageEvent event, StreamInput buffer, long requestId) throws IOException {
|
private String handleRequest(MessageEvent event, StreamInput buffer, long requestId) throws IOException {
|
||||||
final String action = buffer.readUTF();
|
final String action = buffer.readUTF();
|
||||||
|
|
||||||
final NettyTransportChannel transportChannel = new NettyTransportChannel(transport, action, event.getChannel(), requestId);
|
final NettyTransportChannel transportChannel = new NettyTransportChannel(transport, action, event.getChannel(), requestId);
|
||||||
@ -190,7 +190,6 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler {
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
handler.messageReceived(streamable, transportChannel);
|
handler.messageReceived(streamable, transportChannel);
|
||||||
}
|
}
|
||||||
return handler;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
try {
|
try {
|
||||||
transportChannel.sendResponse(e);
|
transportChannel.sendResponse(e);
|
||||||
@ -199,7 +198,7 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler {
|
|||||||
logger.warn("Actual Exception", e1);
|
logger.warn("Actual Exception", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
@Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user