CCR: Make AutoFollowMetadata immutable (#33977)
We should make AutoFollowMetadata immutable to avoid being inconsistent when one thread modifies it while other reads it.
This commit is contained in:
parent
018714f938
commit
6ec36b1273
|
@ -368,18 +368,19 @@ public class AutoFollowCoordinator implements ClusterStateApplier {
|
||||||
Index indexToFollow) {
|
Index indexToFollow) {
|
||||||
return currentState -> {
|
return currentState -> {
|
||||||
AutoFollowMetadata currentAutoFollowMetadata = currentState.metaData().custom(AutoFollowMetadata.TYPE);
|
AutoFollowMetadata currentAutoFollowMetadata = currentState.metaData().custom(AutoFollowMetadata.TYPE);
|
||||||
|
Map<String, List<String>> newFollowedIndexUUIDS = new HashMap<>(currentAutoFollowMetadata.getFollowedLeaderIndexUUIDs());
|
||||||
Map<String, List<String>> newFollowedIndexUUIDS =
|
newFollowedIndexUUIDS.compute(clusterAlias, (key, existingUUIDs) -> {
|
||||||
new HashMap<>(currentAutoFollowMetadata.getFollowedLeaderIndexUUIDs());
|
assert existingUUIDs != null;
|
||||||
newFollowedIndexUUIDS.get(clusterAlias).add(indexToFollow.getUUID());
|
List<String> newUUIDs = new ArrayList<>(existingUUIDs);
|
||||||
|
newUUIDs.add(indexToFollow.getUUID());
|
||||||
ClusterState.Builder newState = ClusterState.builder(currentState);
|
return Collections.unmodifiableList(newUUIDs);
|
||||||
AutoFollowMetadata newAutoFollowMetadata = new AutoFollowMetadata(currentAutoFollowMetadata.getPatterns(),
|
});
|
||||||
|
final AutoFollowMetadata newAutoFollowMetadata = new AutoFollowMetadata(currentAutoFollowMetadata.getPatterns(),
|
||||||
newFollowedIndexUUIDS, currentAutoFollowMetadata.getHeaders());
|
newFollowedIndexUUIDS, currentAutoFollowMetadata.getHeaders());
|
||||||
newState.metaData(MetaData.builder(currentState.getMetaData())
|
return ClusterState.builder(currentState)
|
||||||
.putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata)
|
.metaData(MetaData.builder(currentState.getMetaData())
|
||||||
.build());
|
.putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata).build())
|
||||||
return newState.build();
|
.build();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,12 +135,13 @@ public class TransportPutAutoFollowPatternAction extends
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoFollowPattern previousPattern = patterns.get(request.getLeaderClusterAlias());
|
AutoFollowPattern previousPattern = patterns.get(request.getLeaderClusterAlias());
|
||||||
List<String> followedIndexUUIDs = followedLeaderIndices.get(request.getLeaderClusterAlias());
|
final List<String> followedIndexUUIDs;
|
||||||
if (followedIndexUUIDs == null) {
|
if (followedLeaderIndices.containsKey(request.getLeaderClusterAlias())) {
|
||||||
|
followedIndexUUIDs = new ArrayList<>(followedLeaderIndices.get(request.getLeaderClusterAlias()));
|
||||||
|
} else {
|
||||||
followedIndexUUIDs = new ArrayList<>();
|
followedIndexUUIDs = new ArrayList<>();
|
||||||
followedLeaderIndices.put(request.getLeaderClusterAlias(), followedIndexUUIDs);
|
|
||||||
}
|
}
|
||||||
|
followedLeaderIndices.put(request.getLeaderClusterAlias(), followedIndexUUIDs);
|
||||||
// Mark existing leader indices as already auto followed:
|
// Mark existing leader indices as already auto followed:
|
||||||
if (previousPattern != null) {
|
if (previousPattern != null) {
|
||||||
markExistingIndicesAsAutoFollowedForNewPatterns(request.getLeaderIndexPatterns(), leaderClusterState.metaData(),
|
markExistingIndicesAsAutoFollowedForNewPatterns(request.getLeaderIndexPatterns(), leaderClusterState.metaData(),
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
void getLeaderClusterState(Map<String, String> headers,
|
void getLeaderClusterState(Map<String, String> headers,
|
||||||
String leaderClusterAlias,
|
String leaderClusterAlias,
|
||||||
BiConsumer<ClusterState, Exception> handler) {
|
BiConsumer<ClusterState, Exception> handler) {
|
||||||
assertThat(headers, sameInstance(autoFollowHeaders.get("remote")));
|
assertThat(headers, equalTo(autoFollowHeaders.get("remote")));
|
||||||
handler.accept(leaderState, null);
|
handler.accept(leaderState, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
FollowIndexAction.Request followRequest,
|
FollowIndexAction.Request followRequest,
|
||||||
Runnable successHandler,
|
Runnable successHandler,
|
||||||
Consumer<Exception> failureHandler) {
|
Consumer<Exception> failureHandler) {
|
||||||
assertThat(headers, sameInstance(autoFollowHeaders.get("remote")));
|
assertThat(headers, equalTo(autoFollowHeaders.get("remote")));
|
||||||
assertThat(followRequest.getLeaderIndex(), equalTo("remote:logs-20190101"));
|
assertThat(followRequest.getLeaderIndex(), equalTo("remote:logs-20190101"));
|
||||||
assertThat(followRequest.getFollowerIndex(), equalTo("logs-20190101"));
|
assertThat(followRequest.getFollowerIndex(), equalTo("logs-20190101"));
|
||||||
successHandler.run();
|
successHandler.run();
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom metadata that contains auto follow patterns and what leader indices an auto follow pattern has already followed.
|
* Custom metadata that contains auto follow patterns and what leader indices an auto follow pattern has already followed.
|
||||||
|
@ -79,16 +80,19 @@ public class AutoFollowMetadata extends AbstractNamedDiffable<MetaData.Custom> i
|
||||||
public AutoFollowMetadata(Map<String, AutoFollowPattern> patterns,
|
public AutoFollowMetadata(Map<String, AutoFollowPattern> patterns,
|
||||||
Map<String, List<String>> followedLeaderIndexUUIDs,
|
Map<String, List<String>> followedLeaderIndexUUIDs,
|
||||||
Map<String, Map<String, String>> headers) {
|
Map<String, Map<String, String>> headers) {
|
||||||
this.patterns = patterns;
|
this.patterns = Collections.unmodifiableMap(patterns);
|
||||||
this.followedLeaderIndexUUIDs = followedLeaderIndexUUIDs;
|
this.followedLeaderIndexUUIDs = Collections.unmodifiableMap(followedLeaderIndexUUIDs.entrySet().stream()
|
||||||
this.headers = Collections.unmodifiableMap(headers);
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> Collections.unmodifiableList(e.getValue()))));
|
||||||
|
this.headers = Collections.unmodifiableMap(headers.entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> Collections.unmodifiableMap(e.getValue()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutoFollowMetadata(StreamInput in) throws IOException {
|
public AutoFollowMetadata(StreamInput in) throws IOException {
|
||||||
patterns = in.readMap(StreamInput::readString, AutoFollowPattern::new);
|
this(
|
||||||
followedLeaderIndexUUIDs = in.readMapOfLists(StreamInput::readString, StreamInput::readString);
|
in.readMap(StreamInput::readString, AutoFollowPattern::new),
|
||||||
headers = Collections.unmodifiableMap(in.readMap(StreamInput::readString,
|
in.readMapOfLists(StreamInput::readString, StreamInput::readString),
|
||||||
valIn -> Collections.unmodifiableMap(valIn.readMap(StreamInput::readString, StreamInput::readString))));
|
in.readMap(StreamInput::readString, valIn -> valIn.readMap(StreamInput::readString, StreamInput::readString))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, AutoFollowPattern> getPatterns() {
|
public Map<String, AutoFollowPattern> getPatterns() {
|
||||||
|
|
Loading…
Reference in New Issue