Skip to content

Commit 94edf37

Browse files
himshikhaBukhtawar
authored andcommitted
Add cluster state checksum in manifest (opensearch-project#15218)
* Add cluster state checksum in manifest for remote state and routing table publication Signed-off-by: Himshikha Gupta <[email protected]> Co-authored-by: Bukhtawar Khan <[email protected]>
1 parent a21d6f9 commit 94edf37

38 files changed

+2085
-61
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
4646
- [Remote Publication] Add remote download stats ([#15291](https://github.com/opensearch-project/OpenSearch/pull/15291)))
4747
- Add support for comma-separated list of index names to be used with Snapshot Status API ([#15409](https://github.com/opensearch-project/OpenSearch/pull/15409))
4848
- Add prefix support to hashed prefix & infix path types on remote store ([#15557](https://github.com/opensearch-project/OpenSearch/pull/15557))
49+
- [Remote Publication] Added checksum validation for cluster state behind a cluster setting ([#15218](https://github.com/opensearch-project/OpenSearch/pull/15218))
4950

5051
### Dependencies
5152
- Bump `netty` from 4.1.111.Final to 4.1.112.Final ([#15081](https://github.com/opensearch-project/OpenSearch/pull/15081))

libs/core/src/main/java/org/opensearch/core/common/io/stream/BufferedChecksumStreamOutput.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,18 @@
3333
package org.opensearch.core.common.io.stream;
3434

3535
import org.apache.lucene.store.BufferedChecksum;
36+
import org.opensearch.common.Nullable;
3637
import org.opensearch.common.annotation.PublicApi;
3738

3839
import java.io.IOException;
40+
import java.util.ArrayList;
41+
import java.util.Arrays;
42+
import java.util.Collection;
43+
import java.util.Collections;
44+
import java.util.List;
45+
import java.util.Map;
46+
import java.util.TreeMap;
47+
import java.util.stream.Collectors;
3948
import java.util.zip.CRC32;
4049
import java.util.zip.Checksum;
4150

@@ -90,4 +99,75 @@ public void reset() throws IOException {
9099
public void resetDigest() {
91100
digest.reset();
92101
}
102+
103+
@Override
104+
public void writeMap(@Nullable Map<String, Object> map) throws IOException {
105+
Map<String, Object> newMap = new TreeMap<>(map);
106+
writeGenericValue(newMap);
107+
}
108+
109+
@Override
110+
public <K, V> void writeMap(Map<K, V> map, final Writeable.Writer<K> keyWriter, final Writeable.Writer<V> valueWriter)
111+
throws IOException {
112+
writeVInt(map.size());
113+
map.keySet().stream().sorted().forEachOrdered(key -> {
114+
try {
115+
keyWriter.write(this, key);
116+
valueWriter.write(this, map.get(key));
117+
} catch (IOException e) {
118+
throw new RuntimeException("Failed to write map values.", e);
119+
}
120+
});
121+
}
122+
123+
public <K, V> void writeMapValues(Map<K, V> map, final Writeable.Writer<V> valueWriter) throws IOException {
124+
writeVInt(map.size());
125+
map.keySet().stream().sorted().forEachOrdered(key -> {
126+
try {
127+
valueWriter.write(this, map.get(key));
128+
} catch (IOException e) {
129+
throw new RuntimeException("Failed to write map values.", e);
130+
}
131+
});
132+
}
133+
134+
@Override
135+
public void writeStringArray(String[] array) throws IOException {
136+
String[] copyArray = Arrays.copyOf(array, array.length);
137+
Arrays.sort(copyArray);
138+
super.writeStringArray(copyArray);
139+
}
140+
141+
@Override
142+
public void writeVLongArray(long[] values) throws IOException {
143+
long[] copyValues = Arrays.copyOf(values, values.length);
144+
Arrays.sort(copyValues);
145+
super.writeVLongArray(copyValues);
146+
}
147+
148+
@Override
149+
public void writeCollection(final Collection<? extends Writeable> collection) throws IOException {
150+
List<? extends Writeable> sortedList = collection.stream().sorted().collect(Collectors.toList());
151+
super.writeCollection(sortedList, (o, v) -> v.writeTo(o));
152+
}
153+
154+
@Override
155+
public void writeStringCollection(final Collection<String> collection) throws IOException {
156+
List<String> listCollection = new ArrayList<>(collection);
157+
Collections.sort(listCollection);
158+
writeCollection(listCollection, StreamOutput::writeString);
159+
}
160+
161+
@Override
162+
public void writeOptionalStringCollection(final Collection<String> collection) throws IOException {
163+
if (collection != null) {
164+
List<String> listCollection = new ArrayList<>(collection);
165+
Collections.sort(listCollection);
166+
writeBoolean(true);
167+
writeCollection(listCollection, StreamOutput::writeString);
168+
} else {
169+
writeBoolean(false);
170+
}
171+
}
172+
93173
}

libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamOutput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ public final <K, V> void writeMapOfLists(final Map<K, List<V>> map, final Writer
633633
* @param keyWriter The key writer
634634
* @param valueWriter The value writer
635635
*/
636-
public final <K, V> void writeMap(final Map<K, V> map, final Writer<K> keyWriter, final Writer<V> valueWriter) throws IOException {
636+
public <K, V> void writeMap(final Map<K, V> map, final Writer<K> keyWriter, final Writer<V> valueWriter) throws IOException {
637637
writeVInt(map.size());
638638
for (final Map.Entry<K, V> entry : map.entrySet()) {
639639
keyWriter.write(this, entry.getKey());
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.core.common.io.stream;
10+
11+
import java.io.IOException;
12+
13+
/**
14+
* Provides a method for serialization which will give ordered stream, creating same byte array on every invocation.
15+
* This should be invoked with a stream that provides ordered serialization.
16+
*/
17+
public interface VerifiableWriteable extends Writeable {
18+
19+
void writeVerifiableTo(BufferedChecksumStreamOutput out) throws IOException;
20+
}

server/src/internalClusterTest/java/org/opensearch/gateway/remote/RemoteRoutingTableServiceIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ protected Settings nodeSettings(int nodeOrdinal) {
6767
)
6868
.put("node.attr." + REMOTE_STORE_ROUTING_TABLE_REPOSITORY_NAME_ATTRIBUTE_KEY, REMOTE_ROUTING_TABLE_REPO)
6969
.put(REMOTE_PUBLICATION_EXPERIMENTAL, true)
70+
.put(RemoteClusterStateService.REMOTE_CLUSTER_STATE_CHECKSUM_VALIDATION_ENABLED_SETTING.getKey(), true)
7071
.build();
7172
}
7273

server/src/internalClusterTest/java/org/opensearch/gateway/remote/RemoteStatePublicationIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ protected Settings nodeSettings(int nodeOrdinal) {
9090
.put("node.attr." + REMOTE_STORE_ROUTING_TABLE_REPOSITORY_NAME_ATTRIBUTE_KEY, routingTableRepoName)
9191
.put(routingTableRepoTypeAttributeKey, ReloadableFsRepository.TYPE)
9292
.put(routingTableRepoSettingsAttributeKeyPrefix + "location", segmentRepoPath)
93+
.put(RemoteClusterStateService.REMOTE_CLUSTER_STATE_CHECKSUM_VALIDATION_ENABLED_SETTING.getKey(), true)
9394
.build();
9495
}
9596

server/src/main/java/org/opensearch/cluster/AbstractDiffable.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ private static class CompleteDiff<T extends Diffable<T>> implements Diff<T> {
8383
this.part = part;
8484
}
8585

86+
@Override
87+
public String toString() {
88+
return "CompleteDiff{" + "part=" + part + '}';
89+
}
90+
8691
/**
8792
* Creates simple diff without changes
8893
*/

server/src/main/java/org/opensearch/cluster/ClusterState.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ default boolean isPrivate() {
156156

157157
}
158158

159-
private static final NamedDiffableValueSerializer<Custom> CUSTOM_VALUE_SERIALIZER = new NamedDiffableValueSerializer<>(Custom.class);
159+
public static final NamedDiffableValueSerializer<Custom> CUSTOM_VALUE_SERIALIZER = new NamedDiffableValueSerializer<>(Custom.class);
160160

161161
public static final String UNKNOWN_UUID = "_na_";
162162

@@ -839,6 +839,34 @@ private static class ClusterStateDiff implements Diff<ClusterState> {
839839
minimumClusterManagerNodesOnPublishingClusterManager = after.minimumClusterManagerNodesOnPublishingClusterManager;
840840
}
841841

842+
@Override
843+
public String toString() {
844+
return new StringBuilder().append("ClusterStateDiff{toVersion=")
845+
.append(toVersion)
846+
.append(", fromUuid='")
847+
.append(fromUuid)
848+
.append('\'')
849+
.append(", toUuid='")
850+
.append(toUuid)
851+
.append('\'')
852+
.append(", clusterName=")
853+
.append(clusterName)
854+
.append(", routingTable=")
855+
.append(routingTable)
856+
.append(", nodes=")
857+
.append(nodes)
858+
.append(", metadata=")
859+
.append(metadata)
860+
.append(", blocks=")
861+
.append(blocks)
862+
.append(", customs=")
863+
.append(customs)
864+
.append(", minimumClusterManagerNodesOnPublishingClusterManager=")
865+
.append(minimumClusterManagerNodesOnPublishingClusterManager)
866+
.append("}")
867+
.toString();
868+
}
869+
842870
ClusterStateDiff(StreamInput in, DiscoveryNode localNode) throws IOException {
843871
clusterName = new ClusterName(in);
844872
fromUuid = in.readString();

server/src/main/java/org/opensearch/cluster/DiffableUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ public Map<K, T> getUpserts() {
271271
return upserts;
272272
}
273273

274+
@Override
275+
public String toString() {
276+
return new StringBuilder().append("MapDiff{deletes=")
277+
.append(deletes)
278+
.append(", diffs=")
279+
.append(diffs)
280+
.append(", upserts=")
281+
.append(upserts)
282+
.append("}")
283+
.toString();
284+
}
285+
274286
@Override
275287
public void writeTo(StreamOutput out) throws IOException {
276288
out.writeCollection(deletes, (o, v) -> keySerializer.writeKey(v, o));

server/src/main/java/org/opensearch/cluster/block/ClusterBlock.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
* @opensearch.api
5353
*/
5454
@PublicApi(since = "1.0.0")
55-
public class ClusterBlock implements Writeable, ToXContentFragment {
55+
public class ClusterBlock implements Writeable, ToXContentFragment, Comparable<ClusterBlock> {
5656

5757
private final int id;
5858
@Nullable
@@ -217,7 +217,13 @@ public int hashCode() {
217217
return Objects.hash(id, uuid);
218218
}
219219

220+
@Override
221+
public int compareTo(ClusterBlock block) {
222+
return Integer.compare(block.id(), this.id());
223+
}
224+
220225
public boolean isAllowReleaseResources() {
221226
return allowReleaseResources;
222227
}
228+
223229
}

0 commit comments

Comments
 (0)