Merge pull request #12944 from jasontedor/feature/7990

Add mechanism for transporting shard-level actions by node
This commit is contained in:
Jason Tedor 2015-08-29 16:45:29 -04:00
commit 5e2efcfe09
39 changed files with 1439 additions and 879 deletions

View File

@ -21,7 +21,6 @@ package org.elasticsearch.action.admin.cluster.stats;
import com.carrotsearch.hppc.ObjectObjectHashMap; import com.carrotsearch.hppc.ObjectObjectHashMap;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import org.elasticsearch.action.admin.indices.stats.CommonStats; import org.elasticsearch.action.admin.indices.stats.CommonStats;
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;
@ -67,10 +66,10 @@ public class ClusterStatsIndices implements ToXContent, Streamable {
for (ClusterStatsNodeResponse r : nodeResponses) { for (ClusterStatsNodeResponse r : nodeResponses) {
for (org.elasticsearch.action.admin.indices.stats.ShardStats shardStats : r.shardsStats()) { for (org.elasticsearch.action.admin.indices.stats.ShardStats shardStats : r.shardsStats()) {
ShardStats indexShardStats = countsPerIndex.get(shardStats.getIndex()); ShardStats indexShardStats = countsPerIndex.get(shardStats.getShardRouting().getIndex());
if (indexShardStats == null) { if (indexShardStats == null) {
indexShardStats = new ShardStats(); indexShardStats = new ShardStats();
countsPerIndex.put(shardStats.getIndex(), indexShardStats); countsPerIndex.put(shardStats.getShardRouting().getIndex(), indexShardStats);
} }
indexShardStats.total++; indexShardStats.total++;

View File

@ -1,92 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.admin.indices.cache.clear;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.index.shard.ShardId;
import java.io.IOException;
/**
*
*/
class ShardClearIndicesCacheRequest extends BroadcastShardRequest {
private boolean queryCache = false;
private boolean fieldDataCache = false;
private boolean recycler;
private boolean requestCache = false;
private String[] fields = null;
ShardClearIndicesCacheRequest() {
}
ShardClearIndicesCacheRequest(ShardId shardId, ClearIndicesCacheRequest request) {
super(shardId, request);
queryCache = request.queryCache();
fieldDataCache = request.fieldDataCache();
fields = request.fields();
recycler = request.recycler();
requestCache = request.requestCache();
}
public boolean queryCache() {
return queryCache;
}
public boolean requestCache() {
return requestCache;
}
public boolean fieldDataCache() {
return this.fieldDataCache;
}
public boolean recycler() {
return this.recycler;
}
public String[] fields() {
return this.fields;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
queryCache = in.readBoolean();
fieldDataCache = in.readBoolean();
recycler = in.readBoolean();
fields = in.readStringArray();
requestCache = in.readBoolean();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBoolean(queryCache);
out.writeBoolean(fieldDataCache);
out.writeBoolean(recycler);
out.writeStringArrayNullable(fields);
out.writeBoolean(requestCache);
}
}

View File

@ -1,36 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.admin.indices.cache.clear;
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
import org.elasticsearch.index.shard.ShardId;
/**
*
*/
class ShardClearIndicesCacheResponse extends BroadcastShardResponse {
ShardClearIndicesCacheResponse() {
}
ShardClearIndicesCacheResponse(ShardId shardId) {
super(shardId);
}
}

View File

@ -21,17 +21,16 @@ package org.elasticsearch.action.admin.indices.cache.clear;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
@ -40,14 +39,14 @@ import org.elasticsearch.indices.cache.request.IndicesRequestCache;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.util.ArrayList; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
* Indices clear cache action. * Indices clear cache action.
*/ */
public class TransportClearIndicesCacheAction extends TransportBroadcastAction<ClearIndicesCacheRequest, ClearIndicesCacheResponse, ShardClearIndicesCacheRequest, ShardClearIndicesCacheResponse> { public class TransportClearIndicesCacheAction extends TransportBroadcastByNodeAction<ClearIndicesCacheRequest, ClearIndicesCacheResponse, TransportBroadcastByNodeAction.EmptyResult> {
private final IndicesService indicesService; private final IndicesService indicesService;
private final IndicesRequestCache indicesRequestCache; private final IndicesRequestCache indicesRequestCache;
@ -58,48 +57,33 @@ public class TransportClearIndicesCacheAction extends TransportBroadcastAction<C
IndicesRequestCache indicesQueryCache, ActionFilters actionFilters, IndicesRequestCache indicesQueryCache, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver) { IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, ClearIndicesCacheAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, ClearIndicesCacheAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
ClearIndicesCacheRequest.class, ShardClearIndicesCacheRequest.class, ThreadPool.Names.MANAGEMENT); ClearIndicesCacheRequest.class, ThreadPool.Names.MANAGEMENT);
this.indicesService = indicesService; this.indicesService = indicesService;
this.indicesRequestCache = indicesQueryCache; this.indicesRequestCache = indicesQueryCache;
} }
@Override @Override
protected ClearIndicesCacheResponse newResponse(ClearIndicesCacheRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected EmptyResult readShardResult(StreamInput in) throws IOException {
int successfulShards = 0; return EmptyResult.readEmptyResultFrom(in);
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
for (int i = 0; i < shardsResponses.length(); i++) {
Object shardResponse = shardsResponses.get(i);
if (shardResponse == null) {
// simply ignore non active shards
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
failedShards++;
if (shardFailures == null) {
shardFailures = new ArrayList<>();
}
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else {
successfulShards++;
}
}
return new ClearIndicesCacheResponse(shardsResponses.length(), successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardClearIndicesCacheRequest newShardRequest(int numShards, ShardRouting shard, ClearIndicesCacheRequest request) { protected ClearIndicesCacheResponse newResponse(ClearIndicesCacheRequest request, int totalShards, int successfulShards, int failedShards, List<EmptyResult> responses, List<ShardOperationFailedException> shardFailures) {
return new ShardClearIndicesCacheRequest(shard.shardId(), request); return new ClearIndicesCacheResponse(totalShards, successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardClearIndicesCacheResponse newShardResponse() { protected ClearIndicesCacheRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardClearIndicesCacheResponse(); final ClearIndicesCacheRequest request = new ClearIndicesCacheRequest();
request.readFrom(in);
return request;
} }
@Override @Override
protected ShardClearIndicesCacheResponse shardOperation(ShardClearIndicesCacheRequest request) { protected EmptyResult shardOperation(ClearIndicesCacheRequest request, ShardRouting shardRouting) {
IndexService service = indicesService.indexService(request.shardId().getIndex()); IndexService service = indicesService.indexService(shardRouting.getIndex());
if (service != null) { if (service != null) {
IndexShard shard = service.shard(request.shardId().id()); IndexShard shard = service.shard(shardRouting.id());
boolean clearedAtLeastOne = false; boolean clearedAtLeastOne = false;
if (request.queryCache()) { if (request.queryCache()) {
clearedAtLeastOne = true; clearedAtLeastOne = true;
@ -137,15 +121,15 @@ public class TransportClearIndicesCacheAction extends TransportBroadcastAction<C
} }
} }
} }
return new ShardClearIndicesCacheResponse(request.shardId()); return EmptyResult.INSTANCE;
} }
/** /**
* The refresh request works against *all* shards. * The refresh request works against *all* shards.
*/ */
@Override @Override
protected GroupShardsIterator shards(ClusterState clusterState, ClearIndicesCacheRequest request, String[] concreteIndices) { protected ShardsIterator shards(ClusterState clusterState, ClearIndicesCacheRequest request, String[] concreteIndices) {
return clusterState.routingTable().allActiveShardsGrouped(concreteIndices, true); return clusterState.routingTable().allShards(concreteIndices);
} }
@Override @Override
@ -157,5 +141,4 @@ public class TransportClearIndicesCacheAction extends TransportBroadcastAction<C
protected ClusterBlockException checkRequestBlock(ClusterState state, ClearIndicesCacheRequest request, String[] concreteIndices) { protected ClusterBlockException checkRequestBlock(ClusterState state, ClearIndicesCacheRequest request, String[] concreteIndices) {
return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, concreteIndices); return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, concreteIndices);
} }
} }

View File

@ -1,60 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.admin.indices.optimize;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.index.shard.ShardId;
import java.io.IOException;
/**
*
*/
final class ShardOptimizeRequest extends BroadcastShardRequest {
private OptimizeRequest request = new OptimizeRequest();
ShardOptimizeRequest() {
}
ShardOptimizeRequest(ShardId shardId, OptimizeRequest request) {
super(shardId, request);
this.request = request;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
request.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
request.writeTo(out);
}
public OptimizeRequest optimizeRequest() {
return this.request;
}
}

View File

@ -1,36 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.admin.indices.optimize;
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
import org.elasticsearch.index.shard.ShardId;
/**
*
*/
class ShardOptimizeResponse extends BroadcastShardResponse {
ShardOptimizeResponse() {
}
ShardOptimizeResponse(ShardId shardId) {
super(shardId);
}
}

View File

@ -21,31 +21,29 @@ package org.elasticsearch.action.admin.indices.optimize;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.util.ArrayList; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
* Optimize index/indices action. * Optimize index/indices action.
*/ */
public class TransportOptimizeAction extends TransportBroadcastAction<OptimizeRequest, OptimizeResponse, ShardOptimizeRequest, ShardOptimizeResponse> { public class TransportOptimizeAction extends TransportBroadcastByNodeAction<OptimizeRequest, OptimizeResponse, TransportBroadcastByNodeAction.EmptyResult> {
private final IndicesService indicesService; private final IndicesService indicesService;
@ -54,55 +52,40 @@ public class TransportOptimizeAction extends TransportBroadcastAction<OptimizeRe
TransportService transportService, IndicesService indicesService, TransportService transportService, IndicesService indicesService,
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, OptimizeAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, OptimizeAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
OptimizeRequest.class, ShardOptimizeRequest.class, ThreadPool.Names.OPTIMIZE); OptimizeRequest.class, ThreadPool.Names.OPTIMIZE);
this.indicesService = indicesService; this.indicesService = indicesService;
} }
@Override @Override
protected OptimizeResponse newResponse(OptimizeRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected EmptyResult readShardResult(StreamInput in) throws IOException {
int successfulShards = 0; return EmptyResult.readEmptyResultFrom(in);
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
for (int i = 0; i < shardsResponses.length(); i++) {
Object shardResponse = shardsResponses.get(i);
if (shardResponse == null) {
// a non active shard, ignore...
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
failedShards++;
if (shardFailures == null) {
shardFailures = new ArrayList<>();
}
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else {
successfulShards++;
}
}
return new OptimizeResponse(shardsResponses.length(), successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardOptimizeRequest newShardRequest(int numShards, ShardRouting shard, OptimizeRequest request) { protected OptimizeResponse newResponse(OptimizeRequest request, int totalShards, int successfulShards, int failedShards, List<EmptyResult> responses, List<ShardOperationFailedException> shardFailures) {
return new ShardOptimizeRequest(shard.shardId(), request); return new OptimizeResponse(totalShards, successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardOptimizeResponse newShardResponse() { protected OptimizeRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardOptimizeResponse(); final OptimizeRequest request = new OptimizeRequest();
request.readFrom(in);
return request;
} }
@Override @Override
protected ShardOptimizeResponse shardOperation(ShardOptimizeRequest request) { protected EmptyResult shardOperation(OptimizeRequest request, ShardRouting shardRouting) {
IndexShard indexShard = indicesService.indexServiceSafe(request.shardId().getIndex()).shardSafe(request.shardId().id()); IndexShard indexShard = indicesService.indexServiceSafe(shardRouting.shardId().getIndex()).shardSafe(shardRouting.shardId().id());
indexShard.optimize(request.optimizeRequest()); indexShard.optimize(request);
return new ShardOptimizeResponse(request.shardId()); return EmptyResult.INSTANCE;
} }
/** /**
* The refresh request works against *all* shards. * The refresh request works against *all* shards.
*/ */
@Override @Override
protected GroupShardsIterator shards(ClusterState clusterState, OptimizeRequest request, String[] concreteIndices) { protected ShardsIterator shards(ClusterState clusterState, OptimizeRequest request, String[] concreteIndices) {
return clusterState.routingTable().allActiveShardsGrouped(concreteIndices, true); return clusterState.routingTable().allShards(concreteIndices);
} }
@Override @Override

View File

@ -25,6 +25,7 @@ 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.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.indices.recovery.RecoveryState;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -38,7 +39,7 @@ import java.util.Map;
public class RecoveryResponse extends BroadcastResponse implements ToXContent { public class RecoveryResponse extends BroadcastResponse implements ToXContent {
private boolean detailed = false; private boolean detailed = false;
private Map<String, List<ShardRecoveryResponse>> shardResponses = new HashMap<>(); private Map<String, List<RecoveryState>> shardRecoveryStates = new HashMap<>();
public RecoveryResponse() { } public RecoveryResponse() { }
@ -50,18 +51,18 @@ public class RecoveryResponse extends BroadcastResponse implements ToXContent {
* @param successfulShards Count of shards successfully processed * @param successfulShards Count of shards successfully processed
* @param failedShards Count of shards which failed to process * @param failedShards Count of shards which failed to process
* @param detailed Display detailed metrics * @param detailed Display detailed metrics
* @param shardResponses Map of indices to shard recovery information * @param shardRecoveryStates Map of indices to shard recovery information
* @param shardFailures List of failures processing shards * @param shardFailures List of failures processing shards
*/ */
public RecoveryResponse(int totalShards, int successfulShards, int failedShards, boolean detailed, public RecoveryResponse(int totalShards, int successfulShards, int failedShards, boolean detailed,
Map<String, List<ShardRecoveryResponse>> shardResponses, List<ShardOperationFailedException> shardFailures) { Map<String, List<RecoveryState>> shardRecoveryStates, List<ShardOperationFailedException> shardFailures) {
super(totalShards, successfulShards, failedShards, shardFailures); super(totalShards, successfulShards, failedShards, shardFailures);
this.shardResponses = shardResponses; this.shardRecoveryStates = shardRecoveryStates;
this.detailed = detailed; this.detailed = detailed;
} }
public boolean hasRecoveries() { public boolean hasRecoveries() {
return shardResponses.size() > 0; return shardRecoveryStates.size() > 0;
} }
public boolean detailed() { public boolean detailed() {
@ -72,23 +73,23 @@ public class RecoveryResponse extends BroadcastResponse implements ToXContent {
this.detailed = detailed; this.detailed = detailed;
} }
public Map<String, List<ShardRecoveryResponse>> shardResponses() { public Map<String, List<RecoveryState>> shardRecoveryStates() {
return shardResponses; return shardRecoveryStates;
} }
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (hasRecoveries()) { if (hasRecoveries()) {
for (String index : shardResponses.keySet()) { for (String index : shardRecoveryStates.keySet()) {
List<ShardRecoveryResponse> responses = shardResponses.get(index); List<RecoveryState> recoveryStates = shardRecoveryStates.get(index);
if (responses == null || responses.size() == 0) { if (recoveryStates == null || recoveryStates.size() == 0) {
continue; continue;
} }
builder.startObject(index); builder.startObject(index);
builder.startArray("shards"); builder.startArray("shards");
for (ShardRecoveryResponse recoveryResponse : responses) { for (RecoveryState recoveryState : recoveryStates) {
builder.startObject(); builder.startObject();
recoveryResponse.toXContent(builder, params); recoveryState.toXContent(builder, params);
builder.endObject(); builder.endObject();
} }
builder.endArray(); builder.endArray();
@ -101,12 +102,12 @@ public class RecoveryResponse extends BroadcastResponse implements ToXContent {
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
out.writeVInt(shardResponses.size()); out.writeVInt(shardRecoveryStates.size());
for (Map.Entry<String, List<ShardRecoveryResponse>> entry : shardResponses.entrySet()) { for (Map.Entry<String, List<RecoveryState>> entry : shardRecoveryStates.entrySet()) {
out.writeString(entry.getKey()); out.writeString(entry.getKey());
out.writeVInt(entry.getValue().size()); out.writeVInt(entry.getValue().size());
for (ShardRecoveryResponse recoveryResponse : entry.getValue()) { for (RecoveryState recoveryState : entry.getValue()) {
recoveryResponse.writeTo(out); recoveryState.writeTo(out);
} }
} }
} }
@ -118,11 +119,11 @@ public class RecoveryResponse extends BroadcastResponse implements ToXContent {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
String s = in.readString(); String s = in.readString();
int listSize = in.readVInt(); int listSize = in.readVInt();
List<ShardRecoveryResponse> list = new ArrayList<>(listSize); List<RecoveryState> list = new ArrayList<>(listSize);
for (int j = 0; j < listSize; j++) { for (int j = 0; j < listSize; j++) {
list.add(ShardRecoveryResponse.readShardRecoveryResponse(in)); list.add(RecoveryState.readRecoveryState(in));
} }
shardResponses.put(s, list); shardRecoveryStates.put(s, list);
} }
} }
} }

View File

@ -1,100 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.admin.indices.recovery;
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.recovery.RecoveryState;
import java.io.IOException;
/**
* Information regarding the recovery state of a shard.
*/
public class ShardRecoveryResponse extends BroadcastShardResponse implements ToXContent {
RecoveryState recoveryState;
public ShardRecoveryResponse() { }
/**
* Constructs shard recovery information for the given index and shard id.
*
* @param shardId Id of the shard
*/
ShardRecoveryResponse(ShardId shardId) {
super(shardId);
}
/**
* Sets the recovery state information for the shard.
*
* @param recoveryState Recovery state
*/
public void recoveryState(RecoveryState recoveryState) {
this.recoveryState = recoveryState;
}
/**
* Gets the recovery state information for the shard. Null if shard wasn't recovered / recovery didn't start yet.
*
* @return Recovery state
*/
@Nullable
public RecoveryState recoveryState() {
return recoveryState;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
recoveryState.toXContent(builder, params);
return builder;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
recoveryState.writeTo(out);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
recoveryState = RecoveryState.readRecoveryState(in);
}
/**
* Builds a new ShardRecoveryResponse from the give input stream.
*
* @param in Input stream
* @return A new ShardRecoveryResponse
* @throws IOException
*/
public static ShardRecoveryResponse readShardRecoveryResponse(StreamInput in) throws IOException {
ShardRecoveryResponse response = new ShardRecoveryResponse();
response.readFrom(in);
return response;
}
}

View File

@ -19,40 +19,37 @@
package org.elasticsearch.action.admin.indices.recovery; package org.elasticsearch.action.admin.indices.recovery;
import com.google.common.collect.Maps;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.recovery.RecoveryState; import org.elasticsearch.indices.recovery.RecoveryState;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
* Transport action for shard recovery operation. This transport action does not actually * Transport action for shard recovery operation. This transport action does not actually
* perform shard recovery, it only reports on recoveries (both active and complete). * perform shard recovery, it only reports on recoveries (both active and complete).
*/ */
public class TransportRecoveryAction extends TransportBroadcastAction<RecoveryRequest, RecoveryResponse, TransportRecoveryAction.ShardRecoveryRequest, ShardRecoveryResponse> { public class TransportRecoveryAction extends TransportBroadcastByNodeAction<RecoveryRequest, RecoveryResponse, RecoveryState> {
private final IndicesService indicesService; private final IndicesService indicesService;
@ -61,84 +58,55 @@ public class TransportRecoveryAction extends TransportBroadcastAction<RecoveryRe
TransportService transportService, IndicesService indicesService, TransportService transportService, IndicesService indicesService,
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, RecoveryAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, RecoveryAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
RecoveryRequest.class, ShardRecoveryRequest.class, ThreadPool.Names.MANAGEMENT); RecoveryRequest.class, ThreadPool.Names.MANAGEMENT);
this.indicesService = indicesService; this.indicesService = indicesService;
} }
@Override @Override
protected RecoveryResponse newResponse(RecoveryRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected RecoveryState readShardResult(StreamInput in) throws IOException {
return RecoveryState.readRecoveryState(in);
}
int successfulShards = 0;
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
Map<String, List<ShardRecoveryResponse>> shardResponses = new HashMap<>();
for (int i = 0; i < shardsResponses.length(); i++) { @Override
Object shardResponse = shardsResponses.get(i); protected RecoveryResponse newResponse(RecoveryRequest request, int totalShards, int successfulShards, int failedShards, List<RecoveryState> responses, List<ShardOperationFailedException> shardFailures) {
if (shardResponse == null) { Map<String, List<RecoveryState>> shardResponses = Maps.newHashMap();
// simply ignore non active shards for (RecoveryState recoveryState : responses) {
} else if (shardResponse instanceof BroadcastShardOperationFailedException) { if (recoveryState == null) {
failedShards++; continue;
if (shardFailures == null) { }
shardFailures = new ArrayList<>(); String indexName = recoveryState.getShardId().getIndex();
if (!shardResponses.containsKey(indexName)) {
shardResponses.put(indexName, new ArrayList<RecoveryState>());
}
if (request.activeOnly()) {
if (recoveryState.getStage() != RecoveryState.Stage.DONE) {
shardResponses.get(indexName).add(recoveryState);
} }
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else { } else {
ShardRecoveryResponse recoveryResponse = (ShardRecoveryResponse) shardResponse; shardResponses.get(indexName).add(recoveryState);
successfulShards++;
if (recoveryResponse.recoveryState() == null) {
// recovery not yet started
continue;
}
String indexName = recoveryResponse.getIndex();
List<ShardRecoveryResponse> responses = shardResponses.get(indexName);
if (responses == null) {
responses = new ArrayList<>();
shardResponses.put(indexName, responses);
}
if (request.activeOnly()) {
if (recoveryResponse.recoveryState().getStage() != RecoveryState.Stage.DONE) {
responses.add(recoveryResponse);
}
} else {
responses.add(recoveryResponse);
}
} }
} }
return new RecoveryResponse(totalShards, successfulShards, failedShards, request.detailed(), shardResponses, shardFailures);
return new RecoveryResponse(shardsResponses.length(), successfulShards,
failedShards, request.detailed(), shardResponses, shardFailures);
} }
@Override @Override
protected ShardRecoveryRequest newShardRequest(int numShards, ShardRouting shard, RecoveryRequest request) { protected RecoveryRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardRecoveryRequest(shard.shardId(), request); final RecoveryRequest recoveryRequest = new RecoveryRequest();
recoveryRequest.readFrom(in);
return recoveryRequest;
} }
@Override @Override
protected ShardRecoveryResponse newShardResponse() { protected RecoveryState shardOperation(RecoveryRequest request, ShardRouting shardRouting) {
return new ShardRecoveryResponse(); IndexService indexService = indicesService.indexServiceSafe(shardRouting.shardId().getIndex());
IndexShard indexShard = indexService.shardSafe(shardRouting.shardId().id());
return indexShard.recoveryState();
} }
@Override @Override
protected ShardRecoveryResponse shardOperation(ShardRecoveryRequest request) { protected ShardsIterator shards(ClusterState state, RecoveryRequest request, String[] concreteIndices) {
return state.routingTable().allShardsIncludingRelocationTargets(concreteIndices);
IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex());
IndexShard indexShard = indexService.shardSafe(request.shardId().id());
ShardRecoveryResponse shardRecoveryResponse = new ShardRecoveryResponse(request.shardId());
RecoveryState state = indexShard.recoveryState();
shardRecoveryResponse.recoveryState(state);
return shardRecoveryResponse;
}
@Override
protected GroupShardsIterator shards(ClusterState state, RecoveryRequest request, String[] concreteIndices) {
return state.routingTable().allAssignedShardsGrouped(concreteIndices, true, true);
} }
@Override @Override
@ -150,14 +118,4 @@ public class TransportRecoveryAction extends TransportBroadcastAction<RecoveryRe
protected ClusterBlockException checkRequestBlock(ClusterState state, RecoveryRequest request, String[] concreteIndices) { protected ClusterBlockException checkRequestBlock(ClusterState state, RecoveryRequest request, String[] concreteIndices) {
return state.blocks().indicesBlockedException(ClusterBlockLevel.READ, concreteIndices); return state.blocks().indicesBlockedException(ClusterBlockLevel.READ, concreteIndices);
} }
static class ShardRecoveryRequest extends BroadcastShardRequest {
ShardRecoveryRequest() {
}
ShardRecoveryRequest(ShardId shardId, RecoveryRequest request) {
super(shardId, request);
}
}
} }

View File

@ -24,7 +24,6 @@ import com.google.common.collect.Sets;
import org.apache.lucene.util.Accountable; import org.apache.lucene.util.Accountable;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.cluster.ClusterState;
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.unit.ByteSizeValue; import org.elasticsearch.common.unit.ByteSizeValue;
@ -50,7 +49,7 @@ public class IndicesSegmentResponse extends BroadcastResponse implements ToXCont
} }
IndicesSegmentResponse(ShardSegments[] shards, ClusterState clusterState, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) { IndicesSegmentResponse(ShardSegments[] shards, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
super(totalShards, successfulShards, failedShards, shardFailures); super(totalShards, successfulShards, failedShards, shardFailures);
this.shards = shards; this.shards = shards;
} }
@ -63,7 +62,7 @@ public class IndicesSegmentResponse extends BroadcastResponse implements ToXCont
Set<String> indices = Sets.newHashSet(); Set<String> indices = Sets.newHashSet();
for (ShardSegments shard : shards) { for (ShardSegments shard : shards) {
indices.add(shard.getIndex()); indices.add(shard.getShardRouting().getIndex());
} }
for (String index : indices) { for (String index : indices) {

View File

@ -20,10 +20,10 @@
package org.elasticsearch.action.admin.indices.segments; package org.elasticsearch.action.admin.indices.segments;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
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.io.stream.Streamable;
import org.elasticsearch.index.engine.Segment; import org.elasticsearch.index.engine.Segment;
import java.io.IOException; import java.io.IOException;
@ -33,7 +33,7 @@ import java.util.List;
import static org.elasticsearch.cluster.routing.ShardRouting.readShardRoutingEntry; import static org.elasticsearch.cluster.routing.ShardRouting.readShardRoutingEntry;
public class ShardSegments extends BroadcastShardResponse implements Iterable<Segment> { public class ShardSegments implements Streamable, Iterable<Segment> {
private ShardRouting shardRouting; private ShardRouting shardRouting;
@ -43,7 +43,6 @@ public class ShardSegments extends BroadcastShardResponse implements Iterable<Se
} }
ShardSegments(ShardRouting shardRouting, List<Segment> segments) { ShardSegments(ShardRouting shardRouting, List<Segment> segments) {
super(shardRouting.shardId());
this.shardRouting = shardRouting; this.shardRouting = shardRouting;
this.segments = segments; this.segments = segments;
} }
@ -89,7 +88,6 @@ public class ShardSegments extends BroadcastShardResponse implements Iterable<Se
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
shardRouting = readShardRoutingEntry(in); shardRouting = readShardRoutingEntry(in);
int size = in.readVInt(); int size = in.readVInt();
if (size == 0) { if (size == 0) {
@ -104,7 +102,6 @@ public class ShardSegments extends BroadcastShardResponse implements Iterable<Se
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
shardRouting.writeTo(out); shardRouting.writeTo(out);
out.writeVInt(segments.size()); out.writeVInt(segments.size());
for (Segment segment : segments) { for (Segment segment : segments) {

View File

@ -21,37 +21,30 @@ package org.elasticsearch.action.admin.indices.segments;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
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.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
* *
*/ */
public class TransportIndicesSegmentsAction extends TransportBroadcastAction<IndicesSegmentsRequest, IndicesSegmentResponse, TransportIndicesSegmentsAction.IndexShardSegmentRequest, ShardSegments> { public class TransportIndicesSegmentsAction extends TransportBroadcastByNodeAction<IndicesSegmentsRequest, IndicesSegmentResponse, ShardSegments> {
private final IndicesService indicesService; private final IndicesService indicesService;
@ -59,7 +52,7 @@ public class TransportIndicesSegmentsAction extends TransportBroadcastAction<Ind
public TransportIndicesSegmentsAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, public TransportIndicesSegmentsAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService,
IndicesService indicesService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { IndicesService indicesService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, IndicesSegmentsAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, IndicesSegmentsAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
IndicesSegmentsRequest.class, TransportIndicesSegmentsAction.IndexShardSegmentRequest.class, ThreadPool.Names.MANAGEMENT); IndicesSegmentsRequest.class, ThreadPool.Names.MANAGEMENT);
this.indicesService = indicesService; this.indicesService = indicesService;
} }
@ -67,8 +60,8 @@ public class TransportIndicesSegmentsAction extends TransportBroadcastAction<Ind
* Segments goes across *all* active shards. * Segments goes across *all* active shards.
*/ */
@Override @Override
protected GroupShardsIterator shards(ClusterState clusterState, IndicesSegmentsRequest request, String[] concreteIndices) { protected ShardsIterator shards(ClusterState clusterState, IndicesSegmentsRequest request, String[] concreteIndices) {
return clusterState.routingTable().allActiveShardsGrouped(concreteIndices, true); return clusterState.routingTable().allShards(concreteIndices);
} }
@Override @Override
@ -82,68 +75,26 @@ public class TransportIndicesSegmentsAction extends TransportBroadcastAction<Ind
} }
@Override @Override
protected IndicesSegmentResponse newResponse(IndicesSegmentsRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected ShardSegments readShardResult(StreamInput in) throws IOException {
int successfulShards = 0; return ShardSegments.readShardSegments(in);
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
final List<ShardSegments> shards = new ArrayList<>();
for (int i = 0; i < shardsResponses.length(); i++) {
Object shardResponse = shardsResponses.get(i);
if (shardResponse == null) {
// simply ignore non active shards
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
failedShards++;
if (shardFailures == null) {
shardFailures = new ArrayList<>();
}
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else {
shards.add((ShardSegments) shardResponse);
successfulShards++;
}
}
return new IndicesSegmentResponse(shards.toArray(new ShardSegments[shards.size()]), clusterState, shardsResponses.length(), successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected IndexShardSegmentRequest newShardRequest(int numShards, ShardRouting shard, IndicesSegmentsRequest request) { protected IndicesSegmentResponse newResponse(IndicesSegmentsRequest request, int totalShards, int successfulShards, int failedShards, List<ShardSegments> results, List<ShardOperationFailedException> shardFailures) {
return new IndexShardSegmentRequest(shard.shardId(), request); return new IndicesSegmentResponse(results.toArray(new ShardSegments[results.size()]), totalShards, successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardSegments newShardResponse() { protected IndicesSegmentsRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardSegments(); final IndicesSegmentsRequest request = new IndicesSegmentsRequest();
request.readFrom(in);
return request;
} }
@Override @Override
protected ShardSegments shardOperation(IndexShardSegmentRequest request) { protected ShardSegments shardOperation(IndicesSegmentsRequest request, ShardRouting shardRouting) {
IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex()); IndexService indexService = indicesService.indexServiceSafe(shardRouting.getIndex());
IndexShard indexShard = indexService.shardSafe(request.shardId().id()); IndexShard indexShard = indexService.shardSafe(shardRouting.id());
return new ShardSegments(indexShard.routingEntry(), indexShard.engine().segments(request.verbose)); return new ShardSegments(indexShard.routingEntry(), indexShard.engine().segments(request.verbose()));
}
static class IndexShardSegmentRequest extends BroadcastShardRequest {
boolean verbose;
IndexShardSegmentRequest() {
verbose = false;
}
IndexShardSegmentRequest(ShardId shardId, IndicesSegmentsRequest request) {
super(shardId, request);
verbose = request.verbose();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBoolean(verbose);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
verbose = in.readBoolean();
}
} }
} }

View File

@ -24,7 +24,6 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
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;
@ -51,7 +50,7 @@ public class IndicesStatsResponse extends BroadcastResponse implements ToXConten
} }
IndicesStatsResponse(ShardStats[] shards, ClusterState clusterState, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) { IndicesStatsResponse(ShardStats[] shards, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
super(totalShards, successfulShards, failedShards, shardFailures); super(totalShards, successfulShards, failedShards, shardFailures);
this.shards = shards; this.shards = shards;
} }
@ -90,7 +89,7 @@ public class IndicesStatsResponse extends BroadcastResponse implements ToXConten
Set<String> indices = Sets.newHashSet(); Set<String> indices = Sets.newHashSet();
for (ShardStats shard : shards) { for (ShardStats shard : shards) {
indices.add(shard.getIndex()); indices.add(shard.getShardRouting().getIndex());
} }
for (String index : indices) { for (String index : indices) {

View File

@ -19,17 +19,16 @@
package org.elasticsearch.action.admin.indices.stats; package org.elasticsearch.action.admin.indices.stats;
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
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.io.stream.Streamable;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.index.engine.CommitStats; import org.elasticsearch.index.engine.CommitStats;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardPath;
import java.io.IOException; import java.io.IOException;
@ -37,7 +36,7 @@ import static org.elasticsearch.cluster.routing.ShardRouting.readShardRoutingEnt
/** /**
*/ */
public class ShardStats extends BroadcastShardResponse implements ToXContent { public class ShardStats implements Streamable, ToXContent {
private ShardRouting shardRouting; private ShardRouting shardRouting;
private CommonStats commonStats; private CommonStats commonStats;
@Nullable @Nullable
@ -50,7 +49,6 @@ public class ShardStats extends BroadcastShardResponse implements ToXContent {
} }
public ShardStats(IndexShard indexShard, CommonStatsFlags flags) { public ShardStats(IndexShard indexShard, CommonStatsFlags flags) {
super(indexShard.shardId());
this.shardRouting = indexShard.routingEntry(); this.shardRouting = indexShard.routingEntry();
this.dataPath = indexShard.shardPath().getRootDataPath().toString(); this.dataPath = indexShard.shardPath().getRootDataPath().toString();
this.statePath = indexShard.shardPath().getRootStatePath().toString(); this.statePath = indexShard.shardPath().getRootStatePath().toString();
@ -94,7 +92,6 @@ public class ShardStats extends BroadcastShardResponse implements ToXContent {
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
shardRouting = readShardRoutingEntry(in); shardRouting = readShardRoutingEntry(in);
commonStats = CommonStats.readCommonStats(in); commonStats = CommonStats.readCommonStats(in);
commitStats = CommitStats.readOptionalCommitStatsFrom(in); commitStats = CommitStats.readOptionalCommitStatsFrom(in);
@ -105,7 +102,6 @@ public class ShardStats extends BroadcastShardResponse implements ToXContent {
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
shardRouting.writeTo(out); shardRouting.writeTo(out);
commonStats.writeTo(out); commonStats.writeTo(out);
out.writeOptionalStreamable(commitStats); out.writeOptionalStreamable(commitStats);
@ -146,5 +142,4 @@ public class ShardStats extends BroadcastShardResponse implements ToXContent {
static final XContentBuilderString NODE = new XContentBuilderString("node"); static final XContentBuilderString NODE = new XContentBuilderString("node");
static final XContentBuilderString RELOCATING_NODE = new XContentBuilderString("relocating_node"); static final XContentBuilderString RELOCATING_NODE = new XContentBuilderString("relocating_node");
} }
} }

View File

@ -21,37 +21,30 @@ package org.elasticsearch.action.admin.indices.stats;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
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.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.shard.ShardNotFoundException; import org.elasticsearch.index.shard.ShardNotFoundException;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
*/ */
public class TransportIndicesStatsAction extends TransportBroadcastAction<IndicesStatsRequest, IndicesStatsResponse, TransportIndicesStatsAction.IndexShardStatsRequest, ShardStats> { public class TransportIndicesStatsAction extends TransportBroadcastByNodeAction<IndicesStatsRequest, IndicesStatsResponse, ShardStats> {
private final IndicesService indicesService; private final IndicesService indicesService;
@ -60,7 +53,7 @@ public class TransportIndicesStatsAction extends TransportBroadcastAction<Indice
TransportService transportService, IndicesService indicesService, TransportService transportService, IndicesService indicesService,
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, IndicesStatsAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, IndicesStatsAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
IndicesStatsRequest.class, IndexShardStatsRequest.class, ThreadPool.Names.MANAGEMENT); IndicesStatsRequest.class, ThreadPool.Names.MANAGEMENT);
this.indicesService = indicesService; this.indicesService = indicesService;
} }
@ -68,8 +61,8 @@ public class TransportIndicesStatsAction extends TransportBroadcastAction<Indice
* Status goes across *all* shards. * Status goes across *all* shards.
*/ */
@Override @Override
protected GroupShardsIterator shards(ClusterState clusterState, IndicesStatsRequest request, String[] concreteIndices) { protected ShardsIterator shards(ClusterState clusterState, IndicesStatsRequest request, String[] concreteIndices) {
return clusterState.routingTable().allAssignedShardsGrouped(concreteIndices, true); return clusterState.routingTable().allShards(concreteIndices);
} }
@Override @Override
@ -82,45 +75,27 @@ public class TransportIndicesStatsAction extends TransportBroadcastAction<Indice
return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_READ, concreteIndices); return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_READ, concreteIndices);
} }
@Override @Override
protected IndicesStatsResponse newResponse(IndicesStatsRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected ShardStats readShardResult(StreamInput in) throws IOException {
int successfulShards = 0; return ShardStats.readShardStats(in);
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
final List<ShardStats> shards = new ArrayList<>();
for (int i = 0; i < shardsResponses.length(); i++) {
Object shardResponse = shardsResponses.get(i);
if (shardResponse == null) {
// simply ignore non active shards
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
failedShards++;
if (shardFailures == null) {
shardFailures = new ArrayList<>();
}
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else {
shards.add((ShardStats) shardResponse);
successfulShards++;
}
}
return new IndicesStatsResponse(shards.toArray(new ShardStats[shards.size()]), clusterState, shardsResponses.length(), successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected IndexShardStatsRequest newShardRequest(int numShards, ShardRouting shard, IndicesStatsRequest request) { protected IndicesStatsResponse newResponse(IndicesStatsRequest request, int totalShards, int successfulShards, int failedShards, List<ShardStats> responses, List<ShardOperationFailedException> shardFailures) {
return new IndexShardStatsRequest(shard.shardId(), request); return new IndicesStatsResponse(responses.toArray(new ShardStats[responses.size()]), totalShards, successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardStats newShardResponse() { protected IndicesStatsRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardStats(); IndicesStatsRequest request = new IndicesStatsRequest();
request.readFrom(in);
return request;
} }
@Override @Override
protected ShardStats shardOperation(IndexShardStatsRequest request) { protected ShardStats shardOperation(IndicesStatsRequest request, ShardRouting shardRouting) {
IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex()); IndexService indexService = indicesService.indexServiceSafe(shardRouting.shardId().getIndex());
IndexShard indexShard = indexService.shardSafe(request.shardId().id()); IndexShard indexShard = indexService.shardSafe(shardRouting.shardId().id());
// if we don't have the routing entry yet, we need it stats wise, we treat it as if the shard is not ready yet // if we don't have the routing entry yet, we need it stats wise, we treat it as if the shard is not ready yet
if (indexShard.routingEntry() == null) { if (indexShard.routingEntry() == null) {
throw new ShardNotFoundException(indexShard.shardId()); throw new ShardNotFoundException(indexShard.shardId());
@ -128,92 +103,65 @@ public class TransportIndicesStatsAction extends TransportBroadcastAction<Indice
CommonStatsFlags flags = new CommonStatsFlags().clear(); CommonStatsFlags flags = new CommonStatsFlags().clear();
if (request.request.docs()) { if (request.docs()) {
flags.set(CommonStatsFlags.Flag.Docs); flags.set(CommonStatsFlags.Flag.Docs);
} }
if (request.request.store()) { if (request.store()) {
flags.set(CommonStatsFlags.Flag.Store); flags.set(CommonStatsFlags.Flag.Store);
} }
if (request.request.indexing()) { if (request.indexing()) {
flags.set(CommonStatsFlags.Flag.Indexing); flags.set(CommonStatsFlags.Flag.Indexing);
flags.types(request.request.types()); flags.types(request.types());
} }
if (request.request.get()) { if (request.get()) {
flags.set(CommonStatsFlags.Flag.Get); flags.set(CommonStatsFlags.Flag.Get);
} }
if (request.request.search()) { if (request.search()) {
flags.set(CommonStatsFlags.Flag.Search); flags.set(CommonStatsFlags.Flag.Search);
flags.groups(request.request.groups()); flags.groups(request.groups());
} }
if (request.request.merge()) { if (request.merge()) {
flags.set(CommonStatsFlags.Flag.Merge); flags.set(CommonStatsFlags.Flag.Merge);
} }
if (request.request.refresh()) { if (request.refresh()) {
flags.set(CommonStatsFlags.Flag.Refresh); flags.set(CommonStatsFlags.Flag.Refresh);
} }
if (request.request.flush()) { if (request.flush()) {
flags.set(CommonStatsFlags.Flag.Flush); flags.set(CommonStatsFlags.Flag.Flush);
} }
if (request.request.warmer()) { if (request.warmer()) {
flags.set(CommonStatsFlags.Flag.Warmer); flags.set(CommonStatsFlags.Flag.Warmer);
} }
if (request.request.queryCache()) { if (request.queryCache()) {
flags.set(CommonStatsFlags.Flag.QueryCache); flags.set(CommonStatsFlags.Flag.QueryCache);
} }
if (request.request.fieldData()) { if (request.fieldData()) {
flags.set(CommonStatsFlags.Flag.FieldData); flags.set(CommonStatsFlags.Flag.FieldData);
flags.fieldDataFields(request.request.fieldDataFields()); flags.fieldDataFields(request.fieldDataFields());
} }
if (request.request.percolate()) { if (request.percolate()) {
flags.set(CommonStatsFlags.Flag.Percolate); flags.set(CommonStatsFlags.Flag.Percolate);
} }
if (request.request.segments()) { if (request.segments()) {
flags.set(CommonStatsFlags.Flag.Segments); flags.set(CommonStatsFlags.Flag.Segments);
} }
if (request.request.completion()) { if (request.completion()) {
flags.set(CommonStatsFlags.Flag.Completion); flags.set(CommonStatsFlags.Flag.Completion);
flags.completionDataFields(request.request.completionFields()); flags.completionDataFields(request.completionFields());
} }
if (request.request.translog()) { if (request.translog()) {
flags.set(CommonStatsFlags.Flag.Translog); flags.set(CommonStatsFlags.Flag.Translog);
} }
if (request.request.suggest()) { if (request.suggest()) {
flags.set(CommonStatsFlags.Flag.Suggest); flags.set(CommonStatsFlags.Flag.Suggest);
} }
if (request.request.requestCache()) { if (request.requestCache()) {
flags.set(CommonStatsFlags.Flag.RequestCache); flags.set(CommonStatsFlags.Flag.RequestCache);
} }
if (request.request.recovery()) { if (request.recovery()) {
flags.set(CommonStatsFlags.Flag.Recovery); flags.set(CommonStatsFlags.Flag.Recovery);
} }
return new ShardStats(indexShard, flags); return new ShardStats(indexShard, flags);
} }
static class IndexShardStatsRequest extends BroadcastShardRequest {
// TODO if there are many indices, the request might hold a large indices array..., we don't really need to serialize it
IndicesStatsRequest request;
IndexShardStatsRequest() {
}
IndexShardStatsRequest(ShardId shardId, IndicesStatsRequest request) {
super(shardId, request);
this.request = request;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
request = new IndicesStatsRequest();
request.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
request.writeTo(out);
}
}
} }

View File

@ -22,35 +22,31 @@ package org.elasticsearch.action.admin.indices.upgrade.get;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.action.support.broadcast.TransportBroadcastAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.engine.Segment; import org.elasticsearch.index.engine.Segment;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import java.util.ArrayList; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/** /**
* *
*/ */
public class TransportUpgradeStatusAction extends TransportBroadcastAction<UpgradeStatusRequest, UpgradeStatusResponse, TransportUpgradeStatusAction.IndexShardUpgradeStatusRequest, ShardUpgradeStatus> { public class TransportUpgradeStatusAction extends TransportBroadcastByNodeAction<UpgradeStatusRequest, UpgradeStatusResponse, ShardUpgradeStatus> {
private final IndicesService indicesService; private final IndicesService indicesService;
@ -58,7 +54,7 @@ public class TransportUpgradeStatusAction extends TransportBroadcastAction<Upgra
public TransportUpgradeStatusAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, public TransportUpgradeStatusAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService,
IndicesService indicesService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { IndicesService indicesService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, UpgradeStatusAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, super(settings, UpgradeStatusAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
UpgradeStatusRequest.class, IndexShardUpgradeStatusRequest.class, ThreadPool.Names.MANAGEMENT); UpgradeStatusRequest.class, ThreadPool.Names.MANAGEMENT);
this.indicesService = indicesService; this.indicesService = indicesService;
} }
@ -66,8 +62,8 @@ public class TransportUpgradeStatusAction extends TransportBroadcastAction<Upgra
* Getting upgrade stats from *all* active shards. * Getting upgrade stats from *all* active shards.
*/ */
@Override @Override
protected GroupShardsIterator shards(ClusterState clusterState, UpgradeStatusRequest request, String[] concreteIndices) { protected ShardsIterator shards(ClusterState clusterState, UpgradeStatusRequest request, String[] concreteIndices) {
return clusterState.routingTable().allActiveShardsGrouped(concreteIndices, true); return clusterState.routingTable().allShards(concreteIndices);
} }
@Override @Override
@ -81,43 +77,26 @@ public class TransportUpgradeStatusAction extends TransportBroadcastAction<Upgra
} }
@Override @Override
protected UpgradeStatusResponse newResponse(UpgradeStatusRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { protected ShardUpgradeStatus readShardResult(StreamInput in) throws IOException {
int successfulShards = 0; return ShardUpgradeStatus.readShardUpgradeStatus(in);
int failedShards = 0;
List<ShardOperationFailedException> shardFailures = null;
final List<ShardUpgradeStatus> shards = new ArrayList<>();
for (int i = 0; i < shardsResponses.length(); i++) {
Object shardResponse = shardsResponses.get(i);
if (shardResponse == null) {
// simply ignore non active shards
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
failedShards++;
if (shardFailures == null) {
shardFailures = new ArrayList<>();
}
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
} else {
shards.add((ShardUpgradeStatus) shardResponse);
successfulShards++;
}
}
return new UpgradeStatusResponse(shards.toArray(new ShardUpgradeStatus[shards.size()]), shardsResponses.length(), successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected IndexShardUpgradeStatusRequest newShardRequest(int numShards, ShardRouting shard, UpgradeStatusRequest request) { protected UpgradeStatusResponse newResponse(UpgradeStatusRequest request, int totalShards, int successfulShards, int failedShards, List<ShardUpgradeStatus> responses, List<ShardOperationFailedException> shardFailures) {
return new IndexShardUpgradeStatusRequest(shard.shardId(), request); return new UpgradeStatusResponse(responses.toArray(new ShardUpgradeStatus[responses.size()]), totalShards, successfulShards, failedShards, shardFailures);
} }
@Override @Override
protected ShardUpgradeStatus newShardResponse() { protected UpgradeStatusRequest readRequestFrom(StreamInput in) throws IOException {
return new ShardUpgradeStatus(); UpgradeStatusRequest request = new UpgradeStatusRequest();
request.readFrom(in);
return request;
} }
@Override @Override
protected ShardUpgradeStatus shardOperation(IndexShardUpgradeStatusRequest request) { protected ShardUpgradeStatus shardOperation(UpgradeStatusRequest request, ShardRouting shardRouting) {
IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex()); IndexService indexService = indicesService.indexServiceSafe(shardRouting.shardId().getIndex());
IndexShard indexShard = indexService.shardSafe(request.shardId().id()); IndexShard indexShard = indexService.shardSafe(shardRouting.shardId().id());
List<Segment> segments = indexShard.engine().segments(false); List<Segment> segments = indexShard.engine().segments(false);
long total_bytes = 0; long total_bytes = 0;
long to_upgrade_bytes = 0; long to_upgrade_bytes = 0;
@ -136,16 +115,4 @@ public class TransportUpgradeStatusAction extends TransportBroadcastAction<Upgra
return new ShardUpgradeStatus(indexShard.routingEntry(), total_bytes, to_upgrade_bytes, to_upgrade_bytes_ancient); return new ShardUpgradeStatus(indexShard.routingEntry(), total_bytes, to_upgrade_bytes, to_upgrade_bytes_ancient);
} }
static class IndexShardUpgradeStatusRequest extends BroadcastShardRequest {
IndexShardUpgradeStatusRequest() {
}
IndexShardUpgradeStatusRequest(ShardId shardId, UpgradeStatusRequest request) {
super(shardId, request);
}
}
} }

View File

@ -21,10 +21,6 @@ package org.elasticsearch.action.admin.indices.upgrade.get;
import org.elasticsearch.action.support.broadcast.BroadcastRequest; import org.elasticsearch.action.support.broadcast.BroadcastRequest;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
public class UpgradeStatusRequest extends BroadcastRequest<UpgradeStatusRequest> { public class UpgradeStatusRequest extends BroadcastRequest<UpgradeStatusRequest> {

View File

@ -36,14 +36,11 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class UpgradeStatusResponse extends BroadcastResponse implements ToXContent { public class UpgradeStatusResponse extends BroadcastResponse implements ToXContent {
private ShardUpgradeStatus[] shards; private ShardUpgradeStatus[] shards;
private Map<String, IndexUpgradeStatus> indicesUpgradeStatus; private Map<String, IndexUpgradeStatus> indicesUpgradeStatus;
UpgradeStatusResponse() { UpgradeStatusResponse() {
} }
UpgradeStatusResponse(ShardUpgradeStatus[] shards, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) { UpgradeStatusResponse(ShardUpgradeStatus[] shards, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
@ -75,7 +72,6 @@ public class UpgradeStatusResponse extends BroadcastResponse implements ToXConte
return indicesUpgradeStats; return indicesUpgradeStats;
} }
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in); super.readFrom(in);
@ -120,8 +116,6 @@ public class UpgradeStatusResponse extends BroadcastResponse implements ToXConte
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.byteSizeField(Fields.SIZE_IN_BYTES, Fields.SIZE, getTotalBytes()); builder.byteSizeField(Fields.SIZE_IN_BYTES, Fields.SIZE, getTotalBytes());
builder.byteSizeField(Fields.SIZE_TO_UPGRADE_IN_BYTES, Fields.SIZE_TO_UPGRADE, getToUpgradeBytes()); builder.byteSizeField(Fields.SIZE_TO_UPGRADE_IN_BYTES, Fields.SIZE_TO_UPGRADE, getToUpgradeBytes());
builder.byteSizeField(Fields.SIZE_TO_UPGRADE_ANCIENT_IN_BYTES, Fields.SIZE_TO_UPGRADE_ANCIENT, getToUpgradeBytesAncient()); builder.byteSizeField(Fields.SIZE_TO_UPGRADE_ANCIENT_IN_BYTES, Fields.SIZE_TO_UPGRADE_ANCIENT, getToUpgradeBytesAncient());
@ -163,10 +157,8 @@ public class UpgradeStatusResponse extends BroadcastResponse implements ToXConte
} }
builder.endObject(); builder.endObject();
} }
builder.endObject(); builder.endObject();
} }
builder.endObject(); builder.endObject();
} }
return builder; return builder;
@ -186,6 +178,5 @@ public class UpgradeStatusResponse extends BroadcastResponse implements ToXConte
static final XContentBuilderString SIZE_TO_UPGRADE_ANCIENT = new XContentBuilderString("size_to_upgrade_ancient"); static final XContentBuilderString SIZE_TO_UPGRADE_ANCIENT = new XContentBuilderString("size_to_upgrade_ancient");
static final XContentBuilderString SIZE_TO_UPGRADE_IN_BYTES = new XContentBuilderString("size_to_upgrade_in_bytes"); static final XContentBuilderString SIZE_TO_UPGRADE_IN_BYTES = new XContentBuilderString("size_to_upgrade_in_bytes");
static final XContentBuilderString SIZE_TO_UPGRADE_ANCIENT_IN_BYTES = new XContentBuilderString("size_to_upgrade_ancient_in_bytes"); static final XContentBuilderString SIZE_TO_UPGRADE_ANCIENT_IN_BYTES = new XContentBuilderString("size_to_upgrade_ancient_in_bytes");
} }
} }

View File

@ -0,0 +1,562 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.support.broadcast.node;
import com.google.common.collect.Maps;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.FailedNodeException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.NoShardAvailableActionException;
import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
import org.elasticsearch.action.support.HandledTransportAction;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.TransportActions;
import org.elasticsearch.action.support.broadcast.BroadcastRequest;
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.BaseTransportResponseHandler;
import org.elasticsearch.transport.NodeShouldNotConnectException;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestHandler;
import org.elasticsearch.transport.TransportResponse;
import org.elasticsearch.transport.TransportService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Abstraction for transporting aggregated shard-level operations in a single request (NodeRequest) per-node
* and executing the shard-level operations serially on the receiving node. Each shard-level operation can produce a
* result (ShardOperationResult), these per-node shard-level results are aggregated into a single result
* (BroadcastByNodeResponse) to the coordinating node. These per-node results are aggregated into a single result (Result)
* to the client.
*
* @param <Request> the underlying client request
* @param <Response> the response to the client request
* @param <ShardOperationResult> per-shard operation results
*/
public abstract class TransportBroadcastByNodeAction<Request extends BroadcastRequest,
Response extends BroadcastResponse,
ShardOperationResult extends Streamable> extends HandledTransportAction<Request, Response> {
private final ClusterService clusterService;
private final TransportService transportService;
final String transportNodeBroadcastAction;
public TransportBroadcastByNodeAction(
Settings settings,
String actionName,
ThreadPool threadPool,
ClusterService clusterService,
TransportService transportService,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
Class<Request> request,
String executor) {
super(settings, actionName, threadPool, transportService, actionFilters, indexNameExpressionResolver, request);
this.clusterService = clusterService;
this.transportService = transportService;
transportNodeBroadcastAction = actionName + "[n]";
transportService.registerRequestHandler(transportNodeBroadcastAction, new Callable<NodeRequest>() {
@Override
public NodeRequest call() throws Exception {
return new NodeRequest();
}
}, executor, new BroadcastByNodeTransportRequestHandler());
}
private final Response newResponse(Request request, AtomicReferenceArray responses, List<NoShardAvailableActionException> unavailableShardExceptions, Map<String, List<ShardRouting>> nodes) {
int totalShards = 0;
int successfulShards = 0;
List<ShardOperationResult> broadcastByNodeResponses = new ArrayList<>();
List<ShardOperationFailedException> exceptions = new ArrayList<>();
for (int i = 0; i < responses.length(); i++) {
if (responses.get(i) instanceof FailedNodeException) {
FailedNodeException exception = (FailedNodeException) responses.get(i);
totalShards += nodes.get(exception.nodeId()).size();
for (ShardRouting shard : nodes.get(exception.nodeId())) {
exceptions.add(new DefaultShardOperationFailedException(shard.getIndex(), shard.getId(), exception));
}
} else {
NodeResponse response = (NodeResponse) responses.get(i);
broadcastByNodeResponses.addAll(response.results);
totalShards += response.getTotalShards();
successfulShards += response.getSuccessfulShards();
for (BroadcastShardOperationFailedException throwable : response.getExceptions()) {
if (!TransportActions.isShardNotAvailableException(throwable)) {
exceptions.add(new DefaultShardOperationFailedException(throwable.getIndex(), throwable.getShardId().getId(), throwable));
}
}
}
}
totalShards += unavailableShardExceptions.size();
int failedShards = exceptions.size();
return newResponse(request, totalShards, successfulShards, failedShards, broadcastByNodeResponses, exceptions);
}
/**
* Deserialize a shard-level result from an input stream
*
* @param in input stream
* @return a deserialized shard-level result
* @throws IOException
*/
protected abstract ShardOperationResult readShardResult(StreamInput in) throws IOException;
/**
* Creates a new response to the underlying request.
*
* @param request the underlying request
* @param totalShards the total number of shards considered for execution of the operation
* @param successfulShards the total number of shards for which execution of the operation was successful
* @param failedShards the total number of shards for which execution of the operation failed
* @param results the per-node aggregated shard-level results
* @param shardFailures the exceptions corresponding to shard operationa failures
* @return the response
*/
protected abstract Response newResponse(Request request, int totalShards, int successfulShards, int failedShards, List<ShardOperationResult> results, List<ShardOperationFailedException> shardFailures);
/**
* Deserialize a request from an input stream
*
* @param in input stream
* @return a de-serialized request
* @throws IOException
*/
protected abstract Request readRequestFrom(StreamInput in) throws IOException;
/**
* Executes the shard-level operation. This method is called once per shard serially on the receiving node.
*
* @param request the node-level request
* @param shardRouting the shard on which to execute the operation
* @return the result of the shard-level operation for the shard
*/
protected abstract ShardOperationResult shardOperation(Request request, ShardRouting shardRouting);
/**
* Determines the shards on which this operation will be executed on. The operation is executed once per shard.
*
* @param clusterState the cluster state
* @param request the underlying request
* @param concreteIndices the concrete indices on which to execute the operation
* @return the shards on which to execute the operation
*/
protected abstract ShardsIterator shards(ClusterState clusterState, Request request, String[] concreteIndices);
/**
* Executes a global block check before polling the cluster state.
*
* @param state the cluster state
* @param request the underlying request
* @return a non-null exception if the operation is blocked
*/
protected abstract ClusterBlockException checkGlobalBlock(ClusterState state, Request request);
/**
* Executes a global request-level check before polling the cluster state.
*
* @param state the cluster state
* @param request the underlying request
* @param concreteIndices the concrete indices on which to execute the operation
* @return a non-null exception if the operation if blocked
*/
protected abstract ClusterBlockException checkRequestBlock(ClusterState state, Request request, String[] concreteIndices);
@Override
protected void doExecute(Request request, ActionListener<Response> listener) {
new AsyncAction(request, listener).start();
}
protected class AsyncAction {
private final Request request;
private final ActionListener<Response> listener;
private final ClusterState clusterState;
private final DiscoveryNodes nodes;
private final Map<String, List<ShardRouting>> nodeIds;
private final AtomicReferenceArray<Object> responses;
private final AtomicInteger counter = new AtomicInteger();
private List<NoShardAvailableActionException> unavailableShardExceptions = new ArrayList<>();
protected AsyncAction(Request request, ActionListener<Response> listener) {
this.request = request;
this.listener = listener;
clusterState = clusterService.state();
nodes = clusterState.nodes();
ClusterBlockException globalBlockException = checkGlobalBlock(clusterState, request);
if (globalBlockException != null) {
throw globalBlockException;
}
String[] concreteIndices = indexNameExpressionResolver.concreteIndices(clusterState, request);
ClusterBlockException requestBlockException = checkRequestBlock(clusterState, request, concreteIndices);
if (requestBlockException != null) {
throw requestBlockException;
}
logger.trace("resolving shards for [{}] based on cluster state version [{}]", actionName, clusterState.version());
ShardsIterator shardIt = shards(clusterState, request, concreteIndices);
nodeIds = Maps.newHashMap();
for (ShardRouting shard : shardIt.asUnordered()) {
if (shard.assignedToNode()) {
String nodeId = shard.currentNodeId();
if (!nodeIds.containsKey(nodeId)) {
nodeIds.put(nodeId, new ArrayList<ShardRouting>());
}
nodeIds.get(nodeId).add(shard);
} else {
unavailableShardExceptions.add(
new NoShardAvailableActionException(
shard.shardId(),
" no shards available for shard " + shard.toString() + " while executing " + actionName
)
);
}
}
responses = new AtomicReferenceArray<>(nodeIds.size());
}
public void start() {
if (nodeIds.size() == 0) {
try {
onCompletion();
} catch (Throwable e) {
listener.onFailure(e);
}
} else {
int nodeIndex = -1;
for (Map.Entry<String, List<ShardRouting>> entry : nodeIds.entrySet()) {
nodeIndex++;
DiscoveryNode node = nodes.get(entry.getKey());
sendNodeRequest(node, entry.getValue(), nodeIndex);
}
}
}
private void sendNodeRequest(final DiscoveryNode node, List<ShardRouting> shards, final int nodeIndex) {
try {
NodeRequest nodeRequest = new NodeRequest(node.getId(), request, shards);
transportService.sendRequest(node, transportNodeBroadcastAction, nodeRequest, new BaseTransportResponseHandler<NodeResponse>() {
@Override
public NodeResponse newInstance() {
return new NodeResponse();
}
@Override
public void handleResponse(NodeResponse response) {
onNodeResponse(node, nodeIndex, response);
}
@Override
public void handleException(TransportException exp) {
onNodeFailure(node, nodeIndex, exp);
}
@Override
public String executor() {
return ThreadPool.Names.SAME;
}
});
} catch (Throwable e) {
onNodeFailure(node, nodeIndex, e);
}
}
protected void onNodeResponse(DiscoveryNode node, int nodeIndex, NodeResponse response) {
logger.trace("received response for [{}] from node [{}]", actionName, node.id());
// this is defensive to protect against the possibility of double invocation
// the current implementation of TransportService#sendRequest guards against this
// but concurrency is hard, safety is important, and the small performance loss here does not matter
if (responses.compareAndSet(nodeIndex, null, response)) {
if (counter.incrementAndGet() == responses.length()) {
onCompletion();
}
}
}
protected void onNodeFailure(DiscoveryNode node, int nodeIndex, Throwable t) {
String nodeId = node.id();
if (logger.isDebugEnabled() && !(t instanceof NodeShouldNotConnectException)) {
logger.debug("failed to execute [{}] on node [{}]", t, actionName, nodeId);
}
// this is defensive to protect against the possibility of double invocation
// the current implementation of TransportService#sendRequest guards against this
// but concurrency is hard, safety is important, and the small performance loss here does not matter
if (responses.compareAndSet(nodeIndex, null, new FailedNodeException(nodeId, "Failed node [" + nodeId + "]", t))) {
if (counter.incrementAndGet() == responses.length()) {
onCompletion();
}
}
}
protected void onCompletion() {
Response response = null;
try {
response = newResponse(request, responses, unavailableShardExceptions, nodeIds);
} catch (Throwable t) {
logger.debug("failed to combine responses from nodes", t);
listener.onFailure(t);
}
if (response != null) {
try {
listener.onResponse(response);
} catch (Throwable t) {
listener.onFailure(t);
}
}
}
}
class BroadcastByNodeTransportRequestHandler implements TransportRequestHandler<NodeRequest> {
@Override
public void messageReceived(final NodeRequest request, TransportChannel channel) throws Exception {
List<ShardRouting> shards = request.getShards();
final int totalShards = shards.size();
logger.trace("[{}] executing operation on [{}] shards", actionName, totalShards);
final Object[] shardResultOrExceptions = new Object[totalShards];
int shardIndex = -1;
for (final ShardRouting shardRouting : shards) {
shardIndex++;
onShardOperation(request, shardResultOrExceptions, shardIndex, shardRouting);
}
List<BroadcastShardOperationFailedException> accumulatedExceptions = new ArrayList<>();
List<ShardOperationResult> results = new ArrayList<>();
for (int i = 0; i < totalShards; i++) {
if (shardResultOrExceptions[i] instanceof BroadcastShardOperationFailedException) {
accumulatedExceptions.add((BroadcastShardOperationFailedException) shardResultOrExceptions[i]);
} else {
results.add((ShardOperationResult) shardResultOrExceptions[i]);
}
}
channel.sendResponse(new NodeResponse(request.getNodeId(), totalShards, results, accumulatedExceptions));
}
private void onShardOperation(final NodeRequest request, final Object[] shardResults, final int shardIndex, final ShardRouting shardRouting) {
try {
logger.trace("[{}] executing operation for shard [{}]", actionName, shardRouting.shortSummary());
ShardOperationResult result = shardOperation(request.indicesLevelRequest, shardRouting);
shardResults[shardIndex] = result;
logger.trace("[{}] completed operation for shard [{}]", actionName, shardRouting.shortSummary());
} catch (Throwable t) {
BroadcastShardOperationFailedException e = new BroadcastShardOperationFailedException(shardRouting.shardId(), "operation " + actionName + " failed", t);
e.setIndex(shardRouting.getIndex());
e.setShard(shardRouting.shardId());
shardResults[shardIndex] = e;
logger.debug("[{}] failed to execute operation for shard [{}]", e, actionName, shardRouting.shortSummary());
}
}
}
protected class NodeRequest extends TransportRequest implements IndicesRequest {
private String nodeId;
private List<ShardRouting> shards;
protected Request indicesLevelRequest;
protected NodeRequest() {
}
@SuppressForbidden(reason = "debug")
public NodeRequest(String nodeId, Request request, List<ShardRouting> shards) {
super(request);
this.indicesLevelRequest = request;
this.shards = shards;
this.nodeId = nodeId;
System.out.println(TransportBroadcastByNodeAction.this.getClass().getName());
}
public List<ShardRouting> getShards() {
return shards;
}
public String getNodeId() {
return nodeId;
}
public String[] indices() {
return indicesLevelRequest.indices();
}
public IndicesOptions indicesOptions() {
return indicesLevelRequest.indicesOptions();
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
indicesLevelRequest = readRequestFrom(in);
int size = in.readVInt();
shards = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
shards.add(ShardRouting.readShardRoutingEntry(in));
}
nodeId = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
indicesLevelRequest.writeTo(out);
int size = shards.size();
out.writeVInt(size);
for (int i = 0; i < size; i++) {
shards.get(i).writeTo(out);
}
out.writeString(nodeId);
}
}
class NodeResponse extends TransportResponse {
protected String nodeId;
protected int totalShards;
protected List<BroadcastShardOperationFailedException> exceptions;
protected List<ShardOperationResult> results;
public NodeResponse() {
}
public NodeResponse(String nodeId,
int totalShards,
List<ShardOperationResult> results,
List<BroadcastShardOperationFailedException> exceptions) {
this.nodeId = nodeId;
this.totalShards = totalShards;
this.results = results;
this.exceptions = exceptions;
}
public String getNodeId() {
return nodeId;
}
public int getTotalShards() {
return totalShards;
}
public int getSuccessfulShards() {
return results.size();
}
public List<BroadcastShardOperationFailedException> getExceptions() {
return exceptions;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
nodeId = in.readString();
totalShards = in.readVInt();
int resultsSize = in.readVInt();
results = new ArrayList<>(resultsSize);
for (; resultsSize > 0; resultsSize--) {
final ShardOperationResult result = in.readBoolean() ? readShardResult(in) : null;
results.add(result);
}
if (in.readBoolean()) {
int failureShards = in.readVInt();
exceptions = new ArrayList<>(failureShards);
for (int i = 0; i < failureShards; i++) {
exceptions.add(new BroadcastShardOperationFailedException(in));
}
} else {
exceptions = null;
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(nodeId);
out.writeVInt(totalShards);
out.writeVInt(results.size());
for (ShardOperationResult result : results) {
out.writeOptionalStreamable(result);
}
out.writeBoolean(exceptions != null);
if (exceptions != null) {
int failureShards = exceptions.size();
out.writeVInt(failureShards);
for (int i = 0; i < failureShards; i++) {
exceptions.get(i).writeTo(out);
}
}
}
}
/**
* Can be used for implementations of {@link #shardOperation(BroadcastRequest, ShardRouting) shardOperation} for
* which there is no shard-level return value.
*/
public final static class EmptyResult implements Streamable {
public static EmptyResult INSTANCE = new EmptyResult();
private EmptyResult() {
}
@Override
public void readFrom(StreamInput in) throws IOException {
}
@Override
public void writeTo(StreamOutput out) throws IOException {
}
public static EmptyResult readEmptyResultFrom(StreamInput in) {
return INSTANCE;
}
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.cluster.routing;
import com.carrotsearch.hppc.IntSet; import com.carrotsearch.hppc.IntSet;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.UnmodifiableIterator; import com.google.common.collect.UnmodifiableIterator;
@ -223,6 +224,38 @@ public class RoutingTable implements Iterable<IndexRoutingTable>, Diffable<Routi
return new GroupShardsIterator(set); return new GroupShardsIterator(set);
} }
public ShardsIterator allShards(String[] indices) {
return allShardsSatisfyingPredicate(indices, Predicates.<ShardRouting>alwaysTrue(), false);
}
public ShardsIterator allShardsIncludingRelocationTargets(String[] indices) {
return allShardsSatisfyingPredicate(indices, Predicates.<ShardRouting>alwaysTrue(), true);
}
// TODO: replace with JDK 8 native java.util.function.Predicate
private ShardsIterator allShardsSatisfyingPredicate(String[] indices, Predicate<ShardRouting> predicate, boolean includeRelocationTargets) {
// use list here since we need to maintain identity across shards
List<ShardRouting> shards = new ArrayList<>();
for (String index : indices) {
IndexRoutingTable indexRoutingTable = index(index);
if (indexRoutingTable == null) {
continue;
// we simply ignore indices that don't exists (make sense for operations that use it currently)
}
for (IndexShardRoutingTable indexShardRoutingTable : indexRoutingTable) {
for (ShardRouting shardRouting : indexShardRoutingTable) {
if (predicate.apply(shardRouting)) {
shards.add(shardRouting);
if (includeRelocationTargets && shardRouting.relocating()) {
shards.add(shardRouting.buildTargetRelocatingShard());
}
}
}
}
}
return new PlainShardsIterator(shards);
}
/** /**
* All the *active* primary shards for the provided indices grouped (each group is a single element, consisting * All the *active* primary shards for the provided indices grouped (each group is a single element, consisting
* of the primary shard). This is handy for components that expect to get group iterators, but still want in some * of the primary shard). This is handy for components that expect to get group iterators, but still want in some

View File

@ -22,7 +22,6 @@ package org.elasticsearch.rest.action.cat;
import org.apache.lucene.util.CollectionUtil; import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest; import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest;
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
@ -116,19 +115,19 @@ public class RestRecoveryAction extends AbstractCatAction {
Table t = getTableWithHeader(request); Table t = getTableWithHeader(request);
for (String index : response.shardResponses().keySet()) { for (String index : response.shardRecoveryStates().keySet()) {
List<ShardRecoveryResponse> shardRecoveryResponses = response.shardResponses().get(index); List<RecoveryState> shardRecoveryStates = response.shardRecoveryStates().get(index);
if (shardRecoveryResponses.size() == 0) { if (shardRecoveryStates.size() == 0) {
continue; continue;
} }
// Sort ascending by shard id for readability // Sort ascending by shard id for readability
CollectionUtil.introSort(shardRecoveryResponses, new Comparator<ShardRecoveryResponse>() { CollectionUtil.introSort(shardRecoveryStates, new Comparator<RecoveryState>() {
@Override @Override
public int compare(ShardRecoveryResponse o1, ShardRecoveryResponse o2) { public int compare(RecoveryState o1, RecoveryState o2) {
int id1 = o1.recoveryState().getShardId().id(); int id1 = o1.getShardId().id();
int id2 = o2.recoveryState().getShardId().id(); int id2 = o2.getShardId().id();
if (id1 < id2) { if (id1 < id2) {
return -1; return -1;
} else if (id1 > id2) { } else if (id1 > id2) {
@ -139,12 +138,10 @@ public class RestRecoveryAction extends AbstractCatAction {
} }
}); });
for (ShardRecoveryResponse shardResponse : shardRecoveryResponses) { for (RecoveryState state: shardRecoveryStates) {
RecoveryState state = shardResponse.recoveryState();
t.startRow(); t.startRow();
t.addCell(index); t.addCell(index);
t.addCell(shardResponse.getShardId()); t.addCell(state.getShardId().id());
t.addCell(state.getTimer().time()); t.addCell(state.getTimer().time());
t.addCell(state.getType().toString().toLowerCase(Locale.ROOT)); t.addCell(state.getType().toString().toLowerCase(Locale.ROOT));
t.addCell(state.getStage().toString().toLowerCase(Locale.ROOT)); t.addCell(state.getStage().toString().toLowerCase(Locale.ROOT));

View File

@ -21,7 +21,11 @@ package org.elasticsearch.rest.action.cat;
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
import org.elasticsearch.action.admin.indices.segments.*; import org.elasticsearch.action.admin.indices.segments.IndexSegments;
import org.elasticsearch.action.admin.indices.segments.IndexShardSegments;
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentResponse;
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsRequest;
import org.elasticsearch.action.admin.indices.segments.ShardSegments;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
@ -29,7 +33,10 @@ import org.elasticsearch.common.Table;
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.index.engine.Segment; import org.elasticsearch.index.engine.Segment;
import org.elasticsearch.rest.*; import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.action.support.RestActionListener; import org.elasticsearch.rest.action.support.RestActionListener;
import org.elasticsearch.rest.action.support.RestResponseListener; import org.elasticsearch.rest.action.support.RestResponseListener;
import org.elasticsearch.rest.action.support.RestTable; import org.elasticsearch.rest.action.support.RestTable;
@ -120,8 +127,8 @@ public class RestSegmentsAction extends AbstractCatAction {
for (Segment segment : segments) { for (Segment segment : segments) {
table.startRow(); table.startRow();
table.addCell(shardSegment.getIndex()); table.addCell(shardSegment.getShardRouting().getIndex());
table.addCell(shardSegment.getShardId()); table.addCell(shardSegment.getShardRouting().getId());
table.addCell(shardSegment.getShardRouting().primary() ? "p" : "r"); table.addCell(shardSegment.getShardRouting().primary() ? "p" : "r");
table.addCell(nodes.get(shardSegment.getShardRouting().currentNodeId()).getHostAddress()); table.addCell(nodes.get(shardSegment.getShardRouting().currentNodeId()).getHostAddress());
table.addCell(shardSegment.getShardRouting().currentNodeId()); table.addCell(shardSegment.getShardRouting().currentNodeId());

View File

@ -21,6 +21,7 @@ package org.elasticsearch.transport;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.concurrent.Callable;
/** /**
* *
@ -28,20 +29,19 @@ import java.lang.reflect.Constructor;
public class RequestHandlerRegistry<Request extends TransportRequest> { public class RequestHandlerRegistry<Request extends TransportRequest> {
private final String action; private final String action;
private final Constructor<Request> requestConstructor;
private final TransportRequestHandler<Request> handler; private final TransportRequestHandler<Request> handler;
private final boolean forceExecution; private final boolean forceExecution;
private final String executor; private final String executor;
private final Callable<Request> requestFactory;
RequestHandlerRegistry(String action, Class<Request> request, TransportRequestHandler<Request> handler, RequestHandlerRegistry(String action, Class<Request> request, TransportRequestHandler<Request> handler,
String executor, boolean forceExecution) { String executor, boolean forceExecution) {
this(action, new ReflectionFactory<>(request), handler, executor, forceExecution);
}
public RequestHandlerRegistry(String action, Callable<Request> requestFactory, TransportRequestHandler<Request> handler, String executor, boolean forceExecution) {
this.action = action; this.action = action;
try { this.requestFactory = requestFactory;
this.requestConstructor = request.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalStateException("failed to create constructor (does it have a default constructor?) for request " + request, e);
}
this.requestConstructor.setAccessible(true);
assert newRequest() != null; assert newRequest() != null;
this.handler = handler; this.handler = handler;
this.forceExecution = forceExecution; this.forceExecution = forceExecution;
@ -54,7 +54,7 @@ public class RequestHandlerRegistry<Request extends TransportRequest> {
public Request newRequest() { public Request newRequest() {
try { try {
return requestConstructor.newInstance(); return requestFactory.call();
} catch (Exception e) { } catch (Exception e) {
throw new IllegalStateException("failed to instantiate request ", e); throw new IllegalStateException("failed to instantiate request ", e);
} }
@ -71,4 +71,22 @@ public class RequestHandlerRegistry<Request extends TransportRequest> {
public String getExecutor() { public String getExecutor() {
return executor; return executor;
} }
private final static class ReflectionFactory<Request> implements Callable<Request> {
private final Constructor<Request> requestConstructor;
public ReflectionFactory(Class<Request> request) {
try {
this.requestConstructor = request.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalStateException("failed to create constructor (does it have a default constructor?) for request " + request, e);
}
this.requestConstructor.setAccessible(true);
}
@Override
public Request call() throws Exception {
return requestConstructor.newInstance();
}
}
} }

View File

@ -22,8 +22,6 @@ package org.elasticsearch.transport;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.elasticsearch.action.admin.cluster.node.liveness.TransportLivenessAction; import org.elasticsearch.action.admin.cluster.node.liveness.TransportLivenessAction;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.settings.ClusterDynamicSettings;
import org.elasticsearch.cluster.settings.DynamicSettings;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.component.AbstractLifecycleComponent;
@ -35,12 +33,21 @@ import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress; import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.concurrent.*; import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
import org.elasticsearch.common.util.concurrent.ConcurrentMapLong;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.node.settings.NodeSettingsService; import org.elasticsearch.node.settings.NodeSettingsService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -399,6 +406,18 @@ public class TransportService extends AbstractLifecycleComponent<TransportServic
registerRequestHandler(action, request, executor, false, handler); registerRequestHandler(action, request, executor, false, handler);
} }
/**
* Registers a new request handler
* @param action The action the request handler is associated with
* @param requestFactory a callable to be used construct new instances for streaming
* @param executor The executor the request handling will be executed on
* @param handler The handler itself that implements the request handling
*/
public <Request extends TransportRequest> void registerRequestHandler(String action, Callable<Request> requestFactory, String executor, TransportRequestHandler<Request> handler) {
RequestHandlerRegistry<Request> reg = new RequestHandlerRegistry<>(action, requestFactory, handler, executor, false);
registerRequestHandler(reg);
}
/** /**
* Registers a new request handler * Registers a new request handler
* @param action The action the request handler is associated with * @param action The action the request handler is associated with
@ -408,8 +427,12 @@ public class TransportService extends AbstractLifecycleComponent<TransportServic
* @param handler The handler itself that implements the request handling * @param handler The handler itself that implements the request handling
*/ */
public <Request extends TransportRequest> void registerRequestHandler(String action, Class<Request> request, String executor, boolean forceExecution, TransportRequestHandler<Request> handler) { public <Request extends TransportRequest> void registerRequestHandler(String action, Class<Request> request, String executor, boolean forceExecution, TransportRequestHandler<Request> handler) {
RequestHandlerRegistry<Request> reg = new RequestHandlerRegistry<>(action, request, handler, executor, forceExecution);
registerRequestHandler(reg);
}
protected <Request extends TransportRequest> void registerRequestHandler(RequestHandlerRegistry<Request> reg) {
synchronized (requestHandlerMutex) { synchronized (requestHandlerMutex) {
RequestHandlerRegistry<Request> reg = new RequestHandlerRegistry<>(action, request, handler, executor, forceExecution);
RequestHandlerRegistry replaced = requestHandlers.get(reg.getAction()); RequestHandlerRegistry replaced = requestHandlers.get(reg.getAction());
requestHandlers = MapBuilder.newMapBuilder(requestHandlers).put(reg.getAction(), reg).immutableMap(); requestHandlers = MapBuilder.newMapBuilder(requestHandlers).put(reg.getAction(), reg).immutableMap();
if (replaced != null) { if (replaced != null) {

View File

@ -113,6 +113,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
@ -395,7 +396,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
@Test @Test
public void testOptimize() { public void testOptimize() {
String optimizeShardAction = OptimizeAction.NAME + "[s]"; String optimizeShardAction = OptimizeAction.NAME + "[n]";
interceptTransportActions(optimizeShardAction); interceptTransportActions(optimizeShardAction);
OptimizeRequest optimizeRequest = new OptimizeRequest(randomIndicesOrAliases()); OptimizeRequest optimizeRequest = new OptimizeRequest(randomIndicesOrAliases());
@ -419,7 +420,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
@Test @Test
public void testClearCache() { public void testClearCache() {
String clearCacheAction = ClearIndicesCacheAction.NAME + "[s]"; String clearCacheAction = ClearIndicesCacheAction.NAME + "[n]";
interceptTransportActions(clearCacheAction); interceptTransportActions(clearCacheAction);
ClearIndicesCacheRequest clearIndicesCacheRequest = new ClearIndicesCacheRequest(randomIndicesOrAliases()); ClearIndicesCacheRequest clearIndicesCacheRequest = new ClearIndicesCacheRequest(randomIndicesOrAliases());
@ -431,7 +432,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
@Test @Test
public void testRecovery() { public void testRecovery() {
String recoveryAction = RecoveryAction.NAME + "[s]"; String recoveryAction = RecoveryAction.NAME + "[n]";
interceptTransportActions(recoveryAction); interceptTransportActions(recoveryAction);
RecoveryRequest recoveryRequest = new RecoveryRequest(randomIndicesOrAliases()); RecoveryRequest recoveryRequest = new RecoveryRequest(randomIndicesOrAliases());
@ -443,7 +444,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
@Test @Test
public void testSegments() { public void testSegments() {
String segmentsAction = IndicesSegmentsAction.NAME + "[s]"; String segmentsAction = IndicesSegmentsAction.NAME + "[n]";
interceptTransportActions(segmentsAction); interceptTransportActions(segmentsAction);
IndicesSegmentsRequest segmentsRequest = new IndicesSegmentsRequest(randomIndicesOrAliases()); IndicesSegmentsRequest segmentsRequest = new IndicesSegmentsRequest(randomIndicesOrAliases());
@ -455,7 +456,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
@Test @Test
public void testIndicesStats() { public void testIndicesStats() {
String indicesStats = IndicesStatsAction.NAME + "[s]"; String indicesStats = IndicesStatsAction.NAME + "[n]";
interceptTransportActions(indicesStats); interceptTransportActions(indicesStats);
IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest().indices(randomIndicesOrAliases()); IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest().indices(randomIndicesOrAliases());
@ -888,6 +889,11 @@ public class IndicesRequestIT extends ESIntegTestCase {
super.registerRequestHandler(action, request, executor, forceExecution, new InterceptingRequestHandler(action, handler)); super.registerRequestHandler(action, request, executor, forceExecution, new InterceptingRequestHandler(action, handler));
} }
@Override
public <Request extends TransportRequest> void registerRequestHandler(String action, Callable<Request> requestFactory, String executor, TransportRequestHandler<Request> handler) {
super.registerRequestHandler(action, requestFactory, executor, new InterceptingRequestHandler(action, handler));
}
private class InterceptingRequestHandler implements TransportRequestHandler { private class InterceptingRequestHandler implements TransportRequestHandler {
private final TransportRequestHandler requestHandler; private final TransportRequestHandler requestHandler;

View File

@ -0,0 +1,422 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.support.broadcast.node;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.Version;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.action.support.broadcast.BroadcastRequest;
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlock;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.block.ClusterBlocks;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.routing.IndexRoutingTable;
import org.elasticsearch.cluster.routing.IndexShardRoutingTable;
import org.elasticsearch.cluster.routing.RoutingTable;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardRoutingState;
import org.elasticsearch.cluster.routing.ShardsIterator;
import org.elasticsearch.cluster.routing.TestShardRouting;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.DummyTransportAddress;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.cluster.TestClusterService;
import org.elasticsearch.test.transport.CapturingTransport;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportResponse;
import org.elasticsearch.transport.TransportResponseOptions;
import org.elasticsearch.transport.TransportService;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.object.HasToString.hasToString;
public class TransportBroadcastByNodeActionTests extends ESTestCase {
private static final String TEST_INDEX = "test-index";
private static final String TEST_CLUSTER = "test-cluster";
private static ThreadPool THREAD_POOL;
private TestClusterService clusterService;
private CapturingTransport transport;
private TransportService transportService;
private TestTransportBroadcastByNodeAction action;
public static class Request extends BroadcastRequest<Request> {
public Request() {
}
public Request(String[] indices) {
super(indices);
}
}
public static class Response extends BroadcastResponse {
public Response() {
}
public Response(int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
super(totalShards, successfulShards, failedShards, shardFailures);
}
}
class TestTransportBroadcastByNodeAction extends TransportBroadcastByNodeAction<Request, Response, TransportBroadcastByNodeAction.EmptyResult> {
private final Map<ShardRouting, Object> shards = new HashMap<>();
public TestTransportBroadcastByNodeAction(Settings settings, TransportService transportService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver, Class<Request> request, String executor) {
super(settings, "indices:admin/test", THREAD_POOL, TransportBroadcastByNodeActionTests.this.clusterService, transportService, actionFilters, indexNameExpressionResolver, request, executor);
}
@Override
protected EmptyResult readShardResult(StreamInput in) throws IOException {
return EmptyResult.readEmptyResultFrom(in);
}
@Override
protected Response newResponse(Request request, int totalShards, int successfulShards, int failedShards, List<EmptyResult> emptyResults, List<ShardOperationFailedException> shardFailures) {
return new Response(totalShards, successfulShards, failedShards, shardFailures);
}
@Override
protected Request readRequestFrom(StreamInput in) throws IOException {
final Request request = new Request();
request.readFrom(in);
return request;
}
@Override
protected EmptyResult shardOperation(Request request, ShardRouting shardRouting) {
if (rarely()) {
shards.put(shardRouting, Boolean.TRUE);
return EmptyResult.INSTANCE;
} else {
ElasticsearchException e = new ElasticsearchException("operation failed");
shards.put(shardRouting, e);
throw e;
}
}
@Override
protected ShardsIterator shards(ClusterState clusterState, Request request, String[] concreteIndices) {
return clusterState.routingTable().allShards(new String[]{TEST_INDEX});
}
@Override
protected ClusterBlockException checkGlobalBlock(ClusterState state, Request request) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
}
@Override
protected ClusterBlockException checkRequestBlock(ClusterState state, Request request, String[] concreteIndices) {
return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, concreteIndices);
}
public Map<ShardRouting, Object> getResults() {
return shards;
}
}
class MyResolver extends IndexNameExpressionResolver {
public MyResolver() {
super(Settings.EMPTY);
}
@Override
public String[] concreteIndices(ClusterState state, IndicesRequest request) {
return request.indices();
}
}
@BeforeClass
public static void startThreadPool() {
THREAD_POOL = new ThreadPool(TransportBroadcastByNodeActionTests.class.getSimpleName());
}
@Before
public void setUp() throws Exception {
super.setUp();
transport = new CapturingTransport();
clusterService = new TestClusterService(THREAD_POOL);
transportService = new TransportService(transport, THREAD_POOL);
transportService.start();
setClusterState(clusterService, TEST_INDEX);
action = new TestTransportBroadcastByNodeAction(
Settings.EMPTY,
transportService,
new ActionFilters(new HashSet<ActionFilter>()),
new MyResolver(),
Request.class,
ThreadPool.Names.SAME
);
}
void setClusterState(TestClusterService clusterService, String index) {
int numberOfNodes = randomIntBetween(3, 5);
DiscoveryNodes.Builder discoBuilder = DiscoveryNodes.builder();
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
int shardIndex = -1;
for (int i = 0; i < numberOfNodes; i++) {
final DiscoveryNode node = newNode(i);
discoBuilder = discoBuilder.put(node);
int numberOfShards = randomIntBetween(0, 10);
for (int j = 0; j < numberOfShards; j++) {
final ShardId shardId = new ShardId(index, ++shardIndex);
ShardRouting shard = TestShardRouting.newShardRouting(index, shardId.getId(), node.id(), true, ShardRoutingState.STARTED, 1);
IndexShardRoutingTable.Builder indexShard = new IndexShardRoutingTable.Builder(shardId);
indexShard.addShard(shard);
indexRoutingTable.addIndexShard(indexShard.build());
}
}
discoBuilder.localNodeId(newNode(0).id());
discoBuilder.masterNodeId(newNode(numberOfNodes - 1).id());
ClusterState.Builder stateBuilder = ClusterState.builder(new ClusterName(TEST_CLUSTER));
stateBuilder.nodes(discoBuilder);
stateBuilder.routingTable(RoutingTable.builder().add(indexRoutingTable.build()).build());
ClusterState clusterState = stateBuilder.build();
clusterService.setState(clusterState);
}
static DiscoveryNode newNode(int nodeId) {
return new DiscoveryNode("node_" + nodeId, DummyTransportAddress.INSTANCE, Version.CURRENT);
}
@AfterClass
public static void destroyThreadPool() {
ThreadPool.terminate(THREAD_POOL, 30, TimeUnit.SECONDS);
// since static must set to null to be eligible for collection
THREAD_POOL = null;
}
public void testGlobalBlock() {
Request request = new Request(new String[]{TEST_INDEX});
PlainActionFuture<Response> listener = new PlainActionFuture<>();
ClusterBlocks.Builder block = ClusterBlocks.builder()
.addGlobalBlock(new ClusterBlock(1, "", false, true, RestStatus.SERVICE_UNAVAILABLE, ClusterBlockLevel.ALL));
clusterService.setState(ClusterState.builder(clusterService.state()).blocks(block));
try {
action.new AsyncAction(request, listener).start();
fail("expected ClusterBlockException");
} catch (ClusterBlockException expected) {
}
}
public void testRequestBlock() {
Request request = new Request(new String[]{TEST_INDEX});
PlainActionFuture<Response> listener = new PlainActionFuture<>();
ClusterBlocks.Builder block = ClusterBlocks.builder()
.addIndexBlock(TEST_INDEX, new ClusterBlock(1, "test-block", false, true, RestStatus.SERVICE_UNAVAILABLE, ClusterBlockLevel.ALL));
clusterService.setState(ClusterState.builder(clusterService.state()).blocks(block));
try {
action.new AsyncAction(request, listener).start();
fail("expected ClusterBlockException");
} catch (ClusterBlockException expected) {
}
}
public void testOneRequestIsSentToEachNodeHoldingAShard() {
Request request = new Request(new String[]{TEST_INDEX});
PlainActionFuture<Response> listener = new PlainActionFuture<>();
action.new AsyncAction(request, listener).start();
Map<String, List<CapturingTransport.CapturedRequest>> capturedRequests = transport.capturedRequestsByTargetNode();
ShardsIterator shardIt = clusterService.state().routingTable().allShards(new String[]{TEST_INDEX});
Set<String> set = new HashSet<>();
for (ShardRouting shard : shardIt.asUnordered()) {
set.add(shard.currentNodeId());
}
// check a request was sent to the right number of nodes
assertEquals(set.size(), capturedRequests.size());
// check requests were sent to the right nodes
assertEquals(set, capturedRequests.keySet());
for (Map.Entry<String, List<CapturingTransport.CapturedRequest>> entry : capturedRequests.entrySet()) {
// check one request was sent to each node
assertEquals(1, entry.getValue().size());
}
}
public void testOperationExecution() throws Exception {
ShardsIterator shardIt = clusterService.state().routingTable().allShards(new String[]{TEST_INDEX});
Set<ShardRouting> shards = new HashSet<>();
String nodeId = shardIt.asUnordered().iterator().next().currentNodeId();
for (ShardRouting shard : shardIt.asUnordered()) {
if (nodeId.equals(shard.currentNodeId())) {
shards.add(shard);
}
}
final TransportBroadcastByNodeAction.BroadcastByNodeTransportRequestHandler handler =
action.new BroadcastByNodeTransportRequestHandler();
TestTransportChannel channel = new TestTransportChannel();
handler.messageReceived(action.new NodeRequest(nodeId, new Request(), new ArrayList<>(shards)), channel);
// check the operation was executed only on the expected shards
assertEquals(shards, action.getResults().keySet());
TransportResponse response = channel.getCapturedResponse();
assertTrue(response instanceof TransportBroadcastByNodeAction.NodeResponse);
TransportBroadcastByNodeAction.NodeResponse nodeResponse = (TransportBroadcastByNodeAction.NodeResponse)response;
// check the operation was executed on the correct node
assertEquals("node id", nodeId, nodeResponse.getNodeId());
int successfulShards = 0;
int failedShards = 0;
for (Object result : action.getResults().values()) {
if (!(result instanceof ElasticsearchException)) {
successfulShards++;
} else {
failedShards++;
}
}
// check the operation results
assertEquals("successful shards", successfulShards, nodeResponse.getSuccessfulShards());
assertEquals("total shards", action.getResults().size(), nodeResponse.getTotalShards());
assertEquals("failed shards", failedShards, nodeResponse.getExceptions().size());
List<BroadcastShardOperationFailedException> exceptions = nodeResponse.getExceptions();
for (BroadcastShardOperationFailedException exception : exceptions) {
assertThat(exception.getMessage(), is("operation indices:admin/test failed"));
assertThat(exception, hasToString(containsString("operation failed")));
}
}
public void testResultAggregation() throws ExecutionException, InterruptedException {
Request request = new Request(new String[]{TEST_INDEX});
PlainActionFuture<Response> listener = new PlainActionFuture<>();
action.new AsyncAction(request, listener).start();
Map<String, List<CapturingTransport.CapturedRequest>> capturedRequests = transport.capturedRequestsByTargetNode();
transport.clear();
ShardsIterator shardIt = clusterService.state().getRoutingTable().allShards(new String[]{TEST_INDEX});
Map<String, List<ShardRouting>> map = new HashMap<>();
for (ShardRouting shard : shardIt.asUnordered()) {
if (!map.containsKey(shard.currentNodeId())) {
map.put(shard.currentNodeId(), new ArrayList<ShardRouting>());
}
map.get(shard.currentNodeId()).add(shard);
}
int totalShards = 0;
int totalSuccessfulShards = 0;
int totalFailedShards = 0;
for (Map.Entry<String, List<CapturingTransport.CapturedRequest>> entry : capturedRequests.entrySet()) {
List<BroadcastShardOperationFailedException> exceptions = new ArrayList<>();
long requestId = entry.getValue().get(0).requestId;
if (rarely()) {
// simulate node failure
totalShards += map.get(entry.getKey()).size();
totalFailedShards += map.get(entry.getKey()).size();
transport.handleResponse(requestId, new Exception());
} else {
List<ShardRouting> shards = map.get(entry.getKey());
List<TransportBroadcastByNodeAction.EmptyResult> shardResults = new ArrayList<>();
for (ShardRouting shard : shards) {
totalShards++;
if (rarely()) {
// simulate operation failure
totalFailedShards++;
exceptions.add(new BroadcastShardOperationFailedException(shard.shardId(), "operation indices:admin/test failed"));
} else {
shardResults.add(TransportBroadcastByNodeAction.EmptyResult.INSTANCE);
}
}
totalSuccessfulShards += shardResults.size();
TransportBroadcastByNodeAction.NodeResponse nodeResponse = action.new NodeResponse(entry.getKey(), shards.size(), shardResults, exceptions);
transport.handleResponse(requestId, nodeResponse);
}
}
Response response = listener.get();
assertEquals("total shards", totalShards, response.getTotalShards());
assertEquals("successful shards", totalSuccessfulShards, response.getSuccessfulShards());
assertEquals("failed shards", totalFailedShards, response.getFailedShards());
assertEquals("accumulated exceptions", totalFailedShards, response.getShardFailures().length);
}
public class TestTransportChannel implements TransportChannel {
private TransportResponse capturedResponse;
public TransportResponse getCapturedResponse() {
return capturedResponse;
}
@Override
public String action() {
return null;
}
@Override
public String getProfileName() {
return "";
}
@Override
public void sendResponse(TransportResponse response) throws IOException {
capturedResponse = response;
}
@Override
public void sendResponse(TransportResponse response, TransportResponseOptions options) throws IOException {
}
@Override
public void sendResponse(Throwable error) throws IOException {
}
}
}

View File

@ -19,7 +19,6 @@
package org.elasticsearch.benchmark.recovery; package org.elasticsearch.benchmark.recovery;
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.bootstrap.BootstrapForTesting; import org.elasticsearch.bootstrap.BootstrapForTesting;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
@ -30,6 +29,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.SizeValue; import org.elasticsearch.common.unit.SizeValue;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.indices.recovery.RecoveryState;
import org.elasticsearch.node.Node; import org.elasticsearch.node.Node;
import org.elasticsearch.test.BackgroundIndexer; import org.elasticsearch.test.BackgroundIndexer;
import org.elasticsearch.transport.TransportModule; import org.elasticsearch.transport.TransportModule;
@ -128,12 +128,12 @@ public class ReplicaRecoveryBenchmark {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long currentDocs = indexer.totalIndexedDocs(); long currentDocs = indexer.totalIndexedDocs();
RecoveryResponse recoveryResponse = client1.admin().indices().prepareRecoveries(INDEX_NAME).setActiveOnly(true).get(); RecoveryResponse recoveryResponse = client1.admin().indices().prepareRecoveries(INDEX_NAME).setActiveOnly(true).get();
List<ShardRecoveryResponse> indexRecoveries = recoveryResponse.shardResponses().get(INDEX_NAME); List<RecoveryState> indexRecoveries = recoveryResponse.shardRecoveryStates().get(INDEX_NAME);
long translogOps; long translogOps;
long bytes; long bytes;
if (indexRecoveries.size() > 0) { if (indexRecoveries.size() > 0) {
translogOps = indexRecoveries.get(0).recoveryState().getTranslog().recoveredOperations(); translogOps = indexRecoveries.get(0).getTranslog().recoveredOperations();
bytes = recoveryResponse.shardResponses().get(INDEX_NAME).get(0).recoveryState().getIndex().recoveredBytes(); bytes = recoveryResponse.shardRecoveryStates().get(INDEX_NAME).get(0).getIndex().recoveredBytes();
} else { } else {
bytes = lastBytes = 0; bytes = lastBytes = 0;
translogOps = lastTranslogOps = 0; translogOps = lastTranslogOps = 0;

View File

@ -243,4 +243,25 @@ public class RoutingTableTest extends ESAllocationTestCase {
fail("Calling with non-existing index should be ignored at the moment"); fail("Calling with non-existing index should be ignored at the moment");
} }
} }
public void testAllShardsForMultipleIndices() {
assertThat(this.emptyRoutingTable.allShards(new String[0]).size(), is(0));
assertThat(this.testRoutingTable.allShards(new String[]{TEST_INDEX_1}).size(), is(this.shardsPerIndex));
initPrimaries();
assertThat(this.testRoutingTable.allShards(new String[]{TEST_INDEX_1}).size(), is(this.shardsPerIndex));
startInitializingShards(TEST_INDEX_1);
assertThat(this.testRoutingTable.allShards(new String[]{TEST_INDEX_1}).size(), is(this.shardsPerIndex));
startInitializingShards(TEST_INDEX_2);
assertThat(this.testRoutingTable.allShards(new String[]{TEST_INDEX_1, TEST_INDEX_2}).size(), is(this.totalNumberOfShards));
try {
this.testRoutingTable.allShards(new String[]{TEST_INDEX_1, "not_exists"});
} catch (IndexNotFoundException e) {
fail("Calling with non-existing index should be ignored at the moment");
}
}
} }

View File

@ -42,7 +42,11 @@ import org.elasticsearch.discovery.zen.publish.PublishClusterStateAction;
import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.*; import org.elasticsearch.transport.BytesTransportRequest;
import org.elasticsearch.transport.EmptyTransportResponseHandler;
import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportResponse;
import org.elasticsearch.transport.TransportService;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.Test; import org.junit.Test;
@ -112,7 +116,7 @@ public class ZenDiscoveryIT extends ESIntegTestCase {
createIndex("test"); createIndex("test");
ensureSearchable("test"); ensureSearchable("test");
RecoveryResponse r = client().admin().indices().prepareRecoveries("test").get(); RecoveryResponse r = client().admin().indices().prepareRecoveries("test").get();
int numRecoveriesBeforeNewMaster = r.shardResponses().get("test").size(); int numRecoveriesBeforeNewMaster = r.shardRecoveryStates().get("test").size();
final String oldMaster = internalCluster().getMasterName(); final String oldMaster = internalCluster().getMasterName();
internalCluster().stopCurrentMasterNode(); internalCluster().stopCurrentMasterNode();
@ -127,7 +131,7 @@ public class ZenDiscoveryIT extends ESIntegTestCase {
ensureSearchable("test"); ensureSearchable("test");
r = client().admin().indices().prepareRecoveries("test").get(); r = client().admin().indices().prepareRecoveries("test").get();
int numRecoveriesAfterNewMaster = r.shardResponses().get("test").size(); int numRecoveriesAfterNewMaster = r.shardRecoveryStates().get("test").size();
assertThat(numRecoveriesAfterNewMaster, equalTo(numRecoveriesBeforeNewMaster)); assertThat(numRecoveriesAfterNewMaster, equalTo(numRecoveriesBeforeNewMaster));
} }

View File

@ -35,7 +35,10 @@ import org.elasticsearch.test.ESIntegTestCase;
import org.junit.Test; import org.junit.Test;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
/** /**
*/ */
@ -146,7 +149,7 @@ public class ShardInfoIT extends ESIntegTestCase {
RecoveryResponse recoveryResponse = client().admin().indices().prepareRecoveries("idx") RecoveryResponse recoveryResponse = client().admin().indices().prepareRecoveries("idx")
.setActiveOnly(true) .setActiveOnly(true)
.get(); .get();
assertThat(recoveryResponse.shardResponses().get("idx").size(), equalTo(0)); assertThat(recoveryResponse.shardRecoveryStates().get("idx").size(), equalTo(0));
} }
}); });
} }

View File

@ -19,7 +19,6 @@
package org.elasticsearch.gateway; package org.elasticsearch.gateway;
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.action.count.CountResponse; import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
@ -99,8 +98,7 @@ public class RecoveryBackwardsCompatibilityIT extends ESBackcompatTestCase {
HashMap<String, String> map = new HashMap<>(); HashMap<String, String> map = new HashMap<>();
map.put("details", "true"); map.put("details", "true");
final ToXContent.Params params = new ToXContent.MapParams(map); final ToXContent.Params params = new ToXContent.MapParams(map);
for (ShardRecoveryResponse response : recoveryResponse.shardResponses().get("test")) { for (RecoveryState recoveryState : recoveryResponse.shardRecoveryStates().get("test")) {
RecoveryState recoveryState = response.recoveryState();
final String recoverStateAsJSON = XContentHelper.toString(recoveryState, params); final String recoverStateAsJSON = XContentHelper.toString(recoveryState, params);
if (!recoveryState.getPrimary()) { if (!recoveryState.getPrimary()) {
RecoveryState.Index index = recoveryState.getIndex(); RecoveryState.Index index = recoveryState.getIndex();

View File

@ -20,7 +20,6 @@
package org.elasticsearch.gateway; package org.elasticsearch.gateway;
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.action.admin.indices.stats.IndexStats; import org.elasticsearch.action.admin.indices.stats.IndexStats;
import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.admin.indices.stats.ShardStats;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
@ -400,8 +399,7 @@ public class RecoveryFromGatewayIT extends ESIntegTestCase {
assertSyncIdsNotNull(); assertSyncIdsNotNull();
} }
RecoveryResponse recoveryResponse = client().admin().indices().prepareRecoveries("test").get(); RecoveryResponse recoveryResponse = client().admin().indices().prepareRecoveries("test").get();
for (ShardRecoveryResponse response : recoveryResponse.shardResponses().get("test")) { for (RecoveryState recoveryState : recoveryResponse.shardRecoveryStates().get("test")) {
RecoveryState recoveryState = response.recoveryState();
long recovered = 0; long recovered = 0;
for (RecoveryState.File file : recoveryState.getIndex().fileDetails()) { for (RecoveryState.File file : recoveryState.getIndex().fileDetails()) {
if (file.name().startsWith("segments")) { if (file.name().startsWith("segments")) {
@ -410,7 +408,7 @@ public class RecoveryFromGatewayIT extends ESIntegTestCase {
} }
if (!recoveryState.getPrimary() && (useSyncIds == false)) { if (!recoveryState.getPrimary() && (useSyncIds == false)) {
logger.info("--> replica shard {} recovered from {} to {}, recovered {}, reuse {}", logger.info("--> replica shard {} recovered from {} to {}, recovered {}, reuse {}",
response.getShardId(), recoveryState.getSourceNode().name(), recoveryState.getTargetNode().name(), recoveryState.getShardId().getId(), recoveryState.getSourceNode().name(), recoveryState.getTargetNode().name(),
recoveryState.getIndex().recoveredBytes(), recoveryState.getIndex().reusedBytes()); recoveryState.getIndex().recoveredBytes(), recoveryState.getIndex().reusedBytes());
assertThat("no bytes should be recovered", recoveryState.getIndex().recoveredBytes(), equalTo(recovered)); assertThat("no bytes should be recovered", recoveryState.getIndex().recoveredBytes(), equalTo(recovered));
assertThat("data should have been reused", recoveryState.getIndex().reusedBytes(), greaterThan(0l)); assertThat("data should have been reused", recoveryState.getIndex().reusedBytes(), greaterThan(0l));
@ -422,7 +420,7 @@ public class RecoveryFromGatewayIT extends ESIntegTestCase {
} else { } else {
if (useSyncIds && !recoveryState.getPrimary()) { if (useSyncIds && !recoveryState.getPrimary()) {
logger.info("--> replica shard {} recovered from {} to {} using sync id, recovered {}, reuse {}", logger.info("--> replica shard {} recovered from {} to {} using sync id, recovered {}, reuse {}",
response.getShardId(), recoveryState.getSourceNode().name(), recoveryState.getTargetNode().name(), recoveryState.getShardId().getId(), recoveryState.getSourceNode().name(), recoveryState.getTargetNode().name(),
recoveryState.getIndex().recoveredBytes(), recoveryState.getIndex().reusedBytes()); recoveryState.getIndex().recoveredBytes(), recoveryState.getIndex().reusedBytes());
} }
assertThat(recoveryState.getIndex().recoveredBytes(), equalTo(0l)); assertThat(recoveryState.getIndex().recoveredBytes(), equalTo(0l));

View File

@ -28,7 +28,10 @@ import org.elasticsearch.action.admin.indices.stats.IndexStats;
import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.admin.indices.stats.ShardStats;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.*; import org.elasticsearch.cluster.ClusterInfoService;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.InternalClusterInfoService;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.ShardRoutingState; import org.elasticsearch.cluster.routing.ShardRoutingState;
@ -43,7 +46,6 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.env.ShardLock; import org.elasticsearch.env.ShardLock;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.query.QueryParsingException; import org.elasticsearch.index.query.QueryParsingException;
@ -65,7 +67,10 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static org.elasticsearch.cluster.metadata.IndexMetaData.*; import static org.elasticsearch.cluster.metadata.IndexMetaData.EMPTY_PARAMS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_VERSION_CREATED;
import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;

View File

@ -27,7 +27,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRes
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags; import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder;
@ -53,7 +52,12 @@ import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.store.MockFSDirectoryService; import org.elasticsearch.test.store.MockFSDirectoryService;
import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.test.transport.MockTransportService;
import org.elasticsearch.transport.*; import org.elasticsearch.transport.ConnectTransportException;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestOptions;
import org.elasticsearch.transport.TransportService;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
@ -67,7 +71,13 @@ import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.test.ESIntegTestCase.Scope; import static org.elasticsearch.test.ESIntegTestCase.Scope;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.not;
/** /**
* *
@ -155,18 +165,17 @@ public class IndexRecoveryIT extends ESIntegTestCase {
logger.info("--> request recoveries"); logger.info("--> request recoveries");
RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
assertThat(response.shardResponses().size(), equalTo(SHARD_COUNT)); assertThat(response.shardRecoveryStates().size(), equalTo(SHARD_COUNT));
assertThat(response.shardResponses().get(INDEX_NAME).size(), equalTo(1)); assertThat(response.shardRecoveryStates().get(INDEX_NAME).size(), equalTo(1));
List<ShardRecoveryResponse> shardResponses = response.shardResponses().get(INDEX_NAME); List<RecoveryState> recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
assertThat(shardResponses.size(), equalTo(1)); assertThat(recoveryStates.size(), equalTo(1));
ShardRecoveryResponse shardResponse = shardResponses.get(0); RecoveryState recoveryState = recoveryStates.get(0);
RecoveryState state = shardResponse.recoveryState();
assertRecoveryState(state, 0, Type.STORE, Stage.DONE, node, node, false); assertRecoveryState(recoveryState, 0, Type.STORE, Stage.DONE, node, node, false);
validateIndexRecoveryState(state.getIndex()); validateIndexRecoveryState(recoveryState.getIndex());
} }
@Test @Test
@ -183,8 +192,8 @@ public class IndexRecoveryIT extends ESIntegTestCase {
logger.info("--> request recoveries"); logger.info("--> request recoveries");
RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).setActiveOnly(true).execute().actionGet(); RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).setActiveOnly(true).execute().actionGet();
List<ShardRecoveryResponse> shardResponses = response.shardResponses().get(INDEX_NAME); List<RecoveryState> recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
assertThat(shardResponses.size(), equalTo(0)); // Should not expect any responses back assertThat(recoveryStates.size(), equalTo(0)); // Should not expect any responses back
} }
@Test @Test
@ -209,23 +218,23 @@ public class IndexRecoveryIT extends ESIntegTestCase {
RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
// we should now have two total shards, one primary and one replica // we should now have two total shards, one primary and one replica
List<ShardRecoveryResponse> shardResponses = response.shardResponses().get(INDEX_NAME); List<RecoveryState> recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
assertThat(shardResponses.size(), equalTo(2)); assertThat(recoveryStates.size(), equalTo(2));
List<ShardRecoveryResponse> nodeAResponses = findRecoveriesForTargetNode(nodeA, shardResponses); List<RecoveryState> nodeAResponses = findRecoveriesForTargetNode(nodeA, recoveryStates);
assertThat(nodeAResponses.size(), equalTo(1)); assertThat(nodeAResponses.size(), equalTo(1));
List<ShardRecoveryResponse> nodeBResponses = findRecoveriesForTargetNode(nodeB, shardResponses); List<RecoveryState> nodeBResponses = findRecoveriesForTargetNode(nodeB, recoveryStates);
assertThat(nodeBResponses.size(), equalTo(1)); assertThat(nodeBResponses.size(), equalTo(1));
// validate node A recovery // validate node A recovery
ShardRecoveryResponse nodeAShardResponse = nodeAResponses.get(0); RecoveryState nodeARecoveryState = nodeAResponses.get(0);
assertRecoveryState(nodeAShardResponse.recoveryState(), 0, Type.STORE, Stage.DONE, nodeA, nodeA, false); assertRecoveryState(nodeARecoveryState, 0, Type.STORE, Stage.DONE, nodeA, nodeA, false);
validateIndexRecoveryState(nodeAShardResponse.recoveryState().getIndex()); validateIndexRecoveryState(nodeARecoveryState.getIndex());
// validate node B recovery // validate node B recovery
ShardRecoveryResponse nodeBShardResponse = nodeBResponses.get(0); RecoveryState nodeBRecoveryState = nodeBResponses.get(0);
assertRecoveryState(nodeBShardResponse.recoveryState(), 0, Type.REPLICA, Stage.DONE, nodeA, nodeB, false); assertRecoveryState(nodeBRecoveryState, 0, Type.REPLICA, Stage.DONE, nodeA, nodeB, false);
validateIndexRecoveryState(nodeBShardResponse.recoveryState().getIndex()); validateIndexRecoveryState(nodeBRecoveryState.getIndex());
} }
@Test @Test
@ -266,17 +275,17 @@ public class IndexRecoveryIT extends ESIntegTestCase {
logger.info("--> request recoveries"); logger.info("--> request recoveries");
RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
List<ShardRecoveryResponse> shardResponses = response.shardResponses().get(INDEX_NAME); List<RecoveryState> recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
List<ShardRecoveryResponse> nodeAResponses = findRecoveriesForTargetNode(nodeA, shardResponses); List<RecoveryState> nodeARecoveryStates = findRecoveriesForTargetNode(nodeA, recoveryStates);
assertThat(nodeAResponses.size(), equalTo(1)); assertThat(nodeARecoveryStates.size(), equalTo(1));
List<ShardRecoveryResponse> nodeBResponses = findRecoveriesForTargetNode(nodeB, shardResponses); List<RecoveryState> nodeBRecoveryStates = findRecoveriesForTargetNode(nodeB, recoveryStates);
assertThat(nodeBResponses.size(), equalTo(1)); assertThat(nodeBRecoveryStates.size(), equalTo(1));
assertRecoveryState(nodeAResponses.get(0).recoveryState(), 0, Type.STORE, Stage.DONE, nodeA, nodeA, false); assertRecoveryState(nodeARecoveryStates.get(0), 0, Type.STORE, Stage.DONE, nodeA, nodeA, false);
validateIndexRecoveryState(nodeAResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeARecoveryStates.get(0).getIndex());
assertOnGoingRecoveryState(nodeBResponses.get(0).recoveryState(), 0, Type.RELOCATION, nodeA, nodeB, false); assertOnGoingRecoveryState(nodeBRecoveryStates.get(0), 0, Type.RELOCATION, nodeA, nodeB, false);
validateIndexRecoveryState(nodeBResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeBRecoveryStates.get(0).getIndex());
logger.info("--> request node recovery stats"); logger.info("--> request node recovery stats");
NodesStatsResponse statsResponse = client().admin().cluster().prepareNodesStats().clear().setIndices(new CommonStatsFlags(CommonStatsFlags.Flag.Recovery)).get(); NodesStatsResponse statsResponse = client().admin().cluster().prepareNodesStats().clear().setIndices(new CommonStatsFlags(CommonStatsFlags.Flag.Recovery)).get();
@ -325,11 +334,11 @@ public class IndexRecoveryIT extends ESIntegTestCase {
response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
shardResponses = response.shardResponses().get(INDEX_NAME); recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
assertThat(shardResponses.size(), equalTo(1)); assertThat(recoveryStates.size(), equalTo(1));
assertRecoveryState(shardResponses.get(0).recoveryState(), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false); assertRecoveryState(recoveryStates.get(0), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false);
validateIndexRecoveryState(shardResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(recoveryStates.get(0).getIndex());
statsResponse = client().admin().cluster().prepareNodesStats().clear().setIndices(new CommonStatsFlags(CommonStatsFlags.Flag.Recovery)).get(); statsResponse = client().admin().cluster().prepareNodesStats().clear().setIndices(new CommonStatsFlags(CommonStatsFlags.Flag.Recovery)).get();
assertThat(statsResponse.getNodes(), arrayWithSize(2)); assertThat(statsResponse.getNodes(), arrayWithSize(2));
@ -377,45 +386,45 @@ public class IndexRecoveryIT extends ESIntegTestCase {
.execute().actionGet().getState(); .execute().actionGet().getState();
response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
shardResponses = response.shardResponses().get(INDEX_NAME); recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
nodeAResponses = findRecoveriesForTargetNode(nodeA, shardResponses); nodeARecoveryStates = findRecoveriesForTargetNode(nodeA, recoveryStates);
assertThat(nodeAResponses.size(), equalTo(1)); assertThat(nodeARecoveryStates.size(), equalTo(1));
nodeBResponses = findRecoveriesForTargetNode(nodeB, shardResponses); nodeBRecoveryStates = findRecoveriesForTargetNode(nodeB, recoveryStates);
assertThat(nodeBResponses.size(), equalTo(1)); assertThat(nodeBRecoveryStates.size(), equalTo(1));
List<ShardRecoveryResponse> nodeCResponses = findRecoveriesForTargetNode(nodeC, shardResponses); List<RecoveryState> nodeCRecoveryStates = findRecoveriesForTargetNode(nodeC, recoveryStates);
assertThat(nodeCResponses.size(), equalTo(1)); assertThat(nodeCRecoveryStates.size(), equalTo(1));
assertRecoveryState(nodeAResponses.get(0).recoveryState(), 0, Type.REPLICA, Stage.DONE, nodeB, nodeA, false); assertRecoveryState(nodeARecoveryStates.get(0), 0, Type.REPLICA, Stage.DONE, nodeB, nodeA, false);
validateIndexRecoveryState(nodeAResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeARecoveryStates.get(0).getIndex());
assertRecoveryState(nodeBResponses.get(0).recoveryState(), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false); assertRecoveryState(nodeBRecoveryStates.get(0), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false);
validateIndexRecoveryState(nodeBResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeBRecoveryStates.get(0).getIndex());
// relocations of replicas are marked as REPLICA and the source node is the node holding the primary (B) // relocations of replicas are marked as REPLICA and the source node is the node holding the primary (B)
assertOnGoingRecoveryState(nodeCResponses.get(0).recoveryState(), 0, Type.REPLICA, nodeB, nodeC, false); assertOnGoingRecoveryState(nodeCRecoveryStates.get(0), 0, Type.REPLICA, nodeB, nodeC, false);
validateIndexRecoveryState(nodeCResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeCRecoveryStates.get(0).getIndex());
logger.info("--> speeding up recoveries"); logger.info("--> speeding up recoveries");
restoreRecoverySpeed(); restoreRecoverySpeed();
ensureGreen(); ensureGreen();
response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
shardResponses = response.shardResponses().get(INDEX_NAME); recoveryStates = response.shardRecoveryStates().get(INDEX_NAME);
nodeAResponses = findRecoveriesForTargetNode(nodeA, shardResponses); nodeARecoveryStates = findRecoveriesForTargetNode(nodeA, recoveryStates);
assertThat(nodeAResponses.size(), equalTo(0)); assertThat(nodeARecoveryStates.size(), equalTo(0));
nodeBResponses = findRecoveriesForTargetNode(nodeB, shardResponses); nodeBRecoveryStates = findRecoveriesForTargetNode(nodeB, recoveryStates);
assertThat(nodeBResponses.size(), equalTo(1)); assertThat(nodeBRecoveryStates.size(), equalTo(1));
nodeCResponses = findRecoveriesForTargetNode(nodeC, shardResponses); nodeCRecoveryStates = findRecoveriesForTargetNode(nodeC, recoveryStates);
assertThat(nodeCResponses.size(), equalTo(1)); assertThat(nodeCRecoveryStates.size(), equalTo(1));
assertRecoveryState(nodeBResponses.get(0).recoveryState(), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false); assertRecoveryState(nodeBRecoveryStates.get(0), 0, Type.RELOCATION, Stage.DONE, nodeA, nodeB, false);
validateIndexRecoveryState(nodeBResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeBRecoveryStates.get(0).getIndex());
// relocations of replicas are marked as REPLICA and the source node is the node holding the primary (B) // relocations of replicas are marked as REPLICA and the source node is the node holding the primary (B)
assertRecoveryState(nodeCResponses.get(0).recoveryState(), 0, Type.REPLICA, Stage.DONE, nodeB, nodeC, false); assertRecoveryState(nodeCRecoveryStates.get(0), 0, Type.REPLICA, Stage.DONE, nodeB, nodeC, false);
validateIndexRecoveryState(nodeCResponses.get(0).recoveryState().getIndex()); validateIndexRecoveryState(nodeCRecoveryStates.get(0).getIndex());
} }
@Test @Test
@ -457,24 +466,24 @@ public class IndexRecoveryIT extends ESIntegTestCase {
logger.info("--> request recoveries"); logger.info("--> request recoveries");
RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet(); RecoveryResponse response = client().admin().indices().prepareRecoveries(INDEX_NAME).execute().actionGet();
for (Map.Entry<String, List<ShardRecoveryResponse>> shardRecoveryResponse : response.shardResponses().entrySet()) { for (Map.Entry<String, List<RecoveryState>> indexRecoveryStates : response.shardRecoveryStates().entrySet()) {
assertThat(shardRecoveryResponse.getKey(), equalTo(INDEX_NAME)); assertThat(indexRecoveryStates.getKey(), equalTo(INDEX_NAME));
List<ShardRecoveryResponse> shardRecoveryResponses = shardRecoveryResponse.getValue(); List<RecoveryState> recoveryStates = indexRecoveryStates.getValue();
assertThat(shardRecoveryResponses.size(), equalTo(totalShards)); assertThat(recoveryStates.size(), equalTo(totalShards));
for (ShardRecoveryResponse shardResponse : shardRecoveryResponses) { for (RecoveryState recoveryState : recoveryStates) {
assertRecoveryState(shardResponse.recoveryState(), 0, Type.SNAPSHOT, Stage.DONE, null, nodeA, true); assertRecoveryState(recoveryState, 0, Type.SNAPSHOT, Stage.DONE, null, nodeA, true);
validateIndexRecoveryState(shardResponse.recoveryState().getIndex()); validateIndexRecoveryState(recoveryState.getIndex());
} }
} }
} }
private List<ShardRecoveryResponse> findRecoveriesForTargetNode(String nodeName, List<ShardRecoveryResponse> responses) { private List<RecoveryState> findRecoveriesForTargetNode(String nodeName, List<RecoveryState> recoveryStates) {
List<ShardRecoveryResponse> nodeResponses = new ArrayList<>(); List<RecoveryState> nodeResponses = new ArrayList<>();
for (ShardRecoveryResponse response : responses) { for (RecoveryState recoveryState : recoveryStates) {
if (response.recoveryState().getTargetNode().getName().equals(nodeName)) { if (recoveryState.getTargetNode().getName().equals(nodeName)) {
nodeResponses.add(response); nodeResponses.add(recoveryState);
} }
} }
return nodeResponses; return nodeResponses;

View File

@ -21,7 +21,6 @@ package org.elasticsearch.indices.warmer;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.segments.IndexSegments; import org.elasticsearch.action.admin.indices.segments.IndexSegments;
import org.elasticsearch.action.admin.indices.segments.IndexShardSegments; import org.elasticsearch.action.admin.indices.segments.IndexShardSegments;
@ -49,7 +48,10 @@ import org.junit.Test;
import java.util.Locale; import java.util.Locale;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
public class SimpleIndicesWarmerIT extends ESIntegTestCase { public class SimpleIndicesWarmerIT extends ESIntegTestCase {
@ -272,7 +274,7 @@ public class SimpleIndicesWarmerIT extends ESIntegTestCase {
for (IndexShardSegments indexShardSegments : indicesSegments) { for (IndexShardSegments indexShardSegments : indicesSegments) {
for (ShardSegments shardSegments : indexShardSegments) { for (ShardSegments shardSegments : indexShardSegments) {
for (Segment segment : shardSegments) { for (Segment segment : shardSegments) {
logger.debug("+=" + segment.memoryInBytes + " " + indexShardSegments.getShardId() + " " + shardSegments.getIndex()); logger.debug("+=" + segment.memoryInBytes + " " + indexShardSegments.getShardId() + " " + shardSegments.getShardRouting().getIndex());
total += segment.memoryInBytes; total += segment.memoryInBytes;
} }
} }

View File

@ -284,7 +284,7 @@ public class RecoveryWhileUnderLoadIT extends ESIntegTestCase {
IndicesStatsResponse indicesStatsResponse = client().admin().indices().prepareStats().get(); IndicesStatsResponse indicesStatsResponse = client().admin().indices().prepareStats().get();
for (ShardStats shardStats : indicesStatsResponse.getShards()) { for (ShardStats shardStats : indicesStatsResponse.getShards()) {
DocsStats docsStats = shardStats.getStats().docs; DocsStats docsStats = shardStats.getStats().docs;
logger.info("shard [{}] - count {}, primary {}", shardStats.getShardId(), docsStats.getCount(), shardStats.getShardRouting().primary()); logger.info("shard [{}] - count {}, primary {}", shardStats.getShardRouting().id(), docsStats.getCount(), shardStats.getShardRouting().primary());
} }
//if there was an error we try to wait and see if at some point it'll get fixed //if there was an error we try to wait and see if at some point it'll get fixed

View File

@ -63,7 +63,6 @@ import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.test.transport.MockTransportService;
import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportException; import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportModule;
import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestOptions; import org.elasticsearch.transport.TransportRequestOptions;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
@ -422,7 +421,7 @@ public class RelocationIT extends ESIntegTestCase {
public boolean apply(Object input) { public boolean apply(Object input) {
RecoveryResponse recoveryResponse = internalCluster().client(redNodeName).admin().indices().prepareRecoveries(indexName) RecoveryResponse recoveryResponse = internalCluster().client(redNodeName).admin().indices().prepareRecoveries(indexName)
.get(); .get();
return !recoveryResponse.shardResponses().get(indexName).isEmpty(); return !recoveryResponse.shardRecoveryStates().get(indexName).isEmpty();
} }
} }
); );

View File

@ -32,7 +32,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
import org.elasticsearch.action.admin.indices.recovery.ShardRecoveryResponse;
import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.AbstractDiffable; import org.elasticsearch.cluster.AbstractDiffable;
@ -55,6 +54,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.discovery.zen.elect.ElectMasterService; import org.elasticsearch.discovery.zen.elect.ElectMasterService;
import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.index.store.IndexStore;
import org.elasticsearch.indices.recovery.RecoveryState;
import org.elasticsearch.indices.ttl.IndicesTTLService; import org.elasticsearch.indices.ttl.IndicesTTLService;
import org.elasticsearch.repositories.RepositoryMissingException; import org.elasticsearch.repositories.RepositoryMissingException;
import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestChannel;
@ -81,8 +81,18 @@ import java.util.concurrent.atomic.AtomicReference;
import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.test.ESIntegTestCase.ClusterScope; import static org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import static org.elasticsearch.test.ESIntegTestCase.Scope; import static org.elasticsearch.test.ESIntegTestCase.Scope;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.*; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.*; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBlocked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
/** /**
*/ */
@ -592,9 +602,9 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
assertThat(client().prepareCount("test-idx").get().getCount(), equalTo(100L)); assertThat(client().prepareCount("test-idx").get().getCount(), equalTo(100L));
IntSet reusedShards = new IntHashSet(); IntSet reusedShards = new IntHashSet();
for (ShardRecoveryResponse response : client().admin().indices().prepareRecoveries("test-idx").get().shardResponses().get("test-idx")) { for (RecoveryState recoveryState : client().admin().indices().prepareRecoveries("test-idx").get().shardRecoveryStates().get("test-idx")) {
if (response.recoveryState().getIndex().reusedBytes() > 0) { if (recoveryState.getIndex().reusedBytes() > 0) {
reusedShards.add(response.getShardId()); reusedShards.add(recoveryState.getShardId().getId());
} }
} }
logger.info("--> check that at least half of the shards had some reuse: [{}]", reusedShards); logger.info("--> check that at least half of the shards had some reuse: [{}]", reusedShards);