View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver.handler;
20  
21  import java.io.IOException;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.HRegionInfo;
27  import org.apache.hadoop.hbase.Server;
28  import org.apache.hadoop.hbase.ServerName;
29  import org.apache.hadoop.hbase.executor.EventHandler;
30  import org.apache.hadoop.hbase.executor.EventType;
31  import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;
32  import org.apache.hadoop.hbase.regionserver.HRegion;
33  import org.apache.hadoop.hbase.regionserver.RegionServerServices;
34  
35  /**
36   * Handles closing of a region on a region server.
37   */
38  @InterfaceAudience.Private
39  public class CloseRegionHandler extends EventHandler {
40    // NOTE on priorities shutting down.  There are none for close. There are some
41    // for open.  I think that is right.  On shutdown, we want the meta to close
42    // after the user regions have closed.  What
43    // about the case where master tells us to shutdown a catalog region and we
44    // have a running queue of user regions to close?
45    private static final Log LOG = LogFactory.getLog(CloseRegionHandler.class);
46  
47    private final RegionServerServices rsServices;
48    private final HRegionInfo regionInfo;
49  
50    // If true, the hosting server is aborting.  Region close process is different
51    // when we are aborting.
52    private final boolean abort;
53    private ServerName destination;
54  
55    /**
56     * This method used internally by the RegionServer to close out regions.
57     * @param server
58     * @param rsServices
59     * @param regionInfo
60     * @param abort If the regionserver is aborting.
61     * @param destination
62     */
63    public CloseRegionHandler(final Server server,
64        final RegionServerServices rsServices,
65        final HRegionInfo regionInfo, final boolean abort,
66        ServerName destination) {
67      this(server, rsServices, regionInfo, abort,
68        EventType.M_RS_CLOSE_REGION, destination);
69    }
70  
71    protected CloseRegionHandler(final Server server,
72        final RegionServerServices rsServices, HRegionInfo regionInfo,
73        boolean abort, EventType eventType, ServerName destination) {
74      super(server, eventType);
75      this.server = server;
76      this.rsServices = rsServices;
77      this.regionInfo = regionInfo;
78      this.abort = abort;
79      this.destination = destination;
80    }
81  
82    public HRegionInfo getRegionInfo() {
83      return regionInfo;
84    }
85  
86    @Override
87    public void process() {
88      try {
89        String name = regionInfo.getRegionNameAsString();
90        LOG.debug("Processing close of " + name);
91        String encodedRegionName = regionInfo.getEncodedName();
92        // Check that this region is being served here
93        HRegion region = this.rsServices.getFromOnlineRegions(encodedRegionName);
94        if (region == null) {
95          LOG.warn("Received CLOSE for region " + name + " but currently not serving - ignoring");
96          // TODO: do better than a simple warning
97          return;
98        }
99  
100       // Close the region
101       try {
102         if (region.close(abort) == null) {
103           // This region got closed.  Most likely due to a split.
104           // The split message will clean up the master state.
105           LOG.warn("Can't close region: was already closed during close(): " +
106             regionInfo.getRegionNameAsString());
107           return;
108         }
109       } catch (IOException ioe) {
110         // An IOException here indicates that we couldn't successfully flush the
111         // memstore before closing. So, we need to abort the server and allow
112         // the master to split our logs in order to recover the data.
113         server.abort("Unrecoverable exception while closing region " +
114           regionInfo.getRegionNameAsString() + ", still finishing close", ioe);
115         throw new RuntimeException(ioe);
116       }
117 
118       this.rsServices.removeFromOnlineRegions(region, destination);
119       rsServices.reportRegionStateTransition(TransitionCode.CLOSED, regionInfo);
120 
121       // Done!  Region is closed on this RS
122       LOG.debug("Closed " + region.getRegionNameAsString());
123     } finally {
124       this.rsServices.getRegionsInTransitionInRS().
125           remove(this.regionInfo.getEncodedNameAsBytes());
126     }
127   }
128 }