View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.replication;
20  
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.ServerName;
25  
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.List;
29  
30  /**
31   * This class is responsible for the parsing logic for a znode representing a queue.
32   * It will extract the peerId if it's recovered as well as the dead region servers
33   * that were part of the queue's history.
34   */
35  public class ReplicationQueueInfo {
36    private static final Log LOG = LogFactory.getLog(ReplicationQueueInfo.class);
37  
38    private final String peerId;
39    private final String peerClusterZnode;
40    private boolean queueRecovered;
41    // List of all the dead region servers that had this queue (if recovered)
42    private List<String> deadRegionServers = new ArrayList<String>();
43  
44    /**
45     * The passed znode will be either the id of the peer cluster or
46     * the handling story of that queue in the form of id-servername-*
47     */
48    public ReplicationQueueInfo(String znode) {
49      this.peerClusterZnode = znode;
50      String[] parts = znode.split("-", 2);
51      this.queueRecovered = parts.length != 1;
52      this.peerId = this.queueRecovered ?
53          parts[0] : peerClusterZnode;
54      if (parts.length >= 2) {
55        // extract dead servers
56        extractDeadServersFromZNodeString(parts[1], this.deadRegionServers);
57      }
58    }
59  
60    /**
61     * Parse dead server names from znode string servername can contain "-" such as
62     * "ip-10-46-221-101.ec2.internal", so we need skip some "-" during parsing for the following
63     * cases: 2-ip-10-46-221-101.ec2.internal,52170,1364333181125-<server name>-...
64     */
65    private static void
66        extractDeadServersFromZNodeString(String deadServerListStr, List<String> result) {
67  
68      if(deadServerListStr == null || result == null || deadServerListStr.isEmpty()) return;
69  
70      // valid server name delimiter "-" has to be after "," in a server name
71      int seenCommaCnt = 0;
72      int startIndex = 0;
73      int len = deadServerListStr.length();
74  
75      for (int i = 0; i < len; i++) {
76        switch (deadServerListStr.charAt(i)) {
77        case ',':
78          seenCommaCnt += 1;
79          break;
80        case '-':
81          if(seenCommaCnt>=2) {
82            if (i > startIndex) {
83              String serverName = deadServerListStr.substring(startIndex, i);
84              if(ServerName.isFullServerName(serverName)){
85                result.add(serverName);
86              } else {
87                LOG.error("Found invalid server name:" + serverName);
88              }
89              startIndex = i + 1;
90            }
91            seenCommaCnt = 0;
92          }
93          break;
94        default:
95          break;
96        }
97      }
98  
99      // add tail
100     if(startIndex < len - 1){
101       String serverName = deadServerListStr.substring(startIndex, len);
102       if(ServerName.isFullServerName(serverName)){
103         result.add(serverName);
104       } else {
105         LOG.error("Found invalid server name at the end:" + serverName);
106       }
107     }
108 
109     LOG.debug("Found dead servers:" + result);
110   }
111 
112   public List<String> getDeadRegionServers() {
113     return Collections.unmodifiableList(this.deadRegionServers);
114   }
115 
116   public String getPeerId() {
117     return this.peerId;
118   }
119 
120   public String getPeerClusterZnode() {
121     return this.peerClusterZnode;
122   }
123 
124   public boolean isQueueRecovered() {
125     return queueRecovered;
126   }
127 }