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  import java.util.List;
22  
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.Abortable;
25  import org.apache.hadoop.hbase.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
27  import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
28  import org.apache.hadoop.hbase.zookeeper.ZKConfig;
29  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
30  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
31  import org.apache.zookeeper.KeeperException;
32  
33  import com.google.common.annotations.VisibleForTesting;
34  
35  
36  /**
37   * This is a base class for maintaining replication state in zookeeper.
38   */
39  @InterfaceAudience.Private
40  public abstract class ReplicationStateZKBase {
41  
42    /**
43     * The name of the znode that contains the replication status of a remote slave (i.e. peer)
44     * cluster.
45     */
46    protected final String peerStateNodeName;
47    /** The name of the base znode that contains all replication state. */
48    protected final String replicationZNode;
49    /** The name of the znode that contains a list of all remote slave (i.e. peer) clusters. */
50    protected final String peersZNode;
51    /** The name of the znode that contains all replication queues */
52    protected final String queuesZNode;
53    /** The name of the znode that contains queues of hfile references to be replicated */
54    protected final String hfileRefsZNode;
55    /** The cluster key of the local cluster */
56    protected final String ourClusterKey;
57    /** The name of the znode that contains tableCFs */
58    protected final String tableCFsNodeName;
59  
60    protected final ZooKeeperWatcher zookeeper;
61    protected final Configuration conf;
62    protected final Abortable abortable;
63  
64    // Public for testing
65    public static final byte[] ENABLED_ZNODE_BYTES =
66        toByteArray(ZooKeeperProtos.ReplicationState.State.ENABLED);
67    public static final byte[] DISABLED_ZNODE_BYTES =
68        toByteArray(ZooKeeperProtos.ReplicationState.State.DISABLED);
69    public static final String ZOOKEEPER_ZNODE_REPLICATION_HFILE_REFS_KEY =
70        "zookeeper.znode.replication.hfile.refs";
71    public static final String ZOOKEEPER_ZNODE_REPLICATION_HFILE_REFS_DEFAULT = "hfile-refs";
72  
73    public ReplicationStateZKBase(ZooKeeperWatcher zookeeper, Configuration conf,
74        Abortable abortable) {
75      this.zookeeper = zookeeper;
76      this.conf = conf;
77      this.abortable = abortable;
78  
79      String replicationZNodeName = conf.get("zookeeper.znode.replication", "replication");
80      String peersZNodeName = conf.get("zookeeper.znode.replication.peers", "peers");
81      String queuesZNodeName = conf.get("zookeeper.znode.replication.rs", "rs");
82      String hfileRefsZNodeName = conf.get(ZOOKEEPER_ZNODE_REPLICATION_HFILE_REFS_KEY,
83        ZOOKEEPER_ZNODE_REPLICATION_HFILE_REFS_DEFAULT);
84      this.peerStateNodeName = conf.get("zookeeper.znode.replication.peers.state", "peer-state");
85      this.tableCFsNodeName = conf.get("zookeeper.znode.replication.peers.tableCFs", "tableCFs");
86      this.ourClusterKey = ZKConfig.getZooKeeperClusterKey(this.conf);
87      this.replicationZNode = ZKUtil.joinZNode(this.zookeeper.baseZNode, replicationZNodeName);
88      this.peersZNode = ZKUtil.joinZNode(replicationZNode, peersZNodeName);
89      this.queuesZNode = ZKUtil.joinZNode(replicationZNode, queuesZNodeName);
90      this.hfileRefsZNode = ZKUtil.joinZNode(replicationZNode, hfileRefsZNodeName);
91    }
92  
93    /**
94     * Subclasses that use ZK explicitly can just call this directly while classes
95     * that are trying to hide internal details of storage can wrap the KeeperException
96     * into a ReplicationException or something else.
97     */
98    protected List<String> getListOfReplicatorsZK() throws KeeperException {
99      List<String> result = null;
100     try {
101       result = ZKUtil.listChildrenNoWatch(this.zookeeper, this.queuesZNode);
102     } catch (KeeperException e) {
103       this.abortable.abort("Failed to get list of replicators", e);
104       throw e;
105     }
106     return result;
107   }
108 
109   /**
110    * @param state
111    * @return Serialized protobuf of <code>state</code> with pb magic prefix prepended suitable for
112    *         use as content of a peer-state znode under a peer cluster id as in
113    *         /hbase/replication/peers/PEER_ID/peer-state.
114    */
115   protected static byte[] toByteArray(final ZooKeeperProtos.ReplicationState.State state) {
116     byte[] bytes =
117         ZooKeeperProtos.ReplicationState.newBuilder().setState(state).build().toByteArray();
118     return ProtobufUtil.prependPBMagic(bytes);
119   }
120 
121   protected boolean peerExists(String id) throws KeeperException {
122     return ZKUtil.checkExists(this.zookeeper, ZKUtil.joinZNode(this.peersZNode, id)) >= 0;
123   }
124 
125   /**
126    * Determine if a ZK path points to a peer node.
127    * @param path path to be checked
128    * @return true if the path points to a peer node, otherwise false
129    */
130   protected boolean isPeerPath(String path) {
131     return path.split("/").length == peersZNode.split("/").length + 1;
132   }
133 
134   @VisibleForTesting
135   protected String getTableCFsNode(String id) {
136     return ZKUtil.joinZNode(this.peersZNode, ZKUtil.joinZNode(id, this.tableCFsNodeName));
137   }
138 
139   @VisibleForTesting
140   protected String getPeerStateNode(String id) {
141     return ZKUtil.joinZNode(this.peersZNode, ZKUtil.joinZNode(id, this.peerStateNodeName));
142   }
143 
144   @VisibleForTesting
145   protected String getPeerNode(String id) {
146     return ZKUtil.joinZNode(this.peersZNode, id);
147   }
148 }