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 066 if (deadServerListStr == null || result == null || deadServerListStr.isEmpty()) return; 067 068 // valid server name delimiter "-" has to be after "," in a server name 069 int seenCommaCnt = 0; 070 int startIndex = 0; 071 int len = deadServerListStr.length(); 072 073 for (int i = 0; i < len; i++) { 074 switch (deadServerListStr.charAt(i)) { 075 case ',': 076 seenCommaCnt += 1; 077 break; 078 case '-': 079 if (seenCommaCnt >= 2) { 080 if (i > startIndex) { 081 String serverName = deadServerListStr.substring(startIndex, i); 082 if (ServerName.isFullServerName(serverName)) { 083 result.add(ServerName.valueOf(serverName)); 084 } else { 085 LOG.error("Found invalid server name:" + serverName); 086 } 087 startIndex = i + 1; 088 } 089 seenCommaCnt = 0; 090 } 091 break; 092 default: 093 break; 094 } 095 } 096 097 // add tail 098 if (startIndex < len - 1) { 099 String serverName = deadServerListStr.substring(startIndex, len); 100 if (ServerName.isFullServerName(serverName)) { 101 result.add(ServerName.valueOf(serverName)); 102 } else { 103 LOG.error("Found invalid server name at the end:" + serverName); 104 } 105 } 106 107 LOG.debug("Found dead servers:" + result); 108 } 109 110 public List<ServerName> getDeadRegionServers() { 111 return Collections.unmodifiableList(this.deadRegionServers); 112 } 113 114 public String getPeerId() { 115 return this.peerId; 116 } 117 118 public String getQueueId() { 119 return this.queueId; 120 } 121 122 public boolean isQueueRecovered() { 123 return queueRecovered; 124 } 125}