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 queue id 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 queueId; 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 queueId will be either the id of the peer or the handling story of that queue 048 * in the form of id-servername-* 049 */ 050 public ReplicationQueueInfo(String queueId) { 051 this.queueId = queueId; 052 String[] parts = queueId.split("-", 2); 053 this.queueRecovered = parts.length != 1; 054 this.peerId = this.queueRecovered ? parts[0] : queueId; 055 if (parts.length >= 2) { 056 // extract dead servers 057 extractDeadServersFromZNodeString(parts[1], this.deadRegionServers); 058 } 059 } 060 061 /** 062 * Parse dead server names from queue id. servername can contain "-" such as 063 * "ip-10-46-221-101.ec2.internal", so we need skip some "-" during parsing for the following 064 * cases: 2-ip-10-46-221-101.ec2.internal,52170,1364333181125-<server name>-... 065 */ 066 private static void 067 extractDeadServersFromZNodeString(String deadServerListStr, List<ServerName> result) { 068 069 if(deadServerListStr == null || result == null || deadServerListStr.isEmpty()) return; 070 071 // valid server name delimiter "-" has to be after "," in a server name 072 int seenCommaCnt = 0; 073 int startIndex = 0; 074 int len = deadServerListStr.length(); 075 076 for (int i = 0; i < len; i++) { 077 switch (deadServerListStr.charAt(i)) { 078 case ',': 079 seenCommaCnt += 1; 080 break; 081 case '-': 082 if(seenCommaCnt>=2) { 083 if (i > startIndex) { 084 String serverName = deadServerListStr.substring(startIndex, i); 085 if(ServerName.isFullServerName(serverName)){ 086 result.add(ServerName.valueOf(serverName)); 087 } else { 088 LOG.error("Found invalid server name:" + serverName); 089 } 090 startIndex = i + 1; 091 } 092 seenCommaCnt = 0; 093 } 094 break; 095 default: 096 break; 097 } 098 } 099 100 // add tail 101 if(startIndex < len - 1){ 102 String serverName = deadServerListStr.substring(startIndex, len); 103 if(ServerName.isFullServerName(serverName)){ 104 result.add(ServerName.valueOf(serverName)); 105 } else { 106 LOG.error("Found invalid server name at the end:" + serverName); 107 } 108 } 109 110 LOG.debug("Found dead servers:" + result); 111 } 112 113 public List<ServerName> getDeadRegionServers() { 114 return Collections.unmodifiableList(this.deadRegionServers); 115 } 116 117 public String getPeerId() { 118 return this.peerId; 119 } 120 121 public String getQueueId() { 122 return this.queueId; 123 } 124 125 public boolean isQueueRecovered() { 126 return queueRecovered; 127 } 128}