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.replication; 020 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025 026import org.apache.yetus.audience.InterfaceAudience; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029import org.apache.hadoop.hbase.ServerName; 030 031/** 032 * This class is responsible for the parsing logic for a znode representing a queue. 033 * It will extract the peerId if it's recovered as well as the dead region servers 034 * that were part of the queue's history. 035 */ 036@InterfaceAudience.Private 037public class ReplicationQueueInfo { 038 private static final Logger LOG = LoggerFactory.getLogger(ReplicationQueueInfo.class); 039 040 private final String peerId; 041 private final String peerClusterZnode; 042 private boolean queueRecovered; 043 // List of all the dead region servers that had this queue (if recovered) 044 private List<ServerName> deadRegionServers = new ArrayList<>(); 045 046 /** 047 * The passed znode will be either the id of the peer cluster or 048 * the handling story of that queue in the form of id-servername-* 049 */ 050 public ReplicationQueueInfo(String znode) { 051 this.peerClusterZnode = znode; 052 String[] parts = znode.split("-", 2); 053 this.queueRecovered = parts.length != 1; 054 this.peerId = this.queueRecovered ? 055 parts[0] : peerClusterZnode; 056 if (parts.length >= 2) { 057 // extract dead servers 058 extractDeadServersFromZNodeString(parts[1], this.deadRegionServers); 059 } 060 } 061 062 /** 063 * Parse dead server names from znode string servername can contain "-" such as 064 * "ip-10-46-221-101.ec2.internal", so we need skip some "-" during parsing for the following 065 * cases: 2-ip-10-46-221-101.ec2.internal,52170,1364333181125-<server name>-... 066 */ 067 private static void 068 extractDeadServersFromZNodeString(String deadServerListStr, List<ServerName> result) { 069 070 if(deadServerListStr == null || result == null || deadServerListStr.isEmpty()) return; 071 072 // valid server name delimiter "-" has to be after "," in a server name 073 int seenCommaCnt = 0; 074 int startIndex = 0; 075 int len = deadServerListStr.length(); 076 077 for (int i = 0; i < len; i++) { 078 switch (deadServerListStr.charAt(i)) { 079 case ',': 080 seenCommaCnt += 1; 081 break; 082 case '-': 083 if(seenCommaCnt>=2) { 084 if (i > startIndex) { 085 String serverName = deadServerListStr.substring(startIndex, i); 086 if(ServerName.isFullServerName(serverName)){ 087 result.add(ServerName.valueOf(serverName)); 088 } else { 089 LOG.error("Found invalid server name:" + serverName); 090 } 091 startIndex = i + 1; 092 } 093 seenCommaCnt = 0; 094 } 095 break; 096 default: 097 break; 098 } 099 } 100 101 // add tail 102 if(startIndex < len - 1){ 103 String serverName = deadServerListStr.substring(startIndex, len); 104 if(ServerName.isFullServerName(serverName)){ 105 result.add(ServerName.valueOf(serverName)); 106 } else { 107 LOG.error("Found invalid server name at the end:" + serverName); 108 } 109 } 110 111 LOG.debug("Found dead servers:" + result); 112 } 113 114 public List<ServerName> getDeadRegionServers() { 115 return Collections.unmodifiableList(this.deadRegionServers); 116 } 117 118 public String getPeerId() { 119 return this.peerId; 120 } 121 122 public String getPeerClusterZnode() { 123 return this.peerClusterZnode; 124 } 125 126 public boolean isQueueRecovered() { 127 return queueRecovered; 128 } 129}