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 */
018
019package org.apache.hadoop.hbase.replication;
020
021import java.util.Collection;
022import java.util.Collections;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026import java.util.Set;
027import java.util.TreeMap;
028
029import org.apache.hadoop.hbase.TableName;
030import org.apache.yetus.audience.InterfaceAudience;
031import org.apache.hadoop.hbase.util.Bytes;
032
033/**
034 * A configuration for the replication peer cluster.
035 */
036@InterfaceAudience.Public
037public class ReplicationPeerConfig {
038
039  private String clusterKey;
040  private String replicationEndpointImpl;
041  private final Map<byte[], byte[]> peerData;
042  private final Map<String, String> configuration;
043  private Map<TableName, ? extends Collection<String>> tableCFsMap = null;
044  private Set<String> namespaces = null;
045  // Default value is true, means replicate all user tables to peer cluster.
046  private boolean replicateAllUserTables = true;
047  private Map<TableName, ? extends Collection<String>> excludeTableCFsMap = null;
048  private Set<String> excludeNamespaces = null;
049  private long bandwidth = 0;
050
051  private ReplicationPeerConfig(ReplicationPeerConfigBuilderImpl builder) {
052    this.clusterKey = builder.clusterKey;
053    this.replicationEndpointImpl = builder.replicationEndpointImpl;
054    this.peerData = Collections.unmodifiableMap(builder.peerData);
055    this.configuration = Collections.unmodifiableMap(builder.configuration);
056    this.tableCFsMap =
057        builder.tableCFsMap != null ? unmodifiableTableCFsMap(builder.tableCFsMap) : null;
058    this.namespaces =
059        builder.namespaces != null ? Collections.unmodifiableSet(builder.namespaces) : null;
060    this.replicateAllUserTables = builder.replicateAllUserTables;
061    this.excludeTableCFsMap =
062        builder.excludeTableCFsMap != null ? unmodifiableTableCFsMap(builder.excludeTableCFsMap)
063            : null;
064    this.excludeNamespaces =
065        builder.excludeNamespaces != null ? Collections.unmodifiableSet(builder.excludeNamespaces)
066            : null;
067    this.bandwidth = builder.bandwidth;
068  }
069
070  private Map<TableName, List<String>>
071      unmodifiableTableCFsMap(Map<TableName, List<String>> tableCFsMap) {
072    Map<TableName, List<String>> newTableCFsMap = new HashMap<>();
073    tableCFsMap.forEach((table, cfs) -> newTableCFsMap.put(table,
074      cfs != null ? Collections.unmodifiableList(cfs) : null));
075    return Collections.unmodifiableMap(newTableCFsMap);
076  }
077
078  /**
079   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
080   *             {@link ReplicationPeerConfigBuilder} to create new ReplicationPeerConfig.
081   */
082  @Deprecated
083  public ReplicationPeerConfig() {
084    this.peerData = new TreeMap<>(Bytes.BYTES_COMPARATOR);
085    this.configuration = new HashMap<>(0);
086  }
087
088  /**
089   * Set the clusterKey which is the concatenation of the slave cluster's:
090   * hbase.zookeeper.quorum:hbase.zookeeper.property.clientPort:zookeeper.znode.parent
091   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
092   *             {@link ReplicationPeerConfigBuilder#setClusterKey(String)} instead.
093   */
094  @Deprecated
095  public ReplicationPeerConfig setClusterKey(String clusterKey) {
096    this.clusterKey = clusterKey;
097    return this;
098  }
099
100  /**
101   * Sets the ReplicationEndpoint plugin class for this peer.
102   * @param replicationEndpointImpl a class implementing ReplicationEndpoint
103   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
104   *             {@link ReplicationPeerConfigBuilder#setReplicationEndpointImpl(String)} instead.
105   */
106  @Deprecated
107  public ReplicationPeerConfig setReplicationEndpointImpl(String replicationEndpointImpl) {
108    this.replicationEndpointImpl = replicationEndpointImpl;
109    return this;
110  }
111
112  public String getClusterKey() {
113    return clusterKey;
114  }
115
116  public String getReplicationEndpointImpl() {
117    return replicationEndpointImpl;
118  }
119
120  public Map<byte[], byte[]> getPeerData() {
121    return peerData;
122  }
123
124  public Map<String, String> getConfiguration() {
125    return configuration;
126  }
127
128  public Map<TableName, List<String>> getTableCFsMap() {
129    return (Map<TableName, List<String>>) tableCFsMap;
130  }
131
132  /**
133   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
134   *             {@link ReplicationPeerConfigBuilder#setTableCFsMap(Map)} instead.
135   */
136  @Deprecated
137  public ReplicationPeerConfig setTableCFsMap(Map<TableName,
138                                              ? extends Collection<String>> tableCFsMap) {
139    this.tableCFsMap = tableCFsMap;
140    return this;
141  }
142
143  public Set<String> getNamespaces() {
144    return this.namespaces;
145  }
146
147  /**
148   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
149   *             {@link ReplicationPeerConfigBuilder#setNamespaces(Set)} instead.
150   */
151  @Deprecated
152  public ReplicationPeerConfig setNamespaces(Set<String> namespaces) {
153    this.namespaces = namespaces;
154    return this;
155  }
156
157  public long getBandwidth() {
158    return this.bandwidth;
159  }
160
161  /**
162   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
163   *             {@link ReplicationPeerConfigBuilder#setBandwidth(long)} instead.
164   */
165  @Deprecated
166  public ReplicationPeerConfig setBandwidth(long bandwidth) {
167    this.bandwidth = bandwidth;
168    return this;
169  }
170
171  public boolean replicateAllUserTables() {
172    return this.replicateAllUserTables;
173  }
174
175  /**
176   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
177   *             {@link ReplicationPeerConfigBuilder#setReplicateAllUserTables(boolean)} instead.
178   */
179  @Deprecated
180  public ReplicationPeerConfig setReplicateAllUserTables(boolean replicateAllUserTables) {
181    this.replicateAllUserTables = replicateAllUserTables;
182    return this;
183  }
184
185  public Map<TableName, List<String>> getExcludeTableCFsMap() {
186    return (Map<TableName, List<String>>) excludeTableCFsMap;
187  }
188
189  /**
190   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
191   *             {@link ReplicationPeerConfigBuilder#setExcludeTableCFsMap(Map)} instead.
192   */
193  @Deprecated
194  public ReplicationPeerConfig setExcludeTableCFsMap(Map<TableName,
195                                              ? extends Collection<String>> tableCFsMap) {
196    this.excludeTableCFsMap = tableCFsMap;
197    return this;
198  }
199
200  public Set<String> getExcludeNamespaces() {
201    return this.excludeNamespaces;
202  }
203
204  /**
205   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0. Use
206   *             {@link ReplicationPeerConfigBuilder#setExcludeNamespaces(Set)} instead.
207   */
208  @Deprecated
209  public ReplicationPeerConfig setExcludeNamespaces(Set<String> namespaces) {
210    this.excludeNamespaces = namespaces;
211    return this;
212  }
213
214  public static ReplicationPeerConfigBuilder newBuilder() {
215    return new ReplicationPeerConfigBuilderImpl();
216  }
217
218  public static ReplicationPeerConfigBuilder newBuilder(ReplicationPeerConfig peerConfig) {
219    ReplicationPeerConfigBuilderImpl builder = new ReplicationPeerConfigBuilderImpl();
220    builder.setClusterKey(peerConfig.getClusterKey())
221        .setReplicationEndpointImpl(peerConfig.getReplicationEndpointImpl())
222        .putAllPeerData(peerConfig.getPeerData()).putAllConfiguration(peerConfig.getConfiguration())
223        .setTableCFsMap(peerConfig.getTableCFsMap()).setNamespaces(peerConfig.getNamespaces())
224        .setReplicateAllUserTables(peerConfig.replicateAllUserTables())
225        .setExcludeTableCFsMap(peerConfig.getExcludeTableCFsMap())
226        .setExcludeNamespaces(peerConfig.getExcludeNamespaces())
227        .setBandwidth(peerConfig.getBandwidth());
228    return builder;
229  }
230
231  static class ReplicationPeerConfigBuilderImpl implements ReplicationPeerConfigBuilder {
232
233    private String clusterKey;
234
235    private String replicationEndpointImpl;
236
237    private Map<byte[], byte[]> peerData = new TreeMap<>(Bytes.BYTES_COMPARATOR);
238
239    private Map<String, String> configuration = new HashMap<>();
240
241    private Map<TableName, List<String>> tableCFsMap = null;
242
243    private Set<String> namespaces = null;
244
245    // Default value is true, means replicate all user tables to peer cluster.
246    private boolean replicateAllUserTables = true;
247
248    private Map<TableName, List<String>> excludeTableCFsMap = null;
249
250    private Set<String> excludeNamespaces = null;
251
252    private long bandwidth = 0;
253
254    @Override
255    public ReplicationPeerConfigBuilder setClusterKey(String clusterKey) {
256      this.clusterKey = clusterKey;
257      return this;
258    }
259
260    @Override
261    public ReplicationPeerConfigBuilder setReplicationEndpointImpl(String replicationEndpointImpl) {
262      this.replicationEndpointImpl = replicationEndpointImpl;
263      return this;
264    }
265
266    @Override
267    public ReplicationPeerConfigBuilder putConfiguration(String key, String value) {
268      this.configuration.put(key, value);
269      return this;
270    }
271
272    @Override
273    public ReplicationPeerConfigBuilder putPeerData(byte[] key, byte[] value) {
274      this.peerData.put(key, value);
275      return this;
276    }
277
278    @Override
279    public ReplicationPeerConfigBuilder
280        setTableCFsMap(Map<TableName, List<String>> tableCFsMap) {
281      this.tableCFsMap = tableCFsMap;
282      return this;
283    }
284
285    @Override
286    public ReplicationPeerConfigBuilder setNamespaces(Set<String> namespaces) {
287      this.namespaces = namespaces;
288      return this;
289    }
290
291    @Override
292    public ReplicationPeerConfigBuilder setReplicateAllUserTables(boolean replicateAllUserTables) {
293      this.replicateAllUserTables = replicateAllUserTables;
294      return this;
295    }
296
297    @Override
298    public ReplicationPeerConfigBuilder
299        setExcludeTableCFsMap(Map<TableName, List<String>> excludeTableCFsMap) {
300      this.excludeTableCFsMap = excludeTableCFsMap;
301      return this;
302    }
303
304    @Override
305    public ReplicationPeerConfigBuilder setExcludeNamespaces(Set<String> excludeNamespaces) {
306      this.excludeNamespaces = excludeNamespaces;
307      return this;
308    }
309
310    @Override
311    public ReplicationPeerConfigBuilder setBandwidth(long bandwidth) {
312      this.bandwidth = bandwidth;
313      return this;
314    }
315
316    @Override
317    public ReplicationPeerConfig build() {
318      // It would be nice to validate the configuration, but we have to work with "old" data
319      // from ZK which makes it much more difficult.
320      return new ReplicationPeerConfig(this);
321    }
322  }
323
324  @Override
325  public String toString() {
326    StringBuilder builder = new StringBuilder("clusterKey=").append(clusterKey).append(",");
327    builder.append("replicationEndpointImpl=").append(replicationEndpointImpl).append(",");
328    builder.append("replicateAllUserTables=").append(replicateAllUserTables).append(",");
329    if (replicateAllUserTables) {
330      if (excludeNamespaces != null) {
331        builder.append("excludeNamespaces=").append(excludeNamespaces.toString()).append(",");
332      }
333      if (excludeTableCFsMap != null) {
334        builder.append("excludeTableCFsMap=").append(excludeTableCFsMap.toString()).append(",");
335      }
336    } else {
337      if (namespaces != null) {
338        builder.append("namespaces=").append(namespaces.toString()).append(",");
339      }
340      if (tableCFsMap != null) {
341        builder.append("tableCFs=").append(tableCFsMap.toString()).append(",");
342      }
343    }
344    builder.append("bandwidth=").append(bandwidth);
345    return builder.toString();
346  }
347
348  /**
349   * Decide whether the table need replicate to the peer cluster
350   * @param table name of the table
351   * @return true if the table need replicate to the peer cluster
352   */
353  public boolean needToReplicate(TableName table) {
354    if (replicateAllUserTables) {
355      if (excludeNamespaces != null && excludeNamespaces.contains(table.getNamespaceAsString())) {
356        return false;
357      }
358      if (excludeTableCFsMap != null && excludeTableCFsMap.containsKey(table)) {
359        return false;
360      }
361      return true;
362    } else {
363      if (namespaces != null && namespaces.contains(table.getNamespaceAsString())) {
364        return true;
365      }
366      if (tableCFsMap != null && tableCFsMap.containsKey(table)) {
367        return true;
368      }
369      return false;
370    }
371  }
372}