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