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.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ConcurrentMap;
30 import java.util.concurrent.locks.Lock;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.classification.InterfaceAudience;
36
37 import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
38 import org.apache.hadoop.hbase.util.Bytes;
39 import org.apache.hadoop.hbase.util.IdReadWriteLock;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 @InterfaceAudience.Private
58 public class RegionGroupingProvider implements WALProvider {
59 private static final Log LOG = LogFactory.getLog(RegionGroupingProvider.class);
60
61
62
63
64 public static interface RegionGroupingStrategy {
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 if (providerClass.equals(this.getClass())) {
162 LOG.warn("delegate provider not support multiwal, falling back to defaultProvider.");
163 providerClass = WALFactory.Providers.defaultProvider.clazz;
164 }
165 }
166
167 private WALProvider createProvider(String group) throws IOException {
168 if (META_WAL_PROVIDER_ID.equals(providerId)) {
169 return factory.createProvider(providerClass, listeners, META_WAL_PROVIDER_ID);
170 } else {
171 return factory.createProvider(providerClass, listeners, group);
172 }
173 }
174
175 @Override
176 public List<WAL> getWALs() throws IOException {
177 List<WAL> wals = new ArrayList<WAL>();
178 for (WALProvider provider : cached.values()) {
179 wals.addAll(provider.getWALs());
180 }
181 return wals;
182 }
183
184 private WAL getWAL(final String group) throws IOException {
185 WALProvider provider = cached.get(group);
186 if (provider == null) {
187 Lock lock = createLock.getLock(group.hashCode()).writeLock();
188 lock.lock();
189 try {
190 provider = cached.get(group);
191 if (provider == null) {
192 provider = createProvider(group);
193 cached.put(group, provider);
194 }
195 } finally {
196 lock.unlock();
197 }
198 }
199 return provider.getWAL(null, null);
200 }
201
202 @Override
203 public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
204 final String group;
205 if (META_WAL_PROVIDER_ID.equals(this.providerId)) {
206 group = META_WAL_GROUP_NAME;
207 } else {
208 group = strategy.group(identifier, namespace);
209 }
210 return getWAL(group);
211 }
212
213 @Override
214 public void shutdown() throws IOException {
215
216 IOException failure = null;
217 for (WALProvider provider: cached.values()) {
218 try {
219 provider.shutdown();
220 } catch (IOException e) {
221 LOG.error("Problem shutting down wal provider '" + provider + "': " + e.getMessage());
222 if (LOG.isDebugEnabled()) {
223 LOG.debug("Details of problem shutting down wal provider '" + provider + "'", e);
224 }
225 failure = e;
226 }
227 }
228 if (failure != null) {
229 throw failure;
230 }
231 }
232
233 @Override
234 public void close() throws IOException {
235
236 IOException failure = null;
237 for (WALProvider provider : cached.values()) {
238 try {
239 provider.close();
240 } catch (IOException e) {
241 LOG.error("Problem closing wal provider '" + provider + "': " + e.getMessage());
242 if (LOG.isDebugEnabled()) {
243 LOG.debug("Details of problem closing wal provider '" + provider + "'", e);
244 }
245 failure = e;
246 }
247 }
248 if (failure != null) {
249 throw failure;
250 }
251 }
252
253 static class IdentityGroupingStrategy implements RegionGroupingStrategy {
254 @Override
255 public void init(Configuration config, String providerId) {}
256 @Override
257 public String group(final byte[] identifier, final byte[] namespace) {
258 return "identity-" + Bytes.toString(identifier);
259 }
260 }
261
262 @Override
263 public long getNumLogFiles() {
264 long numLogFiles = 0;
265 for (WALProvider provider : cached.values()) {
266 numLogFiles += provider.getNumLogFiles();
267 }
268 return numLogFiles;
269 }
270
271 @Override
272 public long getLogFileSize() {
273 long logFileSize = 0;
274 for (WALProvider provider : cached.values()) {
275 logFileSize += provider.getLogFileSize();
276 }
277 return logFileSize;
278 }
279 }