package io.crate.metadata.shard.unassigned; import io.crate.blob.v2.BlobIndex; import io.crate.metadata.PartitionName; import io.crate.metadata.Schemas; import io.crate.metadata.blob.BlobSchemaInfo; import org.apache.lucene.util.BytesRef; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.routing.ShardRoutingState; import org.elasticsearch.index.shard.ShardId; import java.util.regex.Matcher; /** * This class represents an unassigned shard * <p> * An UnassignedShard is a shard that is not yet assigned to any node and therefore doesn't really exist anywhere. * <p> * The {@link io.crate.metadata.sys.SysShardsTableInfo} will encode any shards that aren't assigned to a node * by negating them using {@link #markUnassigned(int)} * <p> * The {@link io.crate.operation.collect.sources.ShardCollectSource} will then collect UnassignedShard * instances for all shardIds that are negative. * <p> * This is only for "select ... from sys.shards" queries. */ public class UnassignedShard { public static boolean isUnassigned(int shardId) { return shardId < 0; } /** * valid shard ids are vom 0 to int.max * this method negates a shard id (0 becomes -1, 1 becomes -2, etc.) * <p> * if the given id is already negative it is returned as is */ public static int markUnassigned(int id) { if (id >= 0) { return (id + 1) * -1; } return id; } /** * converts negative shard ids back to positive * (-1 becomes 0, -2 becomes 1 - the opposite of {@link #markUnassigned(int)} */ public static int markAssigned(int shard) { if (shard < 0) { return (shard * -1) - 1; } return shard; } private final String schemaName; private final String tableName; private final Boolean primary; private final int id; private final String partitionIdent; private final BytesRef state; private static final BytesRef UNASSIGNED = new BytesRef("UNASSIGNED"); private static final BytesRef INITIALIZING = new BytesRef("INITIALIZING"); private Boolean orphanedPartition = false; public UnassignedShard(ShardId shardId, ClusterService clusterService, Boolean primary, ShardRoutingState state) { String index = shardId.getIndexName(); boolean isBlobIndex = BlobIndex.isBlobIndex(index); String tableName; String ident = ""; if (isBlobIndex) { this.schemaName = BlobSchemaInfo.NAME; tableName = BlobIndex.stripPrefix(index); } else if (PartitionName.isPartition(index)) { PartitionName partitionName = PartitionName.fromIndexOrTemplate(index); schemaName = partitionName.tableIdent().schema(); tableName = partitionName.tableIdent().name(); ident = partitionName.ident(); if (!clusterService.state().metaData().hasConcreteIndex(tableName)) { orphanedPartition = true; } } else { Matcher matcher = Schemas.SCHEMA_PATTERN.matcher(index); if (matcher.matches()) { this.schemaName = matcher.group(1); tableName = matcher.group(2); } else { this.schemaName = Schemas.DEFAULT_SCHEMA_NAME; tableName = index; } } this.tableName = tableName; partitionIdent = ident; this.primary = primary; this.id = shardId.id(); this.state = state == ShardRoutingState.UNASSIGNED ? UNASSIGNED : INITIALIZING; } public String tableName() { return tableName; } public int id() { return id; } public String schemaName() { return schemaName; } public String partitionIdent() { return partitionIdent; } public Boolean primary() { return primary; } public BytesRef state() { return state; } public Boolean orphanedPartition() { return orphanedPartition; } }