1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.wal;
20
21 import static org.apache.hadoop.hbase.wal.DefaultWALProvider.META_WAL_PROVIDER_ID;
22 import static org.apache.hadoop.hbase.wal.DefaultWALProvider.WAL_FILE_NAME_DELIMITER;
23
24 import java.io.IOException;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentMap;
29 import java.util.concurrent.locks.Lock;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.classification.InterfaceAudience;
35
36 import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.hadoop.hbase.util.IdReadWriteLock;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @InterfaceAudience.Private
57 public class RegionGroupingProvider implements WALProvider {
58 private static final Log LOG = LogFactory.getLog(RegionGroupingProvider.class);
59
60
61
62
63 public static interface RegionGroupingStrategy {
64 String GROUP_NAME_DELIMITER = ".";
65
66
67
68
69 String group(final byte[] identifier, byte[] namespace);
70 void init(Configuration config, String providerId);
71 }
72
73
74
75
76 static enum Strategies {
77 defaultStrategy(BoundedGroupingStrategy.class),
78 identity(IdentityGroupingStrategy.class),
79 bounded(BoundedGroupingStrategy.class),
80 namespace(NamespaceGroupingStrategy.class);
81
82 final Class<? extends RegionGroupingStrategy> clazz;
83 Strategies(Class<? extends RegionGroupingStrategy> clazz) {
84 this.clazz = clazz;
85 }
86 }
87
88
89
90
91
92 RegionGroupingStrategy getStrategy(final Configuration conf, final String key,
93 final String defaultValue) throws IOException {
94 Class<? extends RegionGroupingStrategy> clazz;
95 try {
96 clazz = Strategies.valueOf(conf.get(key, defaultValue)).clazz;
97 } catch (IllegalArgumentException exception) {
98
99
100
101 clazz = conf.getClass(key, IdentityGroupingStrategy.class, RegionGroupingStrategy.class);
102 }
103 LOG.info("Instantiating RegionGroupingStrategy of type " + clazz);
104 try {
105 final RegionGroupingStrategy result = clazz.newInstance();
106 result.init(conf, providerId);
107 return result;
108 } catch (InstantiationException exception) {
109 LOG.error("couldn't set up region grouping strategy, check config key " +
110 REGION_GROUPING_STRATEGY);
111 LOG.debug("Exception details for failure to load region grouping strategy.", exception);
112 throw new IOException("couldn't set up region grouping strategy", exception);
113 } catch (IllegalAccessException exception) {
114 LOG.error("couldn't set up region grouping strategy, check config key " +
115 REGION_GROUPING_STRATEGY);
116 LOG.debug("Exception details for failure to load region grouping strategy.", exception);
117 throw new IOException("couldn't set up region grouping strategy", exception);
118 }
119 }
120
121 public static final String REGION_GROUPING_STRATEGY = "hbase.wal.regiongrouping.strategy";
122 public static final String DEFAULT_REGION_GROUPING_STRATEGY = Strategies.defaultStrategy.name();
123
124
125 public static final String DELEGATE_PROVIDER = "hbase.wal.regiongrouping.delegate.provider";
126 public static final String DEFAULT_DELEGATE_PROVIDER = WALFactory.Providers.defaultProvider
127 .name();
128
129 private static final String META_WAL_GROUP_NAME = "meta";
130
131
132 private final ConcurrentMap<String, WALProvider> cached = new ConcurrentHashMap<>();
133
134 private final IdReadWriteLock createLock = new IdReadWriteLock();
135
136 private RegionGroupingStrategy strategy = null;
137 private WALFactory factory = null;
138 private List<WALActionsListener> listeners = null;
139 private String providerId = null;
140 private Class<? extends WALProvider> providerClass;
141
142 @Override
143 public void init(final WALFactory factory, final Configuration conf,
144 final List<WALActionsListener> listeners, final String providerId) throws IOException {
145 if (null != strategy) {
146 throw new IllegalStateException("WALProvider.init should only be called once.");
147 }
148 this.factory = factory;
149 this.listeners = null == listeners ? null : Collections.unmodifiableList(listeners);
150 StringBuilder sb = new StringBuilder().append(factory.factoryId);
151 if (providerId != null) {
152 if (providerId.startsWith(WAL_FILE_NAME_DELIMITER)) {
153 sb.append(providerId);
154 } else {
155 sb.append(WAL_FILE_NAME_DELIMITER).append(providerId);
156 }
157 }
158 this.providerId = sb.toString();
159 this.strategy = getStrategy(conf, REGION_GROUPING_STRATEGY, DEFAULT_REGION_GROUPING_STRATEGY);
160 this.providerClass = factory.getProviderClass(DELEGATE_PROVIDER, DEFAULT_DELEGATE_PROVIDER);
161 }
162
163 private WALProvider createProvider(String group) throws IOException {
164 if (META_WAL_PROVIDER_ID.equals(providerId)) {
165 return factory.createProvider(providerClass, listeners, META_WAL_PROVIDER_ID);
166 } else {
167 return factory.createProvider(providerClass, listeners, group);
168 }
169 }
170
171 private WAL getWAL(final String group) throws IOException {
172 WALProvider provider = cached.get(group);
173 if (provider == null) {
174 Lock lock = createLock.getLock(group.hashCode()).writeLock();
175 lock.lock();
176 try {
177 provider = cached.get(group);
178 if (provider == null) {
179 provider = createProvider(group);
180 cached.put(group, provider);
181 }
182 } finally {
183 lock.unlock();
184 }
185 }
186 return provider.getWAL(null, null);
187 }
188
189 @Override
190 public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
191 final String group;
192 if (META_WAL_PROVIDER_ID.equals(this.providerId)) {
193 group = META_WAL_GROUP_NAME;
194 } else {
195 group = strategy.group(identifier, namespace);
196 }
197 return getWAL(group);
198 }
199
200 @Override
201 public void shutdown() throws IOException {
202
203 IOException failure = null;
204 for (WALProvider provider: cached.values()) {
205 try {
206 provider.shutdown();
207 } catch (IOException e) {
208 LOG.error("Problem shutting down wal provider '" + provider + "': " + e.getMessage());
209 if (LOG.isDebugEnabled()) {
210 LOG.debug("Details of problem shutting down wal provider '" + provider + "'", e);
211 }
212 failure = e;
213 }
214 }
215 if (failure != null) {
216 throw failure;
217 }
218 }
219
220 @Override
221 public void close() throws IOException {
222
223 IOException failure = null;
224 for (WALProvider provider : cached.values()) {
225 try {
226 provider.close();
227 } catch (IOException e) {
228 LOG.error("Problem closing wal provider '" + provider + "': " + e.getMessage());
229 if (LOG.isDebugEnabled()) {
230 LOG.debug("Details of problem closing wal provider '" + provider + "'", e);
231 }
232 failure = e;
233 }
234 }
235 if (failure != null) {
236 throw failure;
237 }
238 }
239
240 static class IdentityGroupingStrategy implements RegionGroupingStrategy {
241 @Override
242 public void init(Configuration config, String providerId) {}
243 @Override
244 public String group(final byte[] identifier, final byte[] namespace) {
245 return Bytes.toString(identifier);
246 }
247 }
248
249 @Override
250 public long getNumLogFiles() {
251 long numLogFiles = 0;
252 for (WALProvider provider : cached.values()) {
253 numLogFiles += provider.getNumLogFiles();
254 }
255 return numLogFiles;
256 }
257
258 @Override
259 public long getLogFileSize() {
260 long logFileSize = 0;
261 for (WALProvider provider : cached.values()) {
262 logFileSize += provider.getLogFileSize();
263 }
264 return logFileSize;
265 }
266 }