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;
021
022import org.apache.yetus.audience.InterfaceAudience;
023import org.apache.hadoop.hbase.exceptions.DeserializationException;
024import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
025import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
026import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos;
027import org.apache.hadoop.hbase.util.Bytes;
028
029/**
030 * State of a WAL log split during distributed splitting.  State is kept up in zookeeper.
031 * Encapsulates protobuf serialization/deserialization so we don't leak generated pb outside of
032 * this class.  Used by regionserver and master packages.
033 * <p>Immutable
034 */
035@InterfaceAudience.Private
036public class SplitLogTask {
037  private final ServerName originServer;
038  private final ZooKeeperProtos.SplitLogTask.State state;
039
040  public static class Unassigned extends SplitLogTask {
041    public Unassigned(final ServerName originServer) {
042      super(originServer, ZooKeeperProtos.SplitLogTask.State.UNASSIGNED);
043    }
044  }
045
046  public static class Owned extends SplitLogTask {
047    public Owned(final ServerName originServer) {
048      super(originServer, ZooKeeperProtos.SplitLogTask.State.OWNED);
049    }
050  }
051
052  public static class Resigned extends SplitLogTask {
053    public Resigned(final ServerName originServer) {
054      super(originServer, ZooKeeperProtos.SplitLogTask.State.RESIGNED);
055    }
056  }
057
058  public static class Done extends SplitLogTask {
059    public Done(final ServerName originServer) {
060      super(originServer, ZooKeeperProtos.SplitLogTask.State.DONE);
061    }
062  }
063
064  public static class Err extends SplitLogTask {
065    public Err(final ServerName originServer) {
066      super(originServer, ZooKeeperProtos.SplitLogTask.State.ERR);
067    }
068  }
069
070  SplitLogTask(final ZooKeeperProtos.SplitLogTask slt) {
071    this.originServer = ProtobufUtil.toServerName(slt.getServerName());
072    this.state = slt.getState();
073  }
074
075  SplitLogTask(final ServerName originServer, final ZooKeeperProtos.SplitLogTask.State state) {
076    this.originServer = originServer;
077    this.state = state;
078  }
079
080  public ServerName getServerName() {
081    return this.originServer;
082  }
083
084  public boolean isUnassigned(final ServerName sn) {
085    return this.originServer.equals(sn) && isUnassigned();
086  }
087
088  public boolean isUnassigned() {
089    return this.state == ZooKeeperProtos.SplitLogTask.State.UNASSIGNED;
090  }
091
092  public boolean isOwned(final ServerName sn) {
093    return this.originServer.equals(sn) && isOwned();
094  }
095
096  public boolean isOwned() {
097    return this.state == ZooKeeperProtos.SplitLogTask.State.OWNED;
098  }
099
100  public boolean isResigned(final ServerName sn) {
101    return this.originServer.equals(sn) && isResigned();
102  }
103
104  public boolean isResigned() {
105    return this.state == ZooKeeperProtos.SplitLogTask.State.RESIGNED;
106  }
107
108  public boolean isDone(final ServerName sn) {
109    return this.originServer.equals(sn) && isDone();
110  }
111
112  public boolean isDone() {
113    return this.state == ZooKeeperProtos.SplitLogTask.State.DONE;
114  }
115
116  public boolean isErr(final ServerName sn) {
117    return this.originServer.equals(sn) && isErr();
118  }
119
120  public boolean isErr() {
121    return this.state == ZooKeeperProtos.SplitLogTask.State.ERR;
122  }
123
124  @Override
125  public String toString() {
126    return this.state.toString() + " " + this.originServer.toString();
127  }
128
129  @Override
130  public boolean equals(Object obj) {
131    if (!(obj instanceof SplitLogTask)) return false;
132    SplitLogTask other = (SplitLogTask)obj;
133    return other.state.equals(this.state) && other.originServer.equals(this.originServer);
134  }
135
136  @Override
137  public int hashCode() {
138    int hash = 7;
139    hash = 31 * hash + this.state.hashCode();
140    return 31 * hash + this.originServer.hashCode();
141  }
142
143  /**
144   * @param data Serialized date to parse.
145   * @return An SplitLogTaskState instance made of the passed <code>data</code>
146   * @throws DeserializationException
147   * @see #toByteArray()
148   */
149  public static SplitLogTask parseFrom(final byte [] data) throws DeserializationException {
150    ProtobufUtil.expectPBMagicPrefix(data);
151    try {
152      int prefixLen = ProtobufUtil.lengthOfPBMagic();
153      ZooKeeperProtos.SplitLogTask.Builder builder = ZooKeeperProtos.SplitLogTask.newBuilder();
154      ProtobufUtil.mergeFrom(builder, data, prefixLen, data.length - prefixLen);
155      return new SplitLogTask(builder.build());
156    } catch (IOException e) {
157      throw new DeserializationException(Bytes.toStringBinary(data, 0, 64), e);
158    }
159  }
160
161  /**
162   * @return This instance serialized into a byte array
163   * @see #parseFrom(byte[])
164   */
165  public byte [] toByteArray() {
166    // First create a pb ServerName.  Then create a ByteString w/ the TaskState
167    // bytes in it.  Finally create a SplitLogTaskState passing in the two
168    // pbs just created.
169    HBaseProtos.ServerName snpb = ProtobufUtil.toServerName(this.originServer);
170    ZooKeeperProtos.SplitLogTask slts =
171      ZooKeeperProtos.SplitLogTask.newBuilder().setServerName(snpb).setState(this.state).build();
172    return ProtobufUtil.prependPBMagic(slts.toByteArray());
173  }
174}