Search in sources :

Example 86 with ZkNodeProps

use of org.apache.solr.common.cloud.ZkNodeProps in project lucene-solr by apache.

the class ZkController method register.

/**
   * Register shard with ZooKeeper.
   *
   * @return the shardId for the SolrCore
   */
public String register(String coreName, final CoreDescriptor desc, boolean recoverReloadedCores, boolean afterExpiration, boolean skipRecovery) throws Exception {
    try (SolrCore core = cc.getCore(desc.getName())) {
        MDCLoggingContext.setCore(core);
    }
    try {
        // pre register has published our down state
        final String baseUrl = getBaseUrl();
        final CloudDescriptor cloudDesc = desc.getCloudDescriptor();
        final String collection = cloudDesc.getCollectionName();
        final String coreZkNodeName = desc.getCloudDescriptor().getCoreNodeName();
        assert coreZkNodeName != null : "we should have a coreNodeName by now";
        String shardId = cloudDesc.getShardId();
        Map<String, Object> props = new HashMap<>();
        // we only put a subset of props into the leader node
        props.put(ZkStateReader.BASE_URL_PROP, baseUrl);
        props.put(ZkStateReader.CORE_NAME_PROP, coreName);
        props.put(ZkStateReader.NODE_NAME_PROP, getNodeName());
        log.debug("Register replica - core:{} address:{} collection:{} shard:{}", coreName, baseUrl, cloudDesc.getCollectionName(), shardId);
        ZkNodeProps leaderProps = new ZkNodeProps(props);
        try {
            // If we're a preferred leader, insert ourselves at the head of the queue
            boolean joinAtHead = false;
            Replica replica = zkStateReader.getClusterState().getReplica(collection, coreZkNodeName);
            if (replica != null) {
                joinAtHead = replica.getBool(SliceMutator.PREFERRED_LEADER_PROP, false);
            }
            //TODO WHy would replica be null?
            if (replica == null || replica.getType() != Type.PULL) {
                joinElection(desc, afterExpiration, joinAtHead);
            } else if (replica.getType() == Type.PULL) {
                if (joinAtHead) {
                    log.warn("Replica {} was designated as preferred leader but it's type is {}, It won't join election", coreZkNodeName, Type.PULL);
                }
                log.debug("Replica {} skipping election because it's type is {}", coreZkNodeName, Type.PULL);
                startReplicationFromLeader(coreName, false);
            }
        } catch (InterruptedException e) {
            // Restore the interrupted status
            Thread.currentThread().interrupt();
            throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
        } catch (KeeperException | IOException e) {
            throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
        }
        // in this case, we want to wait for the leader as long as the leader might
        // wait for a vote, at least - but also long enough that a large cluster has
        // time to get its act together
        String leaderUrl = getLeader(cloudDesc, leaderVoteWait + 600000);
        String ourUrl = ZkCoreNodeProps.getCoreUrl(baseUrl, coreName);
        log.debug("We are " + ourUrl + " and leader is " + leaderUrl);
        boolean isLeader = leaderUrl.equals(ourUrl);
        Replica.Type replicaType = zkStateReader.getClusterState().getCollection(collection).getReplica(coreZkNodeName).getType();
        assert !(isLeader && replicaType == Type.PULL) : "Pull replica became leader!";
        try (SolrCore core = cc.getCore(desc.getName())) {
            // recover from local transaction log and wait for it to complete before
            // going active
            // TODO: should this be moved to another thread? To recoveryStrat?
            // TODO: should this actually be done earlier, before (or as part of)
            // leader election perhaps?
            UpdateLog ulog = core.getUpdateHandler().getUpdateLog();
            boolean isTlogReplicaAndNotLeader = replicaType == Replica.Type.TLOG && !isLeader;
            if (isTlogReplicaAndNotLeader) {
                String commitVersion = ReplicateFromLeader.getCommitVersion(core);
                if (commitVersion != null) {
                    ulog.copyOverOldUpdates(Long.parseLong(commitVersion));
                }
            }
            // we will call register again after zk expiration and on reload
            if (!afterExpiration && !core.isReloaded() && ulog != null && !isTlogReplicaAndNotLeader) {
                // disable recovery in case shard is in construction state (for shard splits)
                Slice slice = getClusterState().getSlice(collection, shardId);
                if (slice.getState() != Slice.State.CONSTRUCTION || !isLeader) {
                    Future<UpdateLog.RecoveryInfo> recoveryFuture = core.getUpdateHandler().getUpdateLog().recoverFromLog();
                    if (recoveryFuture != null) {
                        log.info("Replaying tlog for " + ourUrl + " during startup... NOTE: This can take a while.");
                        // NOTE: this could potentially block for
                        recoveryFuture.get();
                    // minutes or more!
                    // TODO: public as recovering in the mean time?
                    // TODO: in the future we could do peersync in parallel with recoverFromLog
                    } else {
                        log.debug("No LogReplay needed for core={} baseURL={}", core.getName(), baseUrl);
                    }
                }
            }
            boolean didRecovery = checkRecovery(recoverReloadedCores, isLeader, skipRecovery, collection, coreZkNodeName, core, cc, afterExpiration);
            if (!didRecovery) {
                if (isTlogReplicaAndNotLeader) {
                    startReplicationFromLeader(coreName, true);
                }
                publish(desc, Replica.State.ACTIVE);
            }
            core.getCoreDescriptor().getCloudDescriptor().setHasRegistered(true);
        }
        // make sure we have an update cluster state right away
        zkStateReader.forceUpdateCollection(collection);
        return shardId;
    } finally {
        MDCLoggingContext.clear();
    }
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) SolrCore(org.apache.solr.core.SolrCore) ZkNodeProps(org.apache.solr.common.cloud.ZkNodeProps) IOException(java.io.IOException) Type(org.apache.solr.common.cloud.Replica.Type) Replica(org.apache.solr.common.cloud.Replica) ZooKeeperException(org.apache.solr.common.cloud.ZooKeeperException) Slice(org.apache.solr.common.cloud.Slice) UpdateLog(org.apache.solr.update.UpdateLog) ZooKeeperException(org.apache.solr.common.cloud.ZooKeeperException) KeeperException(org.apache.zookeeper.KeeperException)

Example 87 with ZkNodeProps

use of org.apache.solr.common.cloud.ZkNodeProps in project lucene-solr by apache.

the class ZkController method joinElection.

private void joinElection(CoreDescriptor cd, boolean afterExpiration, boolean joinAtHead) throws InterruptedException, KeeperException, IOException {
    // look for old context - if we find it, cancel it
    String collection = cd.getCloudDescriptor().getCollectionName();
    final String coreNodeName = cd.getCloudDescriptor().getCoreNodeName();
    ContextKey contextKey = new ContextKey(collection, coreNodeName);
    ElectionContext prevContext = electionContexts.get(contextKey);
    if (prevContext != null) {
        prevContext.cancelElection();
    }
    String shardId = cd.getCloudDescriptor().getShardId();
    Map<String, Object> props = new HashMap<>();
    // we only put a subset of props into the leader node
    props.put(ZkStateReader.BASE_URL_PROP, getBaseUrl());
    props.put(ZkStateReader.CORE_NAME_PROP, cd.getName());
    props.put(ZkStateReader.NODE_NAME_PROP, getNodeName());
    props.put(ZkStateReader.CORE_NODE_NAME_PROP, coreNodeName);
    ZkNodeProps ourProps = new ZkNodeProps(props);
    LeaderElector leaderElector = new LeaderElector(zkClient, contextKey, electionContexts);
    ElectionContext context = new ShardLeaderElectionContext(leaderElector, shardId, collection, coreNodeName, ourProps, this, cc);
    leaderElector.setup(context);
    electionContexts.put(contextKey, context);
    leaderElector.joinElection(context, false, joinAtHead);
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ZkNodeProps(org.apache.solr.common.cloud.ZkNodeProps)

Example 88 with ZkNodeProps

use of org.apache.solr.common.cloud.ZkNodeProps in project lucene-solr by apache.

the class ReplicaMutator method checkAndCompleteShardSplit.

private DocCollection checkAndCompleteShardSplit(ClusterState prevState, DocCollection collection, String coreNodeName, String sliceName, Replica replica) {
    Slice slice = collection.getSlice(sliceName);
    Map<String, Object> sliceProps = slice.getProperties();
    if (slice.getState() == Slice.State.RECOVERY) {
        log.info("Shard: {} is in recovery state", sliceName);
        // is this replica active?
        if (replica.getState() == Replica.State.ACTIVE) {
            log.info("Shard: {} is in recovery state and coreNodeName: {} is active", sliceName, coreNodeName);
            // are all other replicas also active?
            boolean allActive = true;
            for (Map.Entry<String, Replica> entry : slice.getReplicasMap().entrySet()) {
                if (coreNodeName.equals(entry.getKey()))
                    continue;
                if (entry.getValue().getState() != Replica.State.ACTIVE) {
                    allActive = false;
                    break;
                }
            }
            if (allActive) {
                log.info("Shard: {} - all replicas are active. Finding status of fellow sub-shards", sliceName);
                // find out about other sub shards
                Map<String, Slice> allSlicesCopy = new HashMap<>(collection.getSlicesMap());
                List<Slice> subShardSlices = new ArrayList<>();
                outer: for (Map.Entry<String, Slice> entry : allSlicesCopy.entrySet()) {
                    if (sliceName.equals(entry.getKey()))
                        continue;
                    Slice otherSlice = entry.getValue();
                    if (otherSlice.getState() == Slice.State.RECOVERY) {
                        if (slice.getParent() != null && slice.getParent().equals(otherSlice.getParent())) {
                            log.info("Shard: {} - Fellow sub-shard: {} found", sliceName, otherSlice.getName());
                            // this is a fellow sub shard so check if all replicas are active
                            for (Map.Entry<String, Replica> sliceEntry : otherSlice.getReplicasMap().entrySet()) {
                                if (sliceEntry.getValue().getState() != Replica.State.ACTIVE) {
                                    allActive = false;
                                    break outer;
                                }
                            }
                            log.info("Shard: {} - Fellow sub-shard: {} has all replicas active", sliceName, otherSlice.getName());
                            subShardSlices.add(otherSlice);
                        }
                    }
                }
                if (allActive) {
                    // hurray, all sub shard replicas are active
                    log.info("Shard: {} - All replicas across all fellow sub-shards are now ACTIVE.", sliceName);
                    String parentSliceName = (String) sliceProps.remove(Slice.PARENT);
                    // now lets see if the parent leader is still the same or else there's a chance of data loss
                    // see SOLR-9438 for details
                    String shardParentZkSession = (String) sliceProps.remove("shard_parent_zk_session");
                    String shardParentNode = (String) sliceProps.remove("shard_parent_node");
                    boolean isLeaderSame = true;
                    if (shardParentNode != null && shardParentZkSession != null) {
                        log.info("Checking whether sub-shard leader node is still the same one at {} with ZK session id {}", shardParentNode, shardParentZkSession);
                        try {
                            Stat leaderZnodeStat = zkStateReader.getZkClient().exists(ZkStateReader.LIVE_NODES_ZKNODE + "/" + shardParentNode, null, true);
                            if (leaderZnodeStat == null) {
                                log.error("The shard leader node: {} is not live anymore!", shardParentNode);
                                isLeaderSame = false;
                            } else if (leaderZnodeStat.getEphemeralOwner() != Long.parseLong(shardParentZkSession)) {
                                log.error("The zk session id for shard leader node: {} has changed from {} to {}", shardParentNode, shardParentZkSession, leaderZnodeStat.getEphemeralOwner());
                                isLeaderSame = false;
                            }
                        } catch (Exception e) {
                            log.warn("Error occurred while checking if parent shard node is still live with the same zk session id. " + "We cannot switch shard states at this time.", e);
                            // we aren't going to make any changes right now
                            return collection;
                        }
                    }
                    if (isLeaderSame) {
                        log.info("Sub-shard leader node is still the same one at {} with ZK session id {}. Preparing to switch shard states.", shardParentNode, shardParentZkSession);
                        Map<String, Object> propMap = new HashMap<>();
                        propMap.put(Overseer.QUEUE_OPERATION, "updateshardstate");
                        propMap.put(parentSliceName, Slice.State.INACTIVE.toString());
                        propMap.put(sliceName, Slice.State.ACTIVE.toString());
                        for (Slice subShardSlice : subShardSlices) {
                            propMap.put(subShardSlice.getName(), Slice.State.ACTIVE.toString());
                        }
                        propMap.put(ZkStateReader.COLLECTION_PROP, collection.getName());
                        ZkNodeProps m = new ZkNodeProps(propMap);
                        return new SliceMutator(zkStateReader).updateShardState(prevState, m).collection;
                    } else {
                        // we must mark the shard split as failed by switching sub-shards to recovery_failed state
                        Map<String, Object> propMap = new HashMap<>();
                        propMap.put(Overseer.QUEUE_OPERATION, "updateshardstate");
                        propMap.put(sliceName, Slice.State.RECOVERY_FAILED.toString());
                        for (Slice subShardSlice : subShardSlices) {
                            propMap.put(subShardSlice.getName(), Slice.State.RECOVERY_FAILED.toString());
                        }
                        propMap.put(ZkStateReader.COLLECTION_PROP, collection.getName());
                        ZkNodeProps m = new ZkNodeProps(propMap);
                        return new SliceMutator(zkStateReader).updateShardState(prevState, m).collection;
                    }
                }
            }
        }
    }
    return collection;
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ZkNodeProps(org.apache.solr.common.cloud.ZkNodeProps) ArrayList(java.util.ArrayList) Replica(org.apache.solr.common.cloud.Replica) SolrException(org.apache.solr.common.SolrException) Stat(org.apache.zookeeper.data.Stat) Slice(org.apache.solr.common.cloud.Slice) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 89 with ZkNodeProps

use of org.apache.solr.common.cloud.ZkNodeProps in project lucene-solr by apache.

the class ReplicaMutator method updateState.

protected ZkWriteCommand updateState(final ClusterState prevState, ZkNodeProps message) {
    final String cName = message.getStr(ZkStateReader.COLLECTION_PROP);
    if (!checkCollectionKeyExistence(message))
        return ZkStateWriter.NO_OP;
    Integer numShards = message.getInt(ZkStateReader.NUM_SHARDS_PROP, null);
    log.debug("Update state numShards={} message={}", numShards, message);
    List<String> shardNames = new ArrayList<>();
    ZkWriteCommand writeCommand = null;
    ClusterState newState = null;
    //collection does not yet exist, create placeholders if num shards is specified
    boolean collectionExists = prevState.hasCollection(cName);
    if (!collectionExists && numShards != null) {
        ClusterStateMutator.getShardNames(numShards, shardNames);
        Map<String, Object> createMsg = Utils.makeMap(NAME, cName);
        createMsg.putAll(message.getProperties());
        writeCommand = new ClusterStateMutator(zkStateReader).createCollection(prevState, new ZkNodeProps(createMsg));
        DocCollection collection = writeCommand.collection;
        newState = ClusterStateMutator.newState(prevState, cName, collection);
    }
    return updateState(newState != null ? newState : prevState, message, cName, numShards, collectionExists);
}
Also used : ClusterState(org.apache.solr.common.cloud.ClusterState) ZkNodeProps(org.apache.solr.common.cloud.ZkNodeProps) ArrayList(java.util.ArrayList) DocCollection(org.apache.solr.common.cloud.DocCollection)

Example 90 with ZkNodeProps

use of org.apache.solr.common.cloud.ZkNodeProps in project lucene-solr by apache.

the class CollectionsAPIDistributedZkTest method testSpecificConfigsets.

@Test
public void testSpecificConfigsets() throws Exception {
    CollectionAdminRequest.createCollection("withconfigset2", "conf2", 1, 1).process(cluster.getSolrClient());
    byte[] data = zkClient().getData(ZkStateReader.COLLECTIONS_ZKNODE + "/" + "withconfigset2", null, null, true);
    assertNotNull(data);
    ZkNodeProps props = ZkNodeProps.load(data);
    String configName = props.getStr(ZkController.CONFIGNAME_PROP);
    assertEquals("conf2", configName);
}
Also used : ZkNodeProps(org.apache.solr.common.cloud.ZkNodeProps) Test(org.junit.Test)

Aggregations

ZkNodeProps (org.apache.solr.common.cloud.ZkNodeProps)91 SolrException (org.apache.solr.common.SolrException)35 HashMap (java.util.HashMap)28 Replica (org.apache.solr.common.cloud.Replica)22 ZkStateReader (org.apache.solr.common.cloud.ZkStateReader)20 ArrayList (java.util.ArrayList)19 Slice (org.apache.solr.common.cloud.Slice)19 KeeperException (org.apache.zookeeper.KeeperException)19 ModifiableSolrParams (org.apache.solr.common.params.ModifiableSolrParams)16 Test (org.junit.Test)16 DocCollection (org.apache.solr.common.cloud.DocCollection)15 SolrZkClient (org.apache.solr.common.cloud.SolrZkClient)14 Map (java.util.Map)13 ClusterState (org.apache.solr.common.cloud.ClusterState)13 IOException (java.io.IOException)10 ZkCoreNodeProps (org.apache.solr.common.cloud.ZkCoreNodeProps)10 ZooKeeperException (org.apache.solr.common.cloud.ZooKeeperException)10 NamedList (org.apache.solr.common.util.NamedList)10 HttpSolrClient (org.apache.solr.client.solrj.impl.HttpSolrClient)9 SolrCore (org.apache.solr.core.SolrCore)8