View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.client.replication;
21  
22  import java.io.Closeable;
23  import java.io.IOException;
24  import java.util.Map;
25  
26  import org.apache.commons.lang.NotImplementedException;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.client.HConnection;
30  import org.apache.hadoop.hbase.client.HConnectionManager;
31  import org.apache.hadoop.hbase.replication.ReplicationZookeeper;
32  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
33  import org.apache.zookeeper.KeeperException;
34  
35  /**
36   * <p>
37   * This class provides the administrative interface to HBase cluster
38   * replication. In order to use it, the cluster and the client using
39   * ReplicationAdmin must be configured with <code>hbase.replication</code>
40   * set to true.
41   * </p>
42   * <p>
43   * Adding a new peer results in creating new outbound connections from every
44   * region server to a subset of region servers on the slave cluster. Each
45   * new stream of replication will start replicating from the beginning of the
46   * current HLog, meaning that edits from that past will be replicated.
47   * </p>
48   * <p>
49   * Removing a peer is a destructive and irreversible operation that stops
50   * all the replication streams for the given cluster and deletes the metadata
51   * used to keep track of the replication state.
52   * </p>
53   * <p>
54   * Enabling and disabling peers is currently not supported.
55   * </p>
56   * <p>
57   * As cluster replication is still experimental, a kill switch is provided
58   * in order to stop all replication-related operations, see
59   * {@link #setReplicating(boolean)}. When setting it back to true, the new
60   * state of all the replication streams will be unknown and may have holes.
61   * Use at your own risk.
62   * </p>
63   * <p>
64   * To see which commands are available in the shell, type
65   * <code>replication</code>.
66   * </p>
67   */
68  public class ReplicationAdmin implements Closeable {
69  
70    private final ReplicationZookeeper replicationZk;
71    private final HConnection connection;
72  
73    /**
74     * Constructor that creates a connection to the local ZooKeeper ensemble.
75     * @param conf Configuration to use
76     * @throws IOException if the connection to ZK cannot be made
77     * @throws RuntimeException if replication isn't enabled.
78     */
79    public ReplicationAdmin(Configuration conf) throws IOException {
80      if (!conf.getBoolean(HConstants.REPLICATION_ENABLE_KEY, false)) {
81        throw new RuntimeException("hbase.replication isn't true, please " +
82            "enable it in order to use replication");
83      }
84      this.connection = HConnectionManager.getConnection(conf);
85      ZooKeeperWatcher zkw = this.connection.getZooKeeperWatcher();
86      try {
87        this.replicationZk = new ReplicationZookeeper(this.connection, conf, zkw);
88      } catch (KeeperException e) {
89        throw new IOException("Unable setup the ZooKeeper connection", e);
90      }
91    }
92  
93    /**
94     * Add a new peer cluster to replicate to.
95     * @param id a short that identifies the cluster
96     * @param clusterKey the concatenation of the slave cluster's
97     * <code>hbase.zookeeper.quorum:hbase.zookeeper.property.clientPort:zookeeper.znode.parent</code>
98     * @throws IllegalStateException if there's already one slave since
99     * multi-slave isn't supported yet.
100    */
101   public void addPeer(String id, String clusterKey) throws IOException {
102     this.replicationZk.addPeer(id, clusterKey);
103   }
104 
105   /**
106    * Removes a peer cluster and stops the replication to it.
107    * @param id a short that identifies the cluster
108    */
109   public void removePeer(String id) throws IOException {
110     this.replicationZk.removePeer(id);
111   }
112 
113   /**
114    * Restart the replication stream to the specified peer.
115    * @param id a short that identifies the cluster
116    */
117   public void enablePeer(String id) {
118     throw new NotImplementedException("Not implemented");
119   }
120 
121   /**
122    * Stop the replication stream to the specified peer.
123    * @param id a short that identifies the cluster
124    */
125   public void disablePeer(String id) {
126     throw new NotImplementedException("Not implemented");
127   }
128 
129   /**
130    * Get the number of slave clusters the local cluster has.
131    * @return number of slave clusters
132    */
133   public int getPeersCount() {
134     return this.replicationZk.listPeersIdsAndWatch().size();
135   }
136 
137   /**
138    * Map of this cluster's peers for display.
139    * @return A map of peer ids to peer cluster keys
140    */
141   public Map<String, String> listPeers() {
142     return this.replicationZk.listPeers();
143   }
144 
145   /**
146    * Get the current status of the kill switch, if the cluster is replicating
147    * or not.
148    * @return true if the cluster is replicated, otherwise false
149    */
150   public boolean getReplicating() throws IOException {
151     try {
152       return this.replicationZk.getReplication();
153     } catch (KeeperException e) {
154       throw new IOException("Couldn't get the replication status");
155     }
156   }
157 
158   /**
159    * Kill switch for all replication-related features
160    * @param newState true to start replication, false to stop it.
161    * completely
162    * @return the previous state
163    */
164   public boolean setReplicating(boolean newState) throws IOException {
165     boolean prev = true;
166     try {
167       prev = getReplicating();
168       this.replicationZk.setReplicating(newState);
169     } catch (KeeperException e) {
170       throw new IOException("Unable to set the replication state", e);
171     }
172     return prev;
173   }
174 
175   /**
176    * Get the ZK-support tool created and used by this object for replication.
177    * @return the ZK-support tool
178    */
179   ReplicationZookeeper getReplicationZk() {
180     return replicationZk;
181   }
182 
183   @Override
184   public void close() throws IOException {
185     if (this.connection != null) {
186       this.connection.close();
187     }
188   }
189 }