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;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.HConstants;
25  import org.apache.hadoop.hbase.HRegionInfo;
26  import org.apache.hadoop.hbase.client.Delete;
27  import org.apache.hadoop.hbase.client.Get;
28  import org.apache.hadoop.hbase.client.Put;
29  import org.apache.hadoop.hbase.client.Result;
30  import org.apache.hadoop.hbase.ipc.HRegionInterface;
31  import org.apache.hadoop.hbase.util.Writables;
32  
33  import java.io.IOException;
34  import java.util.HashSet;
35  import java.util.Map;
36  import java.util.TreeMap;
37  
38  /**
39   * Instantiated to enable or disable a table
40   */
41  class ChangeTableState extends TableOperation {
42    private final Log LOG = LogFactory.getLog(this.getClass());
43    private boolean online;
44    // Do in order.
45    protected final Map<String, HashSet<HRegionInfo>> servedRegions =
46      new TreeMap<String, HashSet<HRegionInfo>>();
47    protected long lockid;
48  
49    ChangeTableState(final HMaster master, final byte [] tableName,
50      final boolean onLine)
51    throws IOException {
52      super(master, tableName);
53      this.online = onLine;
54    }
55  
56    @Override
57    protected void processScanItem(String serverName, HRegionInfo info) {
58      if (isBeingServed(serverName)) {
59        HashSet<HRegionInfo> regions = this.servedRegions.get(serverName);
60        if (regions == null) {
61          regions = new HashSet<HRegionInfo>();
62        }
63        regions.add(info);
64        this.servedRegions.put(serverName, regions);
65      }
66    }
67  
68    @Override
69    protected void postProcessMeta(MetaRegion m, HRegionInterface server)
70    throws IOException {
71      // Process regions not being served
72      if (LOG.isDebugEnabled()) {
73        LOG.debug("Processing unserved regions");
74      }
75      for (HRegionInfo i: this.unservedRegions) {
76        if (i.isOffline() && i.isSplit()) {
77          if (LOG.isDebugEnabled()) {
78            LOG.debug("Skipping region " + i.toString() +
79              " because it is offline and split");
80          }
81          continue;
82        }
83  
84        if(!this.online && this.master.getRegionManager().
85            isPendingOpen(i.getRegionNameAsString())) {
86          LOG.debug("Skipping region " + i.toString() +
87            " because it is pending open, will tell it to close later");
88          continue;
89        }
90  
91        // If it's already offline then don't set it a second/third time, skip
92        // Same for online, don't set again if already online
93        if (!(i.isOffline() && !online) && !(!i.isOffline() && online)) {
94          // Update meta table
95          Put put = updateRegionInfo(i);
96          server.put(m.getRegionName(), put);
97          Delete delete = new Delete(i.getRegionName());
98          delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
99          delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER);
100         server.delete(m.getRegionName(), delete);
101       }
102       if (LOG.isDebugEnabled()) {
103         LOG.debug("Removed server and startcode from row and set online=" +
104           this.online + ": " + i.getRegionNameAsString());
105       }
106       synchronized (master.getRegionManager()) {
107         if (this.online) {
108           // Bring offline regions on-line
109           if (!this.master.getRegionManager().regionIsOpening(i.getRegionNameAsString())) {
110             this.master.getRegionManager().setUnassigned(i, false);
111           }
112         } else {
113           // Prevent region from getting assigned.
114           this.master.getRegionManager().removeRegion(i);
115         }
116       }
117     }
118 
119     // Process regions currently being served
120     if (LOG.isDebugEnabled()) {
121       LOG.debug("Processing regions currently being served");
122     }
123     synchronized (this.master.getRegionManager()) {
124       for (Map.Entry<String, HashSet<HRegionInfo>> e:
125           this.servedRegions.entrySet()) {
126         String serverName = e.getKey();
127         if (this.online) {
128           LOG.debug("Already online");
129           continue;                             // Already being served
130         }
131 
132         // Cause regions being served to be taken off-line and disabled
133         for (HRegionInfo i: e.getValue()) {
134           // The scan we did could be totally staled, get the freshest data
135           Get get = new Get(i.getRegionName());
136           get.addColumn(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
137           Result values = server.get(m.getRegionName(), get);
138           String serverAddress = BaseScanner.getServerAddress(values);
139           // If this region is unassigned, skip!
140           if(serverAddress.length() == 0) {
141             continue;
142           }
143           if (LOG.isDebugEnabled()) {
144             LOG.debug("Adding region " + i.getRegionNameAsString() +
145               " to setClosing list");
146           }
147           // this marks the regions to be closed
148           this.master.getRegionManager().setClosing(serverName, i, true);
149         }
150       }
151     }
152     this.servedRegions.clear();
153   }
154 
155   protected Put updateRegionInfo(final HRegionInfo i)
156   throws IOException {
157     i.setOffline(!online);
158     Put put = new Put(i.getRegionName());
159     put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, Writables.getBytes(i));
160     return put;
161   }
162 }