-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Close Index API] Add unique UUID to ClusterBlock #36775
Changes from 1 commit
07d9144
e976493
62000b2
79e2e99
48c9269
590e3e6
ec7cc6f
7caf533
a2af914
a2f735e
a1c1856
faab39a
9d40a5d
349f254
6b10564
692ea01
798b4f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ | |
import org.elasticsearch.cluster.service.ClusterService; | ||
import org.elasticsearch.common.Nullable; | ||
import org.elasticsearch.common.Priority; | ||
import org.elasticsearch.common.Strings; | ||
import org.elasticsearch.common.UUIDs; | ||
import org.elasticsearch.common.ValidationException; | ||
import org.elasticsearch.common.collect.ImmutableOpenIntMap; | ||
|
@@ -68,6 +69,7 @@ | |
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.EnumSet; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
|
@@ -147,9 +149,30 @@ public void clusterStateProcessed(final String source, final ClusterState oldSta | |
.execute(new WaitForClosedBlocksApplied(blockedIndices, timeout, | ||
ActionListener.wrap(results -> | ||
clusterService.submitStateUpdateTask("close-indices", new ClusterStateUpdateTask(Priority.URGENT) { | ||
|
||
boolean acknowledged = true; | ||
|
||
@Override | ||
public ClusterState execute(final ClusterState currentState) throws Exception { | ||
final ClusterState updatedState = closeRoutingTable(currentState, blockedIndices, results); | ||
// Combine the results of the verify shards before close actions with the cluster state changes | ||
// to determine if the current close action effectively closed all indices. | ||
for (Map.Entry<Index, AcknowledgedResponse> result : results.entrySet()) { | ||
IndexMetaData updatedMetaData = updatedState.metaData().index(result.getKey()); | ||
if (updatedMetaData != null) { | ||
if (result.getValue().isAcknowledged()) { | ||
if (updatedMetaData.getState() == IndexMetaData.State.CLOSE) { | ||
IndexMetaData previousMetaData = currentState.metaData().index(result.getKey()); | ||
if (previousMetaData != null) { | ||
acknowledged = (previousMetaData.getState() == IndexMetaData.State.OPEN); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow this logic here. Wouldn't it be much simpler just to say. If the index is closed at this point, all is good. If not, something must have gone wrong, thereby acked == false. This amounts to the following simple logic:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, let's do that. |
||
} | ||
} | ||
} else { | ||
acknowledged = false; | ||
break; | ||
} | ||
} | ||
} | ||
return allocationService.reroute(updatedState, "indices closed"); | ||
} | ||
|
||
|
@@ -161,7 +184,6 @@ public void onFailure(final String source, final Exception e) { | |
@Override | ||
public void clusterStateProcessed(final String source, | ||
final ClusterState oldState, final ClusterState newState) { | ||
boolean acknowledged = results.values().stream().allMatch(AcknowledgedResponse::isAcknowledged); | ||
listener.onResponse(new AcknowledgedResponse(acknowledged)); | ||
} | ||
}), | ||
|
@@ -242,10 +264,10 @@ static ClusterState addIndexClosedBlocks(final Index[] indices, final Map<Index, | |
blocks.removeIndexBlockWithId(index.getName(), INDEX_CLOSED_BLOCK_ID); | ||
routingTable.remove(index.getName()); | ||
indexBlock = INDEX_CLOSED_BLOCK; | ||
} | ||
if (indexBlock == null) { | ||
} else if (indexBlock == null) { | ||
// Create a new index closed block | ||
indexBlock = createIndexClosedBlock(); | ||
indexBlock = createIndexClosingBlock(); | ||
assert Strings.hasLength(indexBlock.uuid()) : "Closing block should have a UUID"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this assertion should also cover the case where
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure |
||
} | ||
blocks.addIndexBlock(index.getName(), indexBlock); | ||
blockedIndices.put(index, indexBlock); | ||
|
@@ -384,27 +406,26 @@ static ClusterState closeRoutingTable(final ClusterState currentState, | |
final boolean acknowledged = result.getValue().isAcknowledged(); | ||
try { | ||
if (acknowledged == false) { | ||
logger.debug("closing index {} failed", index); | ||
logger.debug("verification of shards before closing {} failed", index); | ||
continue; | ||
} | ||
final IndexMetaData indexMetaData = metadata.getSafe(index); | ||
if (indexMetaData.getState() == IndexMetaData.State.CLOSE) { | ||
logger.debug("closing index {} succeed but index is already closed", index); | ||
logger.debug("verification of shards before closing {} succeeded but index is already closed", index); | ||
assert currentState.blocks().hasIndexBlock(index.getName(), INDEX_CLOSED_BLOCK); | ||
continue; | ||
} | ||
final ClusterBlock closingBlock = blockedIndices.get(index); | ||
if (currentState.blocks().hasIndexBlock(index.getName(), closingBlock) == false) { | ||
logger.debug("closing index {} succeed but block has been removed in the mean time", index); | ||
logger.debug("verification of shards before closing {} succeeded but block has been removed in the meantime", index); | ||
continue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why has it succeeded here? The index is not closed and the block has disappeared, so it must have been reopened in the meanwhile. This should be counted as a failure, not a success. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the message in the log is confusing. What succeeded here is the verification of shards using the block that has now disappeared. I changed to change the log message.
I agree. I pushed a change that combines the results of the TransportVerifyShardBeforeCloseAction and the cluster state changes in order to determine if the current close action has indeed closed the index. |
||
} | ||
|
||
logger.debug("closing index {} succeed", index); | ||
logger.debug("closing index {} succeeded", index); | ||
blocks.removeIndexBlockWithId(index.getName(), INDEX_CLOSED_BLOCK_ID).addIndexBlock(index.getName(), INDEX_CLOSED_BLOCK); | ||
metadata.put(IndexMetaData.builder(indexMetaData).state(IndexMetaData.State.CLOSE)); | ||
routingTable.remove(index.getName()); | ||
closedIndices.add(index.getName()); | ||
|
||
} catch (final IndexNotFoundException e) { | ||
logger.debug("index {} has been deleted since it was blocked before closing, ignoring", index); | ||
} | ||
|
@@ -540,12 +561,10 @@ private static int getTotalShardCount(ClusterState state, Index index) { | |
* @return Generates a {@link ClusterBlock} that blocks read and write operations on soon-to-be-closed indices. The | ||
* cluster block is generated with the id value equals to {@link #INDEX_CLOSED_BLOCK_ID} and a unique UUID. | ||
*/ | ||
public static ClusterBlock createIndexClosedBlock() { | ||
final String description = "Index is blocked due to on-going index closing operation. Note that the closing process can take " + | ||
"time and writes operations are blocked in the meantime. Execute an open index request to unblock the index and allow writes " + | ||
"operation again. Execute a new close index request will try to close the index again."; | ||
return new ClusterBlock(INDEX_CLOSED_BLOCK_ID, UUIDs.randomBase64UUID(), description , false, false, false, | ||
RestStatus.FORBIDDEN, ClusterBlockLevel.READ_WRITE); | ||
public static ClusterBlock createIndexClosingBlock() { | ||
return new ClusterBlock(INDEX_CLOSED_BLOCK_ID, UUIDs.randomBase64UUID(), "index preparing to close. Reopen the index to allow " + | ||
"writes again or retry closing the index to fully close the index.", false, false, false, RestStatus.FORBIDDEN, | ||
EnumSet.of(ClusterBlockLevel.WRITE)); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how could this ever be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't, I tend to be too defensive on NPEs.