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 */
018package org.apache.hadoop.hbase;
019
020import java.io.IOException;
021import java.util.Objects;
022import org.apache.hadoop.conf.Configuration;
023import org.apache.hadoop.hbase.exceptions.DeserializationException;
024import org.apache.hadoop.hbase.util.Bytes;
025import org.apache.yetus.audience.InterfaceAudience;
026
027import org.apache.hbase.thirdparty.com.google.common.base.Strings;
028
029import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
030import org.apache.hadoop.hbase.shaded.protobuf.generated.ActiveClusterSuffixProtos;
031
032/**
033 * The read-replica cluster id for this cluster. It is serialized to the filesystem and up into
034 * zookeeper. This is a container for the id. Also knows how to serialize and deserialize the
035 * cluster id.
036 */
037@InterfaceAudience.Private
038public class ActiveClusterSuffix implements ClusterIdFile {
039  private final String clusterId;
040  private final String suffix;
041
042  public static class Parser implements ClusterIdFileParser<ActiveClusterSuffix> {
043
044    @Override
045    public String getFileName() {
046      return HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME;
047    }
048
049    /**
050     * Parse the serialized representation of the {@link ActiveClusterSuffix}
051     * @param bytes A pb serialized {@link ActiveClusterSuffix} instance with pb magic prefix
052     * @return An instance of {@link ActiveClusterSuffix} made from <code>bytes</code>
053     * @see #toByteArray()
054     */
055    @Override
056    public ActiveClusterSuffix parseFrom(byte[] bytes) throws DeserializationException {
057      if (ProtobufUtil.isPBMagicPrefix(bytes)) {
058        int pblen = ProtobufUtil.lengthOfPBMagic();
059        ActiveClusterSuffixProtos.ActiveClusterSuffix.Builder builder =
060          ActiveClusterSuffixProtos.ActiveClusterSuffix.newBuilder();
061        ActiveClusterSuffixProtos.ActiveClusterSuffix cs = null;
062        try {
063          ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
064          cs = builder.build();
065        } catch (IOException e) {
066          throw new DeserializationException(e);
067        }
068        return convert(cs);
069      } else {
070        // Presume it was written out this way, the old way.
071        return new ActiveClusterSuffix(Bytes.toString(bytes));
072      }
073    }
074
075    @Override
076    public ActiveClusterSuffix readString(String input) {
077      return new ActiveClusterSuffix(input);
078    }
079  }
080
081  public ActiveClusterSuffix(final String clusterId, final String suffix) {
082    this.clusterId = clusterId;
083    this.suffix = suffix;
084  }
085
086  public ActiveClusterSuffix(final String input) {
087    String[] parts = input.split(":", 2);
088    this.clusterId = parts[0];
089    if (parts.length > 1) {
090      this.suffix = parts[1];
091    } else {
092      this.suffix = "";
093    }
094  }
095
096  public static ActiveClusterSuffix parseFrom(byte[] bytes) throws DeserializationException {
097    return new Parser().parseFrom(bytes);
098  }
099
100  public static ActiveClusterSuffix fromConfig(Configuration conf, ClusterId clusterId) {
101    return new ActiveClusterSuffix(clusterId.toString(), conf
102      .get(HConstants.HBASE_META_TABLE_SUFFIX, HConstants.HBASE_META_TABLE_SUFFIX_DEFAULT_VALUE));
103  }
104
105  /** Returns The active cluster suffix serialized using pb w/ pb magic prefix */
106  public byte[] toByteArray() {
107    return ProtobufUtil.prependPBMagic(convert().toByteArray());
108  }
109
110  /** Returns A pb instance to represent this instance. */
111  public ActiveClusterSuffixProtos.ActiveClusterSuffix convert() {
112    return ActiveClusterSuffixProtos.ActiveClusterSuffix.newBuilder().setClusterId(clusterId)
113      .setSuffix(suffix).build();
114  }
115
116  /** Returns A {@link ActiveClusterSuffix} made from the passed in <code>cs</code> */
117  public static ActiveClusterSuffix
118    convert(final ActiveClusterSuffixProtos.ActiveClusterSuffix cs) {
119    return new ActiveClusterSuffix(cs.getClusterId(), cs.getSuffix());
120  }
121
122  /**
123   * @see java.lang.Object#toString()
124   */
125  @Override
126  public String toString() {
127    return String.format("%s:%s", this.clusterId,
128      Strings.isNullOrEmpty(this.suffix) ? "<blank>" : this.suffix);
129  }
130
131  @Override
132  public boolean equals(Object o) {
133    if (o == null || getClass() != o.getClass()) return false;
134    ActiveClusterSuffix that = (ActiveClusterSuffix) o;
135    return Objects.equals(clusterId, that.clusterId) && Objects.equals(suffix, that.suffix);
136  }
137
138  @Override
139  public int hashCode() {
140    return Objects.hash(clusterId, suffix);
141  }
142}