001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.master; 020 021import java.io.IOException; 022import java.util.List; 023import org.apache.hadoop.hbase.HConstants; 024import org.apache.hadoop.hbase.ServerName; 025import org.apache.hadoop.hbase.client.RegionInfo; 026import org.apache.hadoop.hbase.client.RegionInfoBuilder; 027import org.apache.hadoop.hbase.client.RegionReplicaUtil; 028import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 029import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; 030import org.apache.hadoop.hbase.zookeeper.ZKUtil; 031import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 032import org.apache.yetus.audience.InterfaceAudience; 033import org.apache.zookeeper.KeeperException; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Used by the HMaster on startup to split meta logs and assign the meta table. 039 */ 040@InterfaceAudience.Private 041class MasterMetaBootstrap { 042 private static final Logger LOG = LoggerFactory.getLogger(MasterMetaBootstrap.class); 043 044 private final HMaster master; 045 046 public MasterMetaBootstrap(HMaster master) { 047 this.master = master; 048 } 049 050 /** 051 * For assigning hbase:meta replicas only. 052 * TODO: The way this assign runs, nothing but chance to stop all replicas showing up on same 053 * server as the hbase:meta region. 054 */ 055 void assignMetaReplicas() 056 throws IOException, InterruptedException, KeeperException { 057 int numReplicas = master.getConfiguration().getInt(HConstants.META_REPLICAS_NUM, 058 HConstants.DEFAULT_META_REPLICA_NUM); 059 if (numReplicas <= 1) { 060 // No replicaas to assign. Return. 061 return; 062 } 063 final AssignmentManager assignmentManager = master.getAssignmentManager(); 064 if (!assignmentManager.isMetaLoaded()) { 065 throw new IllegalStateException("hbase:meta must be initialized first before we can " + 066 "assign out its replicas"); 067 } 068 ServerName metaServername = MetaTableLocator.getMetaRegionLocation(this.master.getZooKeeper()); 069 for (int i = 1; i < numReplicas; i++) { 070 // Get current meta state for replica from zk. 071 RegionState metaState = MetaTableLocator.getMetaRegionState(master.getZooKeeper(), i); 072 RegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica( 073 RegionInfoBuilder.FIRST_META_REGIONINFO, i); 074 LOG.debug(hri.getRegionNameAsString() + " replica region state from zookeeper=" + metaState); 075 if (metaServername.equals(metaState.getServerName())) { 076 metaState = null; 077 LOG.info(hri.getRegionNameAsString() + 078 " old location is same as current hbase:meta location; setting location as null..."); 079 } 080 // These assigns run inline. All is blocked till they complete. Only interrupt is shutting 081 // down hosting server which calls AM#stop. 082 if (metaState != null && metaState.getServerName() != null) { 083 // Try to retain old assignment. 084 assignmentManager.assignAsync(hri, metaState.getServerName()); 085 } else { 086 assignmentManager.assignAsync(hri); 087 } 088 } 089 unassignExcessMetaReplica(numReplicas); 090 } 091 092 private void unassignExcessMetaReplica(int numMetaReplicasConfigured) { 093 final ZKWatcher zooKeeper = master.getZooKeeper(); 094 // unassign the unneeded replicas (for e.g., if the previous master was configured 095 // with a replication of 3 and now it is 2, we need to unassign the 1 unneeded replica) 096 try { 097 List<String> metaReplicaZnodes = zooKeeper.getMetaReplicaNodes(); 098 for (String metaReplicaZnode : metaReplicaZnodes) { 099 int replicaId = zooKeeper.getZNodePaths().getMetaReplicaIdFromZnode(metaReplicaZnode); 100 if (replicaId >= numMetaReplicasConfigured) { 101 RegionState r = MetaTableLocator.getMetaRegionState(zooKeeper, replicaId); 102 LOG.info("Closing excess replica of meta region " + r.getRegion()); 103 // send a close and wait for a max of 30 seconds 104 ServerManager.closeRegionSilentlyAndWait(master.getClusterConnection(), 105 r.getServerName(), r.getRegion(), 30000); 106 ZKUtil.deleteNode(zooKeeper, zooKeeper.getZNodePaths().getZNodeForReplica(replicaId)); 107 } 108 } 109 } catch (Exception ex) { 110 // ignore the exception since we don't want the master to be wedged due to potential 111 // issues in the cleanup of the extra regions. We can do that cleanup via hbck or manually 112 LOG.warn("Ignoring exception " + ex); 113 } 114 } 115}