25
25
import org .elasticsearch .cluster .node .DiscoveryNodes ;
26
26
27
27
import java .util .ArrayList ;
28
- import java .util .Arrays ;
29
28
import java .util .Collections ;
30
29
import java .util .List ;
30
+ import java .util .Objects ;
31
31
32
32
/**
33
- *
33
+ * An event received by the local node, signaling that the cluster state has changed.
34
34
*/
35
35
public class ClusterChangedEvent {
36
36
@@ -43,6 +43,9 @@ public class ClusterChangedEvent {
43
43
private final DiscoveryNodes .Delta nodesDelta ;
44
44
45
45
public ClusterChangedEvent (String source , ClusterState state , ClusterState previousState ) {
46
+ Objects .requireNonNull (source , "source must not be null" );
47
+ Objects .requireNonNull (state , "state must not be null" );
48
+ Objects .requireNonNull (previousState , "previousState must not be null" );
46
49
this .source = source ;
47
50
this .state = state ;
48
51
this .previousState = previousState ;
@@ -56,19 +59,35 @@ public String source() {
56
59
return this .source ;
57
60
}
58
61
62
+ /**
63
+ * The new cluster state that caused this change event.
64
+ */
59
65
public ClusterState state () {
60
66
return this .state ;
61
67
}
62
68
69
+ /**
70
+ * The previous cluster state for this change event.
71
+ */
63
72
public ClusterState previousState () {
64
73
return this .previousState ;
65
74
}
66
75
76
+ /**
77
+ * Returns <code>true</code> iff the routing tables (for all indices) have
78
+ * changed between the previous cluster state and the current cluster state.
79
+ * Note that this is an object reference equality test, not an equals test.
80
+ */
67
81
public boolean routingTableChanged () {
68
82
return state .routingTable () != previousState .routingTable ();
69
83
}
70
84
85
+ /**
86
+ * Returns <code>true</code> iff the routing table has changed for the given index.
87
+ * Note that this is an object reference equality test, not an equals test.
88
+ */
71
89
public boolean indexRoutingTableChanged (String index ) {
90
+ Objects .requireNonNull (index , "index must not be null" );
72
91
if (!state .routingTable ().hasIndex (index ) && !previousState .routingTable ().hasIndex (index )) {
73
92
return false ;
74
93
}
@@ -82,9 +101,6 @@ public boolean indexRoutingTableChanged(String index) {
82
101
* Returns the indices created in this event
83
102
*/
84
103
public List <String > indicesCreated () {
85
- if (previousState == null ) {
86
- return Arrays .asList (state .metaData ().indices ().keys ().toArray (String .class ));
87
- }
88
104
if (!metaDataChanged ()) {
89
105
return Collections .emptyList ();
90
106
}
@@ -105,20 +121,14 @@ public List<String> indicesCreated() {
105
121
* Returns the indices deleted in this event
106
122
*/
107
123
public List <String > indicesDeleted () {
108
-
109
- // if the new cluster state has a new master then we cannot know if an index which is not in the cluster state
110
- // is actually supposed to be deleted or imported as dangling instead. for example a new master might not have
111
- // the index in its cluster state because it was started with an empty data folder and in this case we want to
112
- // import as dangling. we check here for new master too to be on the safe side in this case.
113
- // This means that under certain conditions deleted indices might be reimported if a master fails while the deletion
114
- // request is issued and a node receives the cluster state that would trigger the deletion from the new master.
115
- // See test MetaDataWriteDataNodesTests.testIndicesDeleted()
124
+ // If the new cluster state has a new cluster UUID, the likely scenario is that a node was elected
125
+ // master that has had its data directory wiped out, in which case we don't want to delete the indices and lose data;
126
+ // rather we want to import them as dangling indices instead. So we check here if the cluster UUID differs from the previous
127
+ // cluster UUID, in which case, we don't want to delete indices that the master erroneously believes shouldn't exist.
128
+ // See test DiscoveryWithServiceDisruptionsIT.testIndicesDeleted()
116
129
// See discussion on https://github.com/elastic/elasticsearch/pull/9952 and
117
130
// https://github.com/elastic/elasticsearch/issues/11665
118
- if (hasNewMaster () || previousState == null ) {
119
- return Collections .emptyList ();
120
- }
121
- if (!metaDataChanged ()) {
131
+ if (metaDataChanged () == false || isNewCluster ()) {
122
132
return Collections .emptyList ();
123
133
}
124
134
List <String > deleted = null ;
@@ -134,10 +144,20 @@ public List<String> indicesDeleted() {
134
144
return deleted == null ? Collections .<String >emptyList () : deleted ;
135
145
}
136
146
147
+ /**
148
+ * Returns <code>true</code> iff the metadata for the cluster has changed between
149
+ * the previous cluster state and the new cluster state. Note that this is an object
150
+ * reference equality test, not an equals test.
151
+ */
137
152
public boolean metaDataChanged () {
138
153
return state .metaData () != previousState .metaData ();
139
154
}
140
155
156
+ /**
157
+ * Returns <code>true</code> iff the {@link IndexMetaData} for a given index
158
+ * has changed between the previous cluster state and the new cluster state.
159
+ * Note that this is an object reference equality test, not an equals test.
160
+ */
141
161
public boolean indexMetaDataChanged (IndexMetaData current ) {
142
162
MetaData previousMetaData = previousState .metaData ();
143
163
if (previousMetaData == null ) {
@@ -152,46 +172,56 @@ public boolean indexMetaDataChanged(IndexMetaData current) {
152
172
return true ;
153
173
}
154
174
175
+ /**
176
+ * Returns <code>true</code> iff the cluster level blocks have changed between cluster states.
177
+ * Note that this is an object reference equality test, not an equals test.
178
+ */
155
179
public boolean blocksChanged () {
156
180
return state .blocks () != previousState .blocks ();
157
181
}
158
182
183
+ /**
184
+ * Returns <code>true</code> iff the local node is the mater node of the cluster.
185
+ */
159
186
public boolean localNodeMaster () {
160
187
return state .nodes ().localNodeMaster ();
161
188
}
162
189
190
+ /**
191
+ * Returns the {@link org.elasticsearch.cluster.node.DiscoveryNodes.Delta} between
192
+ * the previous cluster state and the new cluster state.
193
+ */
163
194
public DiscoveryNodes .Delta nodesDelta () {
164
195
return this .nodesDelta ;
165
196
}
166
197
198
+ /**
199
+ * Returns <code>true</code> iff nodes have been removed from the cluster since the last cluster state.
200
+ */
167
201
public boolean nodesRemoved () {
168
202
return nodesDelta .removed ();
169
203
}
170
204
205
+ /**
206
+ * Returns <code>true</code> iff nodes have been added from the cluster since the last cluster state.
207
+ */
171
208
public boolean nodesAdded () {
172
209
return nodesDelta .added ();
173
210
}
174
211
212
+ /**
213
+ * Returns <code>true</code> iff nodes have been changed (added or removed) from the cluster since the last cluster state.
214
+ */
175
215
public boolean nodesChanged () {
176
216
return nodesRemoved () || nodesAdded ();
177
217
}
178
218
179
- /**
180
- * Checks if this cluster state comes from a different master than the previous one.
181
- * This is a workaround for the scenario where a node misses a cluster state that has either
182
- * no master block or state not recovered flag set. In this case we must make sure that
183
- * if an index is missing from the cluster state is not deleted immediately but instead imported
184
- * as dangling. See discussion on https://github.com/elastic/elasticsearch/pull/9952
185
- */
186
- private boolean hasNewMaster () {
187
- String oldMaster = previousState ().getNodes ().masterNodeId ();
188
- String newMaster = state ().getNodes ().masterNodeId ();
189
- if (oldMaster == null && newMaster == null ) {
190
- return false ;
191
- }
192
- if (oldMaster == null && newMaster != null ) {
193
- return true ;
194
- }
195
- return oldMaster .equals (newMaster ) == false ;
219
+ // Determines whether or not the current cluster state represents an entirely
220
+ // different cluster from the previous cluster state, which will happen when a
221
+ // master node is elected that has never been part of the cluster before.
222
+ private boolean isNewCluster () {
223
+ final String prevClusterUUID = previousState .metaData ().clusterUUID ();
224
+ final String currClusterUUID = state .metaData ().clusterUUID ();
225
+ return prevClusterUUID .equals (currClusterUUID ) == false ;
196
226
}
197
- }
227
+ }
0 commit comments