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.wal;
20  
21  import java.io.IOException;
22  import java.util.List;
23  import java.util.concurrent.atomic.AtomicInteger;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
30  // imports for classes still in regionserver.wal
31  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
32  
33  /**
34   * A WAL Provider that pre-creates N WALProviders and then limits our grouping strategy to them.
35   * Control the number of delegate providers via "hbase.wal.regiongrouping.numgroups." Control
36   * the choice of delegate provider implementation and the grouping strategy the same as
37   * {@link RegionGroupingProvider}.
38   */
39  @InterfaceAudience.Private
40  public class BoundedRegionGroupingProvider extends RegionGroupingProvider {
41    private static final Log LOG = LogFactory.getLog(BoundedRegionGroupingProvider.class);
42  
43    static final String NUM_REGION_GROUPS = "hbase.wal.regiongrouping.numgroups";
44    static final int DEFAULT_NUM_REGION_GROUPS = 2;
45    private WALProvider[] delegates;
46    private AtomicInteger counter = new AtomicInteger(0);
47  
48    @Override
49    public void init(final WALFactory factory, final Configuration conf,
50        final List<WALActionsListener> listeners, final String providerId) throws IOException {
51      super.init(factory, conf, listeners, providerId);
52      // no need to check for and close down old providers; our parent class will throw on re-invoke
53      delegates = new WALProvider[Math.max(1, conf.getInt(NUM_REGION_GROUPS,
54          DEFAULT_NUM_REGION_GROUPS))];
55      for (int i = 0; i < delegates.length; i++) {
56        delegates[i] = factory.getProvider(DELEGATE_PROVIDER, DEFAULT_DELEGATE_PROVIDER, listeners,
57            providerId + i);
58      }
59      LOG.info("Configured to run with " + delegates.length + " delegate WAL providers.");
60    }
61  
62    @Override
63    WALProvider populateCache(final byte[] group) {
64      final WALProvider temp = delegates[counter.getAndIncrement() % delegates.length];
65      final WALProvider extant = cached.putIfAbsent(group, temp);
66      // if someone else beat us to initializing, just take what they set.
67      // note that in such a case we skew load away from the provider we picked at first
68      return extant == null ? temp : extant;
69    }
70  
71    @Override
72    public void shutdown() throws IOException {
73      // save the last exception and rethrow
74      IOException failure = null;
75      for (WALProvider provider : delegates) {
76        try {
77          provider.shutdown();
78        } catch (IOException exception) {
79          LOG.error("Problem shutting down provider '" + provider + "': " + exception.getMessage());
80          LOG.debug("Details of problem shutting down provider '" + provider + "'", exception);
81          failure = exception;
82        }
83      }
84      if (failure != null) {
85        throw failure;
86      }
87    }
88  
89    @Override
90    public void close() throws IOException {
91      // save the last exception and rethrow
92      IOException failure = null;
93      for (WALProvider provider : delegates) {
94        try {
95          provider.close();
96        } catch (IOException exception) {
97          LOG.error("Problem closing provider '" + provider + "': " + exception.getMessage());
98          LOG.debug("Details of problem shutting down provider '" + provider + "'", exception);
99          failure = exception;
100       }
101     }
102     if (failure != null) {
103       throw failure;
104     }
105   }
106 
107   /**
108    * iff the given WALFactory is using the BoundedRegionGroupingProvider for meta and/or non-meta,
109    * count the number of files (rolled and active). if either of them isn't, count 0
110    * for that provider.
111    * @param walFactory may not be null.
112    */
113   public static long getNumLogFiles(WALFactory walFactory) {
114     long result = 0;
115     if (walFactory.provider instanceof BoundedRegionGroupingProvider) {
116       BoundedRegionGroupingProvider groupProviders =
117           (BoundedRegionGroupingProvider)walFactory.provider;
118       for (int i = 0; i < groupProviders.delegates.length; i++) {
119         result +=
120             ((FSHLog)((DefaultWALProvider)(groupProviders.delegates[i])).log).getNumLogFiles();
121       }
122     }
123     WALProvider meta = walFactory.metaProvider.get();
124     if (meta instanceof BoundedRegionGroupingProvider) {
125       for (int i = 0; i < ((BoundedRegionGroupingProvider)meta).delegates.length; i++) {
126         result += ((FSHLog)
127             ((DefaultWALProvider)(((BoundedRegionGroupingProvider)meta).delegates[i])).log)
128             .getNumLogFiles();      }
129     }
130     return result;
131   }
132 
133   /**
134    * iff the given WALFactory is using the BoundedRegionGroupingProvider for meta and/or non-meta,
135    * count the size of files (rolled and active). if either of them isn't, count 0
136    * for that provider.
137    * @param walFactory may not be null.
138    */
139   public static long getLogFileSize(WALFactory walFactory) {
140     long result = 0;
141     if (walFactory.provider instanceof BoundedRegionGroupingProvider) {
142       BoundedRegionGroupingProvider groupProviders =
143           (BoundedRegionGroupingProvider)walFactory.provider;
144       for (int i = 0; i < groupProviders.delegates.length; i++) {
145         result +=
146             ((FSHLog)((DefaultWALProvider)(groupProviders.delegates[i])).log).getLogFileSize();
147       }
148     }
149     WALProvider meta = walFactory.metaProvider.get();
150     if (meta instanceof BoundedRegionGroupingProvider) {
151       for (int i = 0; i < ((BoundedRegionGroupingProvider)meta).delegates.length; i++) {
152         result += ((FSHLog)
153             ((DefaultWALProvider)(((BoundedRegionGroupingProvider)meta).delegates[i])).log)
154             .getLogFileSize();
155       }
156     }
157     return result;
158   }
159 }