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.hadoop.hbase.RemoteExceptionHandler;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.concurrent.BlockingQueue;
28  import java.util.concurrent.LinkedBlockingQueue;
29  import java.util.concurrent.TimeUnit;
30  
31  /**
32   * MetaScanner <code>META</code> table.
33   *
34   * When a <code>META</code> server comes on line, a MetaRegion object is
35   * queued up by regionServerReport() and this thread wakes up.
36   *
37   * It's important to do this work in a separate thread, or else the blocking
38   * action would prevent other work from getting done.
39   */
40  class MetaScanner extends BaseScanner {
41    /** Initial work for the meta scanner is queued up here */
42    private volatile BlockingQueue<MetaRegion> metaRegionsToScan =
43      new LinkedBlockingQueue<MetaRegion>();
44  
45    private final List<MetaRegion> metaRegionsToRescan =
46      new ArrayList<MetaRegion>();
47  
48    /**
49     * Constructor
50     *
51     * @param master
52     */
53    public MetaScanner(HMaster master) {
54      super(master, false, master.getShutdownRequested());
55    }
56  
57    // Don't retry if we get an error while scanning. Errors are most often
58    // caused by the server going away. Wait until next rescan interval when
59    // things should be back to normal.
60    private boolean scanOneMetaRegion(MetaRegion region) {
61      while (!this.master.isClosed() &&
62          !this.master.getRegionManager().isInitialRootScanComplete() &&
63          this.master.getRegionManager().getRootRegionLocation() == null) {
64        sleep();
65      }
66      if (this.master.isClosed()) {
67        return false;
68      }
69  
70      try {
71        // Don't interrupt us while we're working
72        synchronized (scannerLock) {
73          scanRegion(region);
74          this.master.getRegionManager().putMetaRegionOnline(region);
75        }
76      } catch (IOException e) {
77        e = RemoteExceptionHandler.checkIOException(e);
78        LOG.warn("Scan one META region: " + region.toString(), e);
79        // The region may have moved (TestRegionServerAbort, etc.).  If
80        // so, either it won't be in the onlineMetaRegions list or its host
81        // address has changed and the containsValue will fail. If not
82        // found, best thing to do here is probably return.
83        if (!this.master.getRegionManager().isMetaRegionOnline(region.getStartKey())) {
84          LOG.debug("Scanned region is no longer in map of online " +
85          "regions or its value has changed");
86          return false;
87        }
88        // Make sure the file system is still available
89        this.master.checkFileSystem();
90      } catch (Exception e) {
91        // If for some reason we get some other kind of exception,
92        // at least log it rather than go out silently.
93        LOG.error("Unexpected exception", e);
94      }
95      return true;
96    }
97  
98    @Override
99    protected boolean initialScan() {
100     MetaRegion region = null;
101     while (!this.master.isClosed() &&
102         (region == null && metaRegionsToScan.size() > 0) &&
103           !metaRegionsScanned()) {
104       try {
105         region = metaRegionsToScan.poll(this.master.getThreadWakeFrequency(),
106           TimeUnit.MILLISECONDS);
107       } catch (InterruptedException e) {
108         // continue
109       }
110       if (region == null && metaRegionsToRescan.size() != 0) {
111         region = metaRegionsToRescan.remove(0);
112       }
113       if (region != null) {
114         if (!scanOneMetaRegion(region)) {
115           metaRegionsToRescan.add(region);
116         }
117       }
118     }
119     initialScanComplete = true;
120     return true;
121   }
122 
123   @Override
124   protected void maintenanceScan() {
125     List<MetaRegion> regions =
126       this.master.getRegionManager().getListOfOnlineMetaRegions();
127     int regionCount = 0;
128     for (MetaRegion r: regions) {
129       scanOneMetaRegion(r);
130       regionCount++;
131     }
132     LOG.info("All " + regionCount + " .META. region(s) scanned");
133     metaRegionsScanned();
134   }
135 
136   /*
137    * Called by the meta scanner when it has completed scanning all meta
138    * regions. This wakes up any threads that were waiting for this to happen.
139    * @param totalRows Total rows scanned.
140    * @param regionCount Count of regions in  .META. table.
141    * @return False if number of meta regions matches count of online regions.
142    */
143   private synchronized boolean metaRegionsScanned() {
144     if (!this.master.getRegionManager().isInitialRootScanComplete() ||
145         this.master.getRegionManager().numMetaRegions() !=
146           this.master.getRegionManager().numOnlineMetaRegions()) {
147       return false;
148     }
149     notifyAll();
150     return true;
151   }
152 
153   /**
154    * Other threads call this method to wait until all the meta regions have
155    * been scanned.
156    */
157   synchronized boolean waitForMetaRegionsOrClose() {
158     while (!this.master.isClosed()) {
159       synchronized (master.getRegionManager()) {
160         if (this.master.getRegionManager().isInitialRootScanComplete() &&
161             this.master.getRegionManager().numMetaRegions() ==
162               this.master.getRegionManager().numOnlineMetaRegions()) {
163           break;
164         }
165       }
166       try {
167         wait(this.master.getThreadWakeFrequency());
168       } catch (InterruptedException e) {
169         // continue
170       }
171     }
172     return this.master.isClosed();
173   }
174 
175   /**
176    * Add another meta region to scan to the queue.
177    */
178   void addMetaRegionToScan(MetaRegion m) {
179     metaRegionsToScan.add(m);
180   }
181 }