Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ public void testHalfDeletedIndexImport() throws Exception {
.putCustom(IndexGraveyard.TYPE, IndexGraveyard.builder().addTombstone(metadata.index("test").getIndex()).build())
.build()
);
NodeMetadata.FORMAT.writeAndCleanup(new NodeMetadata(nodeId, Version.CURRENT), paths);
NodeMetadata.FORMAT.writeAndCleanup(new NodeMetadata(nodeId, Version.CURRENT, Version.CURRENT), paths);
});

ensureGreen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ public interface NonRestorableCustom extends Custom {}

private SortedMap<String, IndexAbstraction> indicesLookup;

private final Version oldestIndexVersion;

private Metadata(
String clusterUUID,
boolean clusterUUIDCommitted,
Expand All @@ -231,7 +233,8 @@ private Metadata(
String[] visibleOpenIndices,
String[] allClosedIndices,
String[] visibleClosedIndices,
SortedMap<String, IndexAbstraction> indicesLookup
SortedMap<String, IndexAbstraction> indicesLookup,
Version oldestIndexVersion
) {
this.clusterUUID = clusterUUID;
this.clusterUUIDCommitted = clusterUUIDCommitted;
Expand All @@ -253,6 +256,7 @@ private Metadata(
this.allClosedIndices = allClosedIndices;
this.visibleClosedIndices = visibleClosedIndices;
this.indicesLookup = indicesLookup;
this.oldestIndexVersion = oldestIndexVersion;
}

public Metadata withIncrementedVersion() {
Expand All @@ -276,7 +280,8 @@ public Metadata withIncrementedVersion() {
visibleOpenIndices,
allClosedIndices,
visibleClosedIndices,
indicesLookup
indicesLookup,
oldestIndexVersion
);
}

Expand Down Expand Up @@ -319,6 +324,10 @@ public CoordinationMetadata coordinationMetadata() {
return this.coordinationMetadata;
}

public Version oldestIndexVersion() {
return this.oldestIndexVersion;
}

public boolean hasAlias(String alias) {
IndexAbstraction indexAbstraction = getIndicesLookup().get(alias);
if (indexAbstraction != null) {
Expand Down Expand Up @@ -1717,6 +1726,9 @@ public Metadata build(boolean builtIndicesLookupEagerly) {
final List<String> allClosedIndices = new ArrayList<>();
final List<String> visibleClosedIndices = new ArrayList<>();
final Set<String> allAliases = new HashSet<>();

int oldestIndexVersionId = Version.CURRENT.id;

for (ObjectCursor<IndexMetadata> cursor : indices.values()) {
final IndexMetadata indexMetadata = cursor.value;
final String name = indexMetadata.getIndex().getName();
Expand All @@ -1738,6 +1750,7 @@ public Metadata build(boolean builtIndicesLookupEagerly) {
}
}
indexMetadata.getAliases().keysIt().forEachRemaining(allAliases::add);
oldestIndexVersionId = Math.min(oldestIndexVersionId, indexMetadata.getCreationVersion().id);
}

final ArrayList<String> duplicates = new ArrayList<>();
Expand Down Expand Up @@ -1859,7 +1872,8 @@ public Metadata build(boolean builtIndicesLookupEagerly) {
visibleOpenIndicesArray,
allClosedIndicesArray,
visibleClosedIndicesArray,
indicesLookup
indicesLookup,
Version.fromId(oldestIndexVersionId)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public NodeEnvironment(Settings settings, Environment environment) throws IOExce
sharedDataPath = null;
locks = null;
nodeLockId = -1;
nodeMetadata = new NodeMetadata(generateNodeId(settings), Version.CURRENT);
nodeMetadata = new NodeMetadata(generateNodeId(settings), Version.CURRENT, Version.CURRENT);
return;
}
boolean success = false;
Expand Down Expand Up @@ -473,7 +473,9 @@ private static NodeMetadata loadNodeMetadata(Settings settings, Logger logger, N
final NodeMetadata legacyMetadata = NodeMetadata.FORMAT.loadLatestState(logger, NamedXContentRegistry.EMPTY, paths);
if (legacyMetadata == null) {
assert nodeIds.isEmpty() : nodeIds;
metadata = new NodeMetadata(generateNodeId(settings), Version.CURRENT);
// If we couldn't find legacy metadata, we set the latest index version to this version. This happens
// when we are starting a new node and there are no indices to worry about.
metadata = new NodeMetadata(generateNodeId(settings), Version.CURRENT, Version.CURRENT);
} else {
assert nodeIds.equals(Collections.singleton(legacyMetadata.nodeId())) : nodeIds + " doesn't match " + legacyMetadata;
metadata = legacyMetadata;
Expand Down
42 changes: 35 additions & 7 deletions server/src/main/java/org/elasticsearch/env/NodeMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,43 @@ public final class NodeMetadata {

static final String NODE_ID_KEY = "node_id";
static final String NODE_VERSION_KEY = "node_version";
private static final String OLDEST_INDEX_VERSION_KEY = "oldest_index_version";

private final String nodeId;

private final Version nodeVersion;
private final Version oldestIndexVersion;

public NodeMetadata(final String nodeId, final Version nodeVersion) {
public NodeMetadata(final String nodeId, final Version nodeVersion, final Version oldestIndexVersion) {
this.nodeId = Objects.requireNonNull(nodeId);
this.nodeVersion = Objects.requireNonNull(nodeVersion);
this.oldestIndexVersion = Objects.requireNonNull(oldestIndexVersion);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NodeMetadata that = (NodeMetadata) o;
return nodeId.equals(that.nodeId) && nodeVersion.equals(that.nodeVersion);
return nodeId.equals(that.nodeId) && nodeVersion.equals(that.nodeVersion) && oldestIndexVersion.equals(that.oldestIndexVersion);
}

@Override
public int hashCode() {
return Objects.hash(nodeId, nodeVersion);
return Objects.hash(nodeId, nodeVersion, oldestIndexVersion);
}

@Override
public String toString() {
return "NodeMetadata{" + "nodeId='" + nodeId + '\'' + ", nodeVersion=" + nodeVersion + '}';
return "NodeMetadata{"
+ "nodeId='"
+ nodeId
+ '\''
+ ", nodeVersion="
+ nodeVersion
+ ", oldestIndexVersion="
+ oldestIndexVersion
+ '}';
}

public String nodeId() {
Expand All @@ -64,10 +75,14 @@ public Version nodeVersion() {
return nodeVersion;
}

public Version oldestIndexVersion() {
return oldestIndexVersion;
}

public NodeMetadata upgradeToCurrentVersion() {
if (nodeVersion.equals(Version.V_EMPTY)) {
assert Version.CURRENT.major <= Version.V_7_0_0.major + 1 : "version is required in the node metadata from v9 onwards";
return new NodeMetadata(nodeId, Version.CURRENT);
return new NodeMetadata(nodeId, Version.CURRENT, oldestIndexVersion);
}

if (nodeVersion.before(Version.CURRENT.minimumIndexCompatibilityVersion())) {
Expand All @@ -82,12 +97,13 @@ public NodeMetadata upgradeToCurrentVersion() {
);
}

return nodeVersion.equals(Version.CURRENT) ? this : new NodeMetadata(nodeId, Version.CURRENT);
return nodeVersion.equals(Version.CURRENT) ? this : new NodeMetadata(nodeId, Version.CURRENT, oldestIndexVersion);
}

private static class Builder {
String nodeId;
Version nodeVersion;
Version oldestIndexVersion;

public void setNodeId(String nodeId) {
this.nodeId = nodeId;
Expand All @@ -97,16 +113,26 @@ public void setNodeVersionId(int nodeVersionId) {
this.nodeVersion = Version.fromId(nodeVersionId);
}

public void setOldestIndexVersion(int oldestIndexVersionId) {
this.oldestIndexVersion = Version.fromId(oldestIndexVersionId);
}

public NodeMetadata build() {
final Version nodeVersion;
final Version oldestIndexVersion;
if (this.nodeVersion == null) {
assert Version.CURRENT.major <= Version.V_7_0_0.major + 1 : "version is required in the node metadata from v9 onwards";
nodeVersion = Version.V_EMPTY;
} else {
nodeVersion = this.nodeVersion;
}
if (this.oldestIndexVersion == null) {
oldestIndexVersion = Version.V_EMPTY;
} else {
oldestIndexVersion = this.oldestIndexVersion;
}

return new NodeMetadata(nodeId, nodeVersion);
return new NodeMetadata(nodeId, nodeVersion, oldestIndexVersion);
}
}

Expand All @@ -123,6 +149,7 @@ static class NodeMetadataStateFormat extends MetadataStateFormat<NodeMetadata> {
objectParser = new ObjectParser<>("node_meta_data", ignoreUnknownFields, Builder::new);
objectParser.declareString(Builder::setNodeId, new ParseField(NODE_ID_KEY));
objectParser.declareInt(Builder::setNodeVersionId, new ParseField(NODE_VERSION_KEY));
objectParser.declareInt(Builder::setOldestIndexVersion, new ParseField(OLDEST_INDEX_VERSION_KEY));
}

@Override
Expand All @@ -136,6 +163,7 @@ protected XContentBuilder newXContentBuilder(XContentType type, OutputStream str
public void toXContent(XContentBuilder builder, NodeMetadata nodeMetadata) throws IOException {
builder.field(NODE_ID_KEY, nodeMetadata.nodeId);
builder.field(NODE_VERSION_KEY, nodeMetadata.nodeVersion.id);
builder.field(OLDEST_INDEX_VERSION_KEY, nodeMetadata.oldestIndexVersion.id);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void start(
final Tuple<Manifest, Metadata> manifestClusterStateTuple;
try {
NodeMetadata.FORMAT.writeAndCleanup(
new NodeMetadata(persistedClusterStateService.getNodeId(), Version.CURRENT),
new NodeMetadata(persistedClusterStateService.getNodeId(), Version.CURRENT, Version.V_EMPTY),
persistedClusterStateService.getDataPaths()
);
manifestClusterStateTuple = metaStateService.loadFullState();
Expand All @@ -119,6 +119,19 @@ public void start(
.metadata(manifestClusterStateTuple.v2())
.build();

try {
NodeMetadata.FORMAT.writeAndCleanup(
new NodeMetadata(
persistedClusterStateService.getNodeId(),
Version.CURRENT,
clusterState.metadata().oldestIndexVersion()
),
persistedClusterStateService.getDataPaths()
);
} catch (IOException e) {
throw new UncheckedIOException(e);
}

final IncrementalClusterStateWriter incrementalClusterStateWriter = new IncrementalClusterStateWriter(
settings,
clusterService.getClusterSettings(),
Expand Down Expand Up @@ -182,7 +195,11 @@ public void start(
}
// write legacy node metadata to prevent accidental downgrades from spawning empty cluster state
NodeMetadata.FORMAT.writeAndCleanup(
new NodeMetadata(persistedClusterStateService.getNodeId(), Version.CURRENT),
new NodeMetadata(
persistedClusterStateService.getNodeId(),
Version.CURRENT,
clusterState.metadata().oldestIndexVersion()
),
persistedClusterStateService.getDataPaths()
);
success = true;
Expand Down Expand Up @@ -216,7 +233,11 @@ public void start(
metaStateService.deleteAll();
// write legacy node metadata to prevent downgrades from spawning empty cluster state
NodeMetadata.FORMAT.writeAndCleanup(
new NodeMetadata(persistedClusterStateService.getNodeId(), Version.CURRENT),
new NodeMetadata(
persistedClusterStateService.getNodeId(),
Version.CURRENT,
clusterState.metadata().oldestIndexVersion()
),
persistedClusterStateService.getDataPaths()
);
} catch (IOException e) {
Expand Down Expand Up @@ -541,7 +562,11 @@ public void setCurrentTerm(long currentTerm) {
getWriterSafe().writeFullStateAndCommit(currentTerm, lastAcceptedState);
} else {
writeNextStateFully = true; // in case of failure; this flag is cleared on success
getWriterSafe().writeIncrementalTermUpdateAndCommit(currentTerm, lastAcceptedState.version());
getWriterSafe().writeIncrementalTermUpdateAndCommit(
currentTerm,
lastAcceptedState.version(),
lastAcceptedState.metadata().oldestIndexVersion()
);
}
} catch (IOException e) {
throw new ElasticsearchException(e);
Expand Down
Loading