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