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.executor;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  
26  import org.apache.hadoop.hbase.ServerName;
27  import org.apache.hadoop.hbase.executor.EventHandler.EventType;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.apache.hadoop.hbase.util.Writables;
30  import org.apache.hadoop.io.Writable;
31  
32  /**
33   * Data serialized into ZooKeeper for region transitions.
34   */
35  public class RegionTransitionData implements Writable {
36    /**
37     * Type of transition event (offline, opening, opened, closing, closed).
38     * Required.
39     */
40    private EventType eventType;
41  
42    /** Region being transitioned.  Required. */
43    private byte [] regionName;
44  
45    /** Server event originated from.  Optional. */
46    private ServerName origin;
47  
48    /** Time the event was created.  Required but automatically set. */
49    private long stamp;
50  
51    private byte [] payload;
52  
53    /**
54     * Writable constructor.  Do not use directly.
55     */
56    public RegionTransitionData() {}
57  
58    /**
59     * Construct data for a new region transition event with the specified event
60     * type and region name.
61     *
62     * <p>Used when the server name is not known (the master is setting it).  This
63     * happens during cluster startup or during failure scenarios.  When
64     * processing a failed regionserver, the master assigns the regions from that
65     * server to other servers though the region was never 'closed'.  During
66     * master failover, the new master may have regions stuck in transition
67     * without a destination so may have to set regions offline and generate a new
68     * assignment.
69     *
70     * <p>Since only the master uses this constructor, the type should always be
71     * {@link EventType#M_ZK_REGION_OFFLINE}.
72     *
73     * @param eventType type of event
74     * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code>
75     */
76    public RegionTransitionData(EventType eventType, byte [] regionName) {
77      this(eventType, regionName, null);
78    }
79  
80    /**
81     * Construct data for a new region transition event with the specified event
82     * type, region name, and server name.
83     *
84     * <p>Used when the server name is known (a regionserver is setting it).
85     *
86     * <p>Valid types for this constructor are {@link EventType#M_ZK_REGION_CLOSING},
87     * {@link EventType#RS_ZK_REGION_CLOSED}, {@link EventType#RS_ZK_REGION_OPENING},
88     * {@link EventType#RS_ZK_REGION_SPLITTING},
89     * and {@link EventType#RS_ZK_REGION_OPENED}.
90     *
91     * @param eventType type of event
92     * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code>
93     * @param origin Originating {@link ServerName}
94     */
95    public RegionTransitionData(EventType eventType, byte [] regionName,
96        final ServerName origin) {
97      this(eventType, regionName, origin, null);
98    }
99  
100   /**
101    * Construct data for a new region transition event with the specified event
102    * type, region name, and server name.
103    *
104    * <p>Used when the server name is known (a regionserver is setting it).
105    *
106    * <p>Valid types for this constructor are {@link EventType#RS_ZK_REGION_SPLIT}
107    * since SPLIT is only type that currently carries a payload.
108    *
109    * @param eventType type of event
110    * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code>
111    * @param serverName Originating {@link ServerName}
112    * @param payload Payload examples include the daughters involved in a
113    * {@link EventType#RS_ZK_REGION_SPLIT}. Can be null
114    */
115   public RegionTransitionData(EventType eventType, byte [] regionName,
116       final ServerName serverName, final byte [] payload) {
117     this.eventType = eventType;
118     this.stamp = System.currentTimeMillis();
119     this.regionName = regionName;
120     this.origin = serverName;
121     this.payload = payload;
122   }
123 
124   /**
125    * Gets the type of region transition event.
126    *
127    * <p>One of:
128    * <ul>
129    * <li>{@link EventType#M_ZK_REGION_OFFLINE}
130    * <li>{@link EventType#M_ZK_REGION_CLOSING}
131    * <li>{@link EventType#RS_ZK_REGION_CLOSED}
132    * <li>{@link EventType#RS_ZK_REGION_OPENING}
133    * <li>{@link EventType#RS_ZK_REGION_OPENED}
134    * <li>{@link EventType#RS_ZK_REGION_SPLITTING}
135    * <li>{@link EventType#RS_ZK_REGION_SPLIT}
136    * </ul>
137    * @return type of region transition event
138    */
139   public EventType getEventType() {
140     return eventType;
141   }
142 
143   /**
144    * Gets the name of the region being transitioned.
145    *
146    * <p>Region name is required so this never returns null.
147    * @return region name, the result of a call to <code>HRegionInfo#getRegionName()</code>
148    */
149   public byte [] getRegionName() {
150     return regionName;
151   }
152 
153   /**
154    * Gets the server the event originated from.  If null, this event originated
155    * from the master.
156    *
157    * @return server name of originating regionserver, or null if from master
158    */
159   public ServerName getOrigin() {
160     return origin;
161   }
162 
163   /**
164    * Gets the timestamp when this event was created.
165    *
166    * @return stamp event was created
167    */
168   public long getStamp() {
169     return stamp;
170   }
171 
172   /**
173    * @return Payload if any.
174    */
175   public byte [] getPayload() {
176     return this.payload;
177   }
178 
179   @Override
180   public void readFields(DataInput in) throws IOException {
181     // the event type byte
182     eventType = EventType.values()[in.readShort()];
183     // the timestamp
184     stamp = in.readLong();
185     // the encoded name of the region being transitioned
186     regionName = Bytes.readByteArray(in);
187     // remaining fields are optional so prefixed with boolean
188     // the name of the regionserver sending the data
189     if (in.readBoolean()) {
190       byte [] versionedBytes = Bytes.readByteArray(in);
191       this.origin = ServerName.parseVersionedServerName(versionedBytes);
192     }
193     if (in.readBoolean()) {
194       this.payload = Bytes.readByteArray(in);
195     }
196   }
197 
198   @Override
199   public void write(DataOutput out) throws IOException {
200     out.writeShort(eventType.ordinal());
201     out.writeLong(System.currentTimeMillis());
202     Bytes.writeByteArray(out, regionName);
203     // remaining fields are optional so prefixed with boolean
204     out.writeBoolean(this.origin != null);
205     if (this.origin != null) {
206       Bytes.writeByteArray(out, this.origin.getVersionedBytes());
207     }
208     out.writeBoolean(this.payload != null);
209     if (this.payload != null) {
210       Bytes.writeByteArray(out, this.payload);
211     }
212   }
213 
214   /**
215    * Get the bytes for this instance.  Throws a {@link RuntimeException} if
216    * there is an error deserializing this instance because it represents a code
217    * bug.
218    * @return binary representation of this instance
219    */
220   public byte [] getBytes() {
221     try {
222       return Writables.getBytes(this);
223     } catch(IOException e) {
224       throw new RuntimeException(e);
225     }
226   }
227 
228   /**
229    * Get an instance from bytes.  Throws a {@link RuntimeException} if
230    * there is an error serializing this instance from bytes because it
231    * represents a code bug.
232    * @param bytes binary representation of this instance
233    * @return instance of this class
234    */
235   public static RegionTransitionData fromBytes(byte [] bytes) {
236     try {
237       RegionTransitionData data = new RegionTransitionData();
238       Writables.getWritable(bytes, data);
239       return data;
240     } catch(IOException e) {
241       throw new RuntimeException(e);
242     }
243   }
244 
245   @Override
246   public String toString() {
247     return "region=" + Bytes.toStringBinary(regionName) + ", origin=" + this.origin +
248       ", state=" + eventType;
249   }
250 }