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.master.handler;
21  
22  import java.io.IOException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
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.master.DeadServer;
30  import org.apache.hadoop.hbase.master.MasterServices;
31  import org.apache.zookeeper.KeeperException;
32  
33  /**
34   * Shutdown handler for the server hosting <code>-ROOT-</code>,
35   * <code>.META.</code>, or both.
36   */
37  public class MetaServerShutdownHandler extends ServerShutdownHandler {
38    private final boolean carryingRoot;
39    private final boolean carryingMeta;
40    private static final Log LOG = LogFactory.getLog(MetaServerShutdownHandler.class);
41    public MetaServerShutdownHandler(final Server server,
42        final MasterServices services,
43        final DeadServer deadServers, final ServerName serverName,
44        final boolean carryingRoot, final boolean carryingMeta) {
45      super(server, services, deadServers, serverName,
46        EventType.M_META_SERVER_SHUTDOWN, true);
47      this.carryingRoot = carryingRoot;
48      this.carryingMeta = carryingMeta;
49    }
50  
51    @Override
52    public void process() throws IOException {
53  
54      boolean gotException = true;
55      try {
56        try {
57          if (this.shouldSplitHlog) {
58            if (this.services.shouldSplitMetaSeparately()) {
59              LOG.info("Splitting META logs for " + serverName);
60              this.services.getMasterFileSystem().splitMetaLog(serverName);
61            } else {
62              LOG.info("Splitting all logs for " + serverName);
63              this.services.getMasterFileSystem().splitAllLogs(serverName);
64            }
65          }
66        } catch (IOException ioe) {
67          this.services.getExecutorService().submit(this);
68          this.deadServers.add(serverName);
69          throw new IOException("failed log splitting for " +
70              serverName + ", will retry", ioe);
71        }
72    
73        // Assign root and meta if we were carrying them.
74        if (isCarryingRoot()) { // -ROOT-
75          // Check again: region may be assigned to other where because of RIT
76          // timeout
77          if (this.services.getAssignmentManager().isCarryingRoot(serverName)) {
78            LOG.info("Server " + serverName
79                + " was carrying ROOT. Trying to assign.");
80            this.services.getAssignmentManager().regionOffline(
81                HRegionInfo.ROOT_REGIONINFO);
82            verifyAndAssignRootWithRetries();
83          } else {
84            LOG.info("ROOT has been assigned to otherwhere, skip assigning.");
85          }
86        }
87    
88        // Carrying meta?
89        if (isCarryingMeta()) {
90          // Check again: region may be assigned to other where because of RIT
91          // timeout
92          if (this.services.getAssignmentManager().isCarryingMeta(serverName)) {
93            LOG.info("Server " + serverName
94                + " was carrying META. Trying to assign.");
95            this.services.getAssignmentManager().regionOffline(
96                HRegionInfo.FIRST_META_REGIONINFO);
97            this.services.getAssignmentManager().assignMeta();
98          } else {
99            LOG.info("META has been assigned to otherwhere, skip assigning.");
100         }
101       }
102       
103       gotException = false;
104     } finally {
105       if (gotException){
106         // If we had an exception, this.deadServers.finish will be skipped in super.process()
107         this.deadServers.finish(serverName);
108       }
109     }
110 
111     super.process();
112   }
113   /**
114    * Before assign the ROOT region, ensure it haven't
115    *  been assigned by other place
116    * <p>
117    * Under some scenarios, the ROOT region can be opened twice, so it seemed online
118    * in two regionserver at the same time.
119    * If the ROOT region has been assigned, so the operation can be canceled.
120    * @throws InterruptedException
121    * @throws IOException
122    * @throws KeeperException
123    */
124   private void verifyAndAssignRoot()
125   throws InterruptedException, IOException, KeeperException {
126     long timeout = this.server.getConfiguration().
127       getLong("hbase.catalog.verification.timeout", 1000);
128     if (!this.server.getCatalogTracker().verifyRootRegionLocation(timeout)) {
129       this.services.getAssignmentManager().assignRoot();
130     } else if (serverName.equals(server.getCatalogTracker().getRootLocation())) {
131       throw new IOException("-ROOT- is onlined on the dead server "
132           + serverName);
133     } else {
134       LOG.info("Skip assigning -ROOT-, because it is online on the "
135           + server.getCatalogTracker().getRootLocation());
136     }
137   }
138 
139   /**
140    * Failed many times, shutdown processing
141    * @throws IOException
142    */
143   private void verifyAndAssignRootWithRetries() throws IOException {
144     int iTimes = this.server.getConfiguration().getInt(
145         "hbase.catalog.verification.retries", 10);
146 
147     long waitTime = this.server.getConfiguration().getLong(
148         "hbase.catalog.verification.timeout", 1000);
149 
150     int iFlag = 0;
151     while (true) {
152       try {
153         verifyAndAssignRoot();
154         break;
155       } catch (KeeperException e) {
156         this.server.abort("In server shutdown processing, assigning root", e);
157         throw new IOException("Aborting", e);
158       } catch (Exception e) {
159         if (iFlag >= iTimes) {
160           this.server.abort("verifyAndAssignRoot failed after" + iTimes
161               + " times retries, aborting", e);
162           throw new IOException("Aborting", e);
163         }
164         try {
165           Thread.sleep(waitTime);
166         } catch (InterruptedException e1) {
167           LOG.warn("Interrupted when is the thread sleep", e1);
168           Thread.currentThread().interrupt();
169           throw new IOException("Interrupted", e1);
170         }
171         iFlag++;
172       }
173     }
174   }
175 
176   boolean isCarryingRoot() {
177     return this.carryingRoot;
178   }
179 
180   boolean isCarryingMeta() {
181     return this.carryingMeta;
182   }
183   
184   @Override
185   public String toString() {
186     String name = "UnknownServerName";
187     if(server != null && server.getServerName() != null) {
188       name = server.getServerName().toString();
189     }
190     return getClass().getSimpleName() + "-" + name + "-" + getSeqid();
191   }
192 }