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;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  
26  import org.apache.hadoop.hbase.util.Bytes;
27  import org.apache.hadoop.io.Writable;
28  
29  /**
30   * HMsg is for communicating instructions between the HMaster and the
31   * HRegionServers.
32   *
33   * Most of the time the messages are simple but some messages are accompanied
34   * by the region affected.  HMsg may also carry optional message.
35   */
36  public class HMsg implements Writable {
37    public static final HMsg REGIONSERVER_QUIESCE =
38      new HMsg(Type.MSG_REGIONSERVER_QUIESCE);
39    public static final HMsg REGIONSERVER_STOP =
40      new HMsg(Type.MSG_REGIONSERVER_STOP);
41    public static final HMsg [] EMPTY_HMSG_ARRAY = new HMsg[0];
42  
43    /**
44     * Message types sent between master and regionservers
45     */
46    public static enum Type {
47      /** null message */
48      MSG_NONE,
49  
50      // Message types sent from master to region server
51      /** Start serving the specified region */
52      MSG_REGION_OPEN,
53  
54      /** Stop serving the specified region */
55      MSG_REGION_CLOSE,
56  
57      /** Split the specified region */
58      MSG_REGION_SPLIT,
59  
60      /** Compact the specified region */
61      MSG_REGION_COMPACT,
62  
63      /** Master tells region server to stop */
64      MSG_REGIONSERVER_STOP,
65  
66      /** Stop serving the specified region and don't report back that it's
67       * closed
68       */
69      MSG_REGION_CLOSE_WITHOUT_REPORT,
70  
71      /** Stop serving user regions */
72      MSG_REGIONSERVER_QUIESCE,
73  
74      // Message types sent from the region server to the master
75      /** region server is now serving the specified region */
76      MSG_REPORT_OPEN,
77  
78      /** region server is no longer serving the specified region */
79      MSG_REPORT_CLOSE,
80  
81      /** region server is processing open request */
82      MSG_REPORT_PROCESS_OPEN,
83  
84      /**
85       * Region server split the region associated with this message.
86       *
87       * Note that this message is immediately followed by two MSG_REPORT_OPEN
88       * messages, one for each of the new regions resulting from the split
89       * @deprecated See MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS
90       */
91      MSG_REPORT_SPLIT,
92  
93      /**
94       * Region server is shutting down
95       *
96       * Note that this message is followed by MSG_REPORT_CLOSE messages for each
97       * region the region server was serving, unless it was told to quiesce.
98       */
99      MSG_REPORT_EXITING,
100 
101     /** Region server has closed all user regions but is still serving meta
102      * regions
103      */
104     MSG_REPORT_QUIESCED,
105 
106     /**
107      * Flush
108      */
109     MSG_REGION_FLUSH,
110 
111     /**
112      * Run Major Compaction
113      */
114     MSG_REGION_MAJOR_COMPACT,
115 
116     /**
117      * Region server split the region associated with this message.
118      *
119      * Its like MSG_REPORT_SPLIT only it carries the daughters in the message
120      * rather than send them individually in MSG_REPORT_OPEN messages.
121      */
122     MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS,
123 
124     /**
125      * When RegionServer receives this message, it goes into a sleep that only
126      * an exit will cure.  This message is sent by unit tests simulating
127      * pathological states.
128      */
129     TESTING_MSG_BLOCK_RS,
130   }
131 
132   private Type type = null;
133   private HRegionInfo info = null;
134   private byte[] message = null;
135   private HRegionInfo daughterA = null;
136   private HRegionInfo daughterB = null;
137 
138   /** Default constructor. Used during deserialization */
139   public HMsg() {
140     this(Type.MSG_NONE);
141   }
142 
143   /**
144    * Construct a message with the specified message and empty HRegionInfo
145    * @param type Message type
146    */
147   public HMsg(final HMsg.Type type) {
148     this(type, new HRegionInfo(), null);
149   }
150 
151   /**
152    * Construct a message with the specified message and HRegionInfo
153    * @param type Message type
154    * @param hri Region to which message <code>type</code> applies
155    */
156   public HMsg(final HMsg.Type type, final HRegionInfo hri) {
157     this(type, hri, null);
158   }
159 
160   /**
161    * Construct a message with the specified message and HRegionInfo
162    *
163    * @param type Message type
164    * @param hri Region to which message <code>type</code> applies.  Cannot be
165    * null.  If no info associated, used other Constructor.
166    * @param msg Optional message (Stringified exception, etc.)
167    */
168   public HMsg(final HMsg.Type type, final HRegionInfo hri, final byte[] msg) {
169     this(type, hri, null, null, msg);
170   }
171 
172   /**
173    * Construct a message with the specified message and HRegionInfo
174    *
175    * @param type Message type
176    * @param hri Region to which message <code>type</code> applies.  Cannot be
177    * null.  If no info associated, used other Constructor.
178    * @param daughterA
179    * @param daughterB
180    * @param msg Optional message (Stringified exception, etc.)
181    */
182   public HMsg(final HMsg.Type type, final HRegionInfo hri,
183       final HRegionInfo daughterA, final HRegionInfo daughterB, final byte[] msg) {
184     if (type == null) {
185       throw new NullPointerException("Message type cannot be null");
186     }
187     this.type = type;
188     if (hri == null) {
189       throw new NullPointerException("Region cannot be null");
190     }
191     this.info = hri;
192     this.message = msg;
193     this.daughterA = daughterA;
194     this.daughterB = daughterB;
195   }
196 
197   /**
198    * @return Region info or null if none associated with this message type.
199    */
200   public HRegionInfo getRegionInfo() {
201     return this.info;
202   }
203 
204   /** @return the type of message */
205   public Type getType() {
206     return this.type;
207   }
208 
209   /**
210    * @param other Message type to compare to
211    * @return True if we are of same message type as <code>other</code>
212    */
213   public boolean isType(final HMsg.Type other) {
214     return this.type.equals(other);
215   }
216 
217   /** @return the message type */
218   public byte[] getMessage() {
219     return this.message;
220   }
221 
222   /**
223    * @return First daughter if Type is MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS else
224    * null
225    */
226   public HRegionInfo getDaughterA() {
227     return this.daughterA;
228   }
229 
230   /**
231    * @return Second daughter if Type is MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS else
232    * null
233    */
234   public HRegionInfo getDaughterB() {
235     return this.daughterB;
236   }
237 
238   /**
239    * @see java.lang.Object#toString()
240    */
241   @Override
242   public String toString() {
243     StringBuilder sb = new StringBuilder();
244     sb.append(this.type.toString());
245     // If null or empty region, don't bother printing it out.
246     if (this.info != null && this.info.getRegionName().length > 0) {
247       sb.append(": ");
248       sb.append(this.info.getRegionNameAsString());
249     }
250     if (this.message != null && this.message.length > 0) {
251       sb.append(": " + Bytes.toString(this.message));
252     }
253     return sb.toString();
254   }
255 
256   /**
257    * @see java.lang.Object#equals(java.lang.Object)
258    */
259   @Override
260   public boolean equals(Object obj) {
261     if (this == obj) {
262       return true;
263     }
264     if (obj == null) {
265       return false;
266     }
267     if (getClass() != obj.getClass()) {
268       return false;
269     }
270     HMsg that = (HMsg)obj;
271     return this.type.equals(that.type) &&
272       (this.info != null)? this.info.equals(that.info):
273         that.info == null;
274   }
275 
276   /**
277    * @see java.lang.Object#hashCode()
278    */
279   @Override
280   public int hashCode() {
281     int result = this.type.hashCode();
282     if (this.info != null) {
283       result ^= this.info.hashCode();
284     }
285     return result;
286   }
287 
288   // ////////////////////////////////////////////////////////////////////////////
289   // Writable
290   //////////////////////////////////////////////////////////////////////////////
291 
292   /**
293    * @see org.apache.hadoop.io.Writable#write(java.io.DataOutput)
294    */
295   public void write(DataOutput out) throws IOException {
296      out.writeInt(this.type.ordinal());
297      this.info.write(out);
298      if (this.message == null || this.message.length == 0) {
299        out.writeBoolean(false);
300      } else {
301        out.writeBoolean(true);
302        Bytes.writeByteArray(out, this.message);
303      }
304      if (this.type.equals(Type.MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS)) {
305        this.daughterA.write(out);
306        this.daughterB.write(out);
307      }
308    }
309 
310   /**
311    * @see org.apache.hadoop.io.Writable#readFields(java.io.DataInput)
312    */
313   public void readFields(DataInput in) throws IOException {
314      int ordinal = in.readInt();
315      this.type = HMsg.Type.values()[ordinal];
316      this.info.readFields(in);
317      boolean hasMessage = in.readBoolean();
318      if (hasMessage) {
319        this.message = Bytes.readByteArray(in);
320      }
321      if (this.type.equals(Type.MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS)) {
322        this.daughterA = new HRegionInfo();
323        this.daughterB = new HRegionInfo();
324        this.daughterA.readFields(in);
325        this.daughterB.readFields(in);
326      }
327    }
328 }