001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase.util.hbck;
020
021import java.io.IOException;
022import java.util.HashMap;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Map;
026import java.util.Map.Entry;
027import java.util.Set;
028
029import org.apache.hadoop.conf.Configuration;
030import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
031import org.apache.yetus.audience.InterfaceAudience;
032import org.apache.hadoop.hbase.client.ClusterConnection;
033import org.apache.hadoop.hbase.master.cleaner.ReplicationZKNodeCleaner;
034import org.apache.hadoop.hbase.replication.ReplicationQueueInfo;
035import org.apache.hadoop.hbase.util.HbckErrorReporter;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039/*
040 * Check and fix undeleted replication queues for removed peerId.
041 */
042@InterfaceAudience.Private
043public class ReplicationChecker {
044  private static final Logger LOG = LoggerFactory.getLogger(ReplicationChecker.class);
045
046  private final HbckErrorReporter errorReporter;
047  // replicator with its queueIds for removed peers
048  private Map<String, List<String>> undeletedQueueIds = new HashMap<>();
049  // replicator with its undeleted queueIds for removed peers in hfile-refs queue
050  private Set<String> undeletedHFileRefsQueueIds = new HashSet<>();
051  private final ReplicationZKNodeCleaner cleaner;
052
053  public ReplicationChecker(Configuration conf, ZKWatcher zkw, ClusterConnection connection,
054      HbckErrorReporter errorReporter) throws IOException {
055    this.cleaner = new ReplicationZKNodeCleaner(conf, zkw, connection);
056    this.errorReporter = errorReporter;
057  }
058
059  public boolean hasUnDeletedQueues() {
060    return errorReporter.getErrorList()
061        .contains(HbckErrorReporter.ERROR_CODE.UNDELETED_REPLICATION_QUEUE);
062  }
063
064  public void checkUnDeletedQueues() throws IOException {
065    undeletedQueueIds = cleaner.getUnDeletedQueues();
066    for (Entry<String, List<String>> replicatorAndQueueIds : undeletedQueueIds.entrySet()) {
067      String replicator = replicatorAndQueueIds.getKey();
068      for (String queueId : replicatorAndQueueIds.getValue()) {
069        ReplicationQueueInfo queueInfo = new ReplicationQueueInfo(queueId);
070        String msg = "Undeleted replication queue for removed peer found: "
071            + String.format("[removedPeerId=%s, replicator=%s, queueId=%s]", queueInfo.getPeerId(),
072              replicator, queueId);
073        errorReporter.reportError(HbckErrorReporter.ERROR_CODE.UNDELETED_REPLICATION_QUEUE,
074          msg);
075      }
076    }
077
078    checkUnDeletedHFileRefsQueues();
079  }
080
081  private void checkUnDeletedHFileRefsQueues() throws IOException {
082    undeletedHFileRefsQueueIds = cleaner.getUnDeletedHFileRefsQueues();
083    if (undeletedHFileRefsQueueIds != null && !undeletedHFileRefsQueueIds.isEmpty()) {
084      String msg = "Undeleted replication hfile-refs queue for removed peer found: "
085          + undeletedHFileRefsQueueIds + " under hfile-refs node";
086      errorReporter
087          .reportError(HbckErrorReporter.ERROR_CODE.UNDELETED_REPLICATION_QUEUE, msg);
088    }
089  }
090
091  public void fixUnDeletedQueues() throws IOException {
092    if (!undeletedQueueIds.isEmpty()) {
093      cleaner.removeQueues(undeletedQueueIds);
094    }
095    fixUnDeletedHFileRefsQueue();
096  }
097
098  private void fixUnDeletedHFileRefsQueue() throws IOException {
099    if (undeletedHFileRefsQueueIds != null && !undeletedHFileRefsQueueIds.isEmpty()) {
100      cleaner.removeHFileRefsQueues(undeletedHFileRefsQueueIds);
101    }
102  }
103}