View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.master;
19  
20  import java.util.Date;
21  
22  import org.apache.hadoop.hbase.HRegionInfo;
23  import org.apache.hadoop.hbase.ServerName;
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.classification.InterfaceStability;
26  import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos;
27  
28  /**
29   * State of a Region while undergoing transitions.
30   * This class is immutable.
31   */
32  @InterfaceAudience.Private
33  public class RegionState {
34  
35    @InterfaceAudience.Private
36    @InterfaceStability.Evolving
37    public enum State {
38      OFFLINE,        // region is in an offline state
39      PENDING_OPEN,   // same as OPENING, to be removed
40      OPENING,        // server has begun to open but not yet done
41      OPEN,           // server opened region and updated meta
42      PENDING_CLOSE,  // same as CLOSING, to be removed
43      CLOSING,        // server has begun to close but not yet done
44      CLOSED,         // server closed region and updated meta
45      SPLITTING,      // server started split of a region
46      SPLIT,          // server completed split of a region
47      FAILED_OPEN,    // failed to open, and won't retry any more
48      FAILED_CLOSE,   // failed to close, and won't retry any more
49      MERGING,        // server started merge a region
50      MERGED,         // server completed merge a region
51      SPLITTING_NEW,  // new region to be created when RS splits a parent
52                      // region but hasn't be created yet, or master doesn't
53                      // know it's already created
54      MERGING_NEW;    // new region to be created when RS merges two
55                      // daughter regions but hasn't be created yet, or
56                      // master doesn't know it's already created
57  
58      /**
59       * Convert to protobuf ClusterStatusProtos.RegionState.State
60       */
61      public ClusterStatusProtos.RegionState.State convert() {
62        ClusterStatusProtos.RegionState.State rs;
63        switch (this) {
64        case OFFLINE:
65          rs = ClusterStatusProtos.RegionState.State.OFFLINE;
66          break;
67        case PENDING_OPEN:
68          rs = ClusterStatusProtos.RegionState.State.PENDING_OPEN;
69          break;
70        case OPENING:
71          rs = ClusterStatusProtos.RegionState.State.OPENING;
72          break;
73        case OPEN:
74          rs = ClusterStatusProtos.RegionState.State.OPEN;
75          break;
76        case PENDING_CLOSE:
77          rs = ClusterStatusProtos.RegionState.State.PENDING_CLOSE;
78          break;
79        case CLOSING:
80          rs = ClusterStatusProtos.RegionState.State.CLOSING;
81          break;
82        case CLOSED:
83          rs = ClusterStatusProtos.RegionState.State.CLOSED;
84          break;
85        case SPLITTING:
86          rs = ClusterStatusProtos.RegionState.State.SPLITTING;
87          break;
88        case SPLIT:
89          rs = ClusterStatusProtos.RegionState.State.SPLIT;
90          break;
91        case FAILED_OPEN:
92          rs = ClusterStatusProtos.RegionState.State.FAILED_OPEN;
93          break;
94        case FAILED_CLOSE:
95          rs = ClusterStatusProtos.RegionState.State.FAILED_CLOSE;
96          break;
97        case MERGING:
98          rs = ClusterStatusProtos.RegionState.State.MERGING;
99          break;
100       case MERGED:
101         rs = ClusterStatusProtos.RegionState.State.MERGED;
102         break;
103       case SPLITTING_NEW:
104         rs = ClusterStatusProtos.RegionState.State.SPLITTING_NEW;
105         break;
106       case MERGING_NEW:
107         rs = ClusterStatusProtos.RegionState.State.MERGING_NEW;
108         break;
109       default:
110         throw new IllegalStateException("");
111       }
112       return rs;
113     }
114 
115     /**
116      * Convert a protobuf HBaseProtos.RegionState.State to a RegionState.State
117      *
118      * @return the RegionState.State
119      */
120     public static State convert(ClusterStatusProtos.RegionState.State protoState) {
121       State state;
122       switch (protoState) {
123       case OFFLINE:
124         state = OFFLINE;
125         break;
126       case PENDING_OPEN:
127         state = PENDING_OPEN;
128         break;
129       case OPENING:
130         state = OPENING;
131         break;
132       case OPEN:
133         state = OPEN;
134         break;
135       case PENDING_CLOSE:
136         state = PENDING_CLOSE;
137         break;
138       case CLOSING:
139         state = CLOSING;
140         break;
141       case CLOSED:
142         state = CLOSED;
143         break;
144       case SPLITTING:
145         state = SPLITTING;
146         break;
147       case SPLIT:
148         state = SPLIT;
149         break;
150       case FAILED_OPEN:
151         state = FAILED_OPEN;
152         break;
153       case FAILED_CLOSE:
154         state = FAILED_CLOSE;
155         break;
156       case MERGING:
157         state = MERGING;
158         break;
159       case MERGED:
160         state = MERGED;
161         break;
162       case SPLITTING_NEW:
163         state = SPLITTING_NEW;
164         break;
165       case MERGING_NEW:
166         state = MERGING_NEW;
167         break;
168       default:
169         throw new IllegalStateException("");
170       }
171       return state;
172     }
173   }
174 
175   private final long stamp;
176   private final HRegionInfo hri;
177   private final ServerName serverName;
178   private final State state;
179 
180   public RegionState(HRegionInfo region, State state) {
181     this(region, state, System.currentTimeMillis(), null);
182   }
183 
184   public RegionState(HRegionInfo region,
185       State state, ServerName serverName) {
186     this(region, state, System.currentTimeMillis(), serverName);
187   }
188 
189   public RegionState(HRegionInfo region,
190       State state, long stamp, ServerName serverName) {
191     this.hri = region;
192     this.state = state;
193     this.stamp = stamp;
194     this.serverName = serverName;
195   }
196 
197   public State getState() {
198     return state;
199   }
200 
201   public long getStamp() {
202     return stamp;
203   }
204 
205   public HRegionInfo getRegion() {
206     return hri;
207   }
208 
209   public ServerName getServerName() {
210     return serverName;
211   }
212 
213   /**
214    * PENDING_CLOSE (to be removed) is the same as CLOSING
215    */
216   public boolean isClosing() {
217     return state == State.PENDING_CLOSE || state == State.CLOSING;
218   }
219 
220   public boolean isClosed() {
221     return state == State.CLOSED;
222   }
223 
224   /**
225    * PENDING_OPEN (to be removed) is the same as OPENING
226    */
227   public boolean isOpening() {
228     return state == State.PENDING_OPEN || state == State.OPENING;
229   }
230 
231   public boolean isOpened() {
232     return state == State.OPEN;
233   }
234 
235   public boolean isOffline() {
236     return state == State.OFFLINE;
237   }
238 
239   public boolean isSplitting() {
240     return state == State.SPLITTING;
241   }
242 
243   public boolean isSplit() {
244     return state == State.SPLIT;
245   }
246 
247   public boolean isSplittingNew() {
248     return state == State.SPLITTING_NEW;
249   }
250 
251   public boolean isFailedOpen() {
252     return state == State.FAILED_OPEN;
253   }
254 
255   public boolean isFailedClose() {
256     return state == State.FAILED_CLOSE;
257   }
258 
259   public boolean isMerging() {
260     return state == State.MERGING;
261   }
262 
263   public boolean isMerged() {
264     return state == State.MERGED;
265   }
266 
267   public boolean isMergingNew() {
268     return state == State.MERGING_NEW;
269   }
270 
271   public boolean isOnServer(final ServerName sn) {
272     return serverName != null && serverName.equals(sn);
273   }
274 
275   public boolean isMergingOnServer(final ServerName sn) {
276     return isOnServer(sn) && isMerging();
277   }
278 
279   public boolean isMergingNewOnServer(final ServerName sn) {
280     return isOnServer(sn) && isMergingNew();
281   }
282 
283   public boolean isMergingNewOrOpenedOnServer(final ServerName sn) {
284     return isOnServer(sn) && (isMergingNew() || isOpened());
285   }
286 
287   public boolean isMergingNewOrOfflineOnServer(final ServerName sn) {
288     return isOnServer(sn) && (isMergingNew() || isOffline());
289   }
290 
291   public boolean isSplittingOnServer(final ServerName sn) {
292     return isOnServer(sn) && isSplitting();
293   }
294 
295   public boolean isSplittingNewOnServer(final ServerName sn) {
296     return isOnServer(sn) && isSplittingNew();
297   }
298 
299   public boolean isSplittingOrOpenedOnServer(final ServerName sn) {
300     return isOnServer(sn) && (isSplitting() || isOpened());
301   }
302 
303   public boolean isSplittingOrSplitOnServer(final ServerName sn) {
304     return isOnServer(sn) && (isSplitting() || isSplit());
305   }
306 
307   public boolean isClosingOrClosedOnServer(final ServerName sn) {
308     return isOnServer(sn) && (isClosing() || isClosed());
309   }
310 
311   public boolean isOpeningOrFailedOpenOnServer(final ServerName sn) {
312     return isOnServer(sn) && (isOpening() || isFailedOpen());
313   }
314 
315   public boolean isOpeningOrOpenedOnServer(final ServerName sn) {
316     return isOnServer(sn) && (isOpening() || isOpened());
317   }
318 
319   public boolean isOpenedOnServer(final ServerName sn) {
320     return isOnServer(sn) && isOpened();
321   }
322 
323   /**
324    * Check if a region state can transition to offline
325    */
326   public boolean isReadyToOffline() {
327     return isMerged() || isSplit() || isOffline()
328       || isSplittingNew() || isMergingNew();
329   }
330 
331   /**
332    * Check if a region state can transition to online
333    */
334   public boolean isReadyToOnline() {
335     return isOpened() || isSplittingNew() || isMergingNew();
336   }
337 
338   /**
339    * Check if a region state is one of offline states that
340    * can't transition to pending_close/closing (unassign/offline)
341    */
342   public boolean isUnassignable() {
343     return isUnassignable(state);
344   }
345 
346   /**
347    * Check if a region state is one of offline states that
348    * can't transition to pending_close/closing (unassign/offline)
349    */
350   public static boolean isUnassignable(State state) {
351     return state == State.MERGED || state == State.SPLIT || state == State.OFFLINE
352       || state == State.SPLITTING_NEW || state == State.MERGING_NEW;
353   }
354 
355   @Override
356   public String toString() {
357     return "{" + hri.getShortNameToLog()
358       + " state=" + state
359       + ", ts=" + stamp
360       + ", server=" + serverName + "}";
361   }
362 
363   /**
364    * A slower (but more easy-to-read) stringification
365    */
366   public String toDescriptiveString() {
367     long relTime = System.currentTimeMillis() - stamp;
368     return hri.getRegionNameAsString()
369       + " state=" + state
370       + ", ts=" + new Date(stamp) + " (" + (relTime/1000) + "s ago)"
371       + ", server=" + serverName;
372   }
373 
374   /**
375    * Convert a RegionState to an HBaseProtos.RegionState
376    *
377    * @return the converted HBaseProtos.RegionState
378    */
379   public ClusterStatusProtos.RegionState convert() {
380     ClusterStatusProtos.RegionState.Builder regionState = ClusterStatusProtos.RegionState.newBuilder();
381     regionState.setRegionInfo(HRegionInfo.convert(hri));
382     regionState.setState(state.convert());
383     regionState.setStamp(getStamp());
384     return regionState.build();
385   }
386 
387   /**
388    * Convert a protobuf HBaseProtos.RegionState to a RegionState
389    *
390    * @return the RegionState
391    */
392   public static RegionState convert(ClusterStatusProtos.RegionState proto) {
393     return new RegionState(HRegionInfo.convert(proto.getRegionInfo()),
394       State.convert(proto.getState()), proto.getStamp(), null);
395   }
396 
397   /**
398    * Check if two states are the same, except timestamp
399    */
400   @Override
401   public boolean equals(Object obj) {
402     if (this == obj) return true;
403     if (obj == null || getClass() != obj.getClass()) {
404       return false;
405     }
406     RegionState tmp = (RegionState)obj;
407     return tmp.hri.equals(hri) && tmp.state == state
408       && ((serverName != null && serverName.equals(tmp.serverName))
409         || (tmp.serverName == null && serverName == null));
410   }
411 
412   /**
413    * Don't count timestamp in hash code calculation
414    */
415   @Override
416   public int hashCode() {
417     return (serverName != null ? serverName.hashCode() * 11 : 0)
418       + hri.hashCode() + 5 * state.ordinal();
419   }
420 }