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 String GROUP_NAME_DELIMITER = ".";
66
67
68
69
70 String group(final byte[] identifier, byte[] namespace);
71 void init(Configuration config, String providerId);
72 }
73
74
75
76
77 static enum Strategies {
78 defaultStrategy(BoundedGroupingStrategy.class),
79 identity(IdentityGroupingStrategy.class),
80 bounded(BoundedGroupingStrategy.class),
81 namespace(NamespaceGroupingStrategy.class);
82
83 final Class<? extends RegionGroupingStrategy> clazz;
84 Strategies(Class<? extends RegionGroupingStrategy> clazz) {
85 this.clazz = clazz;
86 }
87 }
88
89
90
91
92
93 RegionGroupingStrategy getStrategy(final Configuration conf, final String key,
94 final String defaultValue) throws IOException {
95 Class<? extends RegionGroupingStrategy> clazz;
96 try {
97 clazz = Strategies.valueOf(conf.get(key, defaultValue)).clazz;
98 } catch (IllegalArgumentException exception) {
99
100
101
102 clazz = conf.getClass(key, IdentityGroupingStrategy.class, RegionGroupingStrategy.class);
103 }
104 LOG.info("Instantiating RegionGroupingStrategy of type " + clazz);
105 try {
106 final RegionGroupingStrategy result = clazz.newInstance();
107 result.init(conf, providerId);
108 return result;
109 } catch (InstantiationException exception) {
110 LOG.error("couldn't set up region grouping strategy, check config key " +
111 REGION_GROUPING_STRATEGY);
112 LOG.debug("Exception details for failure to load region grouping strategy.", exception);
113 throw new IOException("couldn't set up region grouping strategy", exception);
114 } catch (IllegalAccessException exception) {
115 LOG.error("couldn't set up region grouping strategy, check config key " +
116 REGION_GROUPING_STRATEGY);
117 LOG.debug("Exception details for failure to load region grouping strategy.", exception);
118 throw new IOException("couldn't set up region grouping strategy", exception);
119 }
120 }
121
122 public static final String REGION_GROUPING_STRATEGY = "hbase.wal.regiongrouping.strategy";
123 public static final String DEFAULT_REGION_GROUPING_STRATEGY = Strategies.defaultStrategy.name();
124
125
126 public static final String DELEGATE_PROVIDER = "hbase.wal.regiongrouping.delegate.provider";
127 public static final String DEFAULT_DELEGATE_PROVIDER = WALFactory.Providers.defaultProvider
128 .name();
129
130 private static final String META_WAL_GROUP_NAME = "meta";
131
132
133 private final ConcurrentMap<String, WALProvider> cached = new ConcurrentHashMap<>();
134
135 private final IdReadWriteLock createLock = new IdReadWriteLock();
136
137 private RegionGroupingStrategy strategy = null;
138 private WALFactory factory = null;
139 private List<WALActionsListener> listeners = null;
140 private String providerId = null;
141 private Class<? extends WALProvider> providerClass;
142
143 @Override
144 public void init(final WALFactory factory, final Configuration conf,
145 final List<WALActionsListener> listeners, final String providerId) throws IOException {
146 if (null != strategy) {
147 throw new IllegalStateException("WALProvider.init should only be called once.");
148 }
149 this.factory = factory;
150 this.listeners = null == listeners ? null : Collections.unmodifiableList(listeners);
151 StringBuilder sb = new StringBuilder().append(factory.factoryId);
152 if (providerId != null) {
153 if (providerId.startsWith(WAL_FILE_NAME_DELIMITER)) {
154 sb.append(providerId);
155 } else {
156 sb.append(WAL_FILE_NAME_DELIMITER).append(providerId);
157 }
158 }
159 this.providerId = sb.toString();
160 this.strategy = getStrategy(conf, REGION_GROUPING_STRATEGY, DEFAULT_REGION_GROUPING_STRATEGY);
161 this.providerClass = factory.getProviderClass(DELEGATE_PROVIDER, DEFAULT_DELEGATE_PROVIDER);
162 }
163
164 private WALProvider createProvider(String group) throws IOException {
165 if (META_WAL_PROVIDER_ID.equals(providerId)) {
166 return factory.createProvider(providerClass, listeners, META_WAL_PROVIDER_ID);
167 } else {
168 return factory.createProvider(providerClass, listeners, group);
169 }
170 }
171
172 @Override
173 public List<WAL> getWALs() throws IOException {
174 List<WAL> wals = new ArrayList<WAL>();
175 for (WALProvider provider : cached.values()) {
176 wals.addAll(provider.getWALs());
177 }
178 return wals;
179 }
180
181 private WAL getWAL(final String group) throws IOException {
182 WALProvider provider = cached.get(group);
183 if (provider == null) {
184 Lock lock = createLock.getLock(group.hashCode()).writeLock();
185 lock.lock();
186 try {
187 provider = cached.get(group);
188 if (provider == null) {
189 provider = createProvider(group);
190 cached.put(group, provider);
191 }
192 } finally {
193 lock.unlock();
194 }
195 }
196 return provider.getWAL(null, null);
197 }
198
199 @Override
200 public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
201 final String group;
202 if (META_WAL_PROVIDER_ID.equals(this.providerId)) {
203 group = META_WAL_GROUP_NAME;
204 } else {
205 group = strategy.group(identifier, namespace);
206 }
207 return getWAL(group);
208 }
209
210 @Override
211 public void shutdown() throws IOException {
212
213 IOException failure = null;
214 for (WALProvider provider: cached.values()) {
215 try {
216 provider.shutdown();
217 } catch (IOException e) {
218 LOG.error("Problem shutting down wal provider '" + provider + "': " + e.getMessage());
219 if (LOG.isDebugEnabled()) {
220 LOG.debug("Details of problem shutting down wal provider '" + provider + "'", e);
221 }
222 failure = e;
223 }
224 }
225 if (failure != null) {
226 throw failure;
227 }
228 }
229
230 @Override
231 public void close() throws IOException {
232
233 IOException failure = null;
234 for (WALProvider provider : cached.values()) {
235 try {
236 provider.close();
237 } catch (IOException e) {
238 LOG.error("Problem closing wal provider '" + provider + "': " + e.getMessage());
239 if (LOG.isDebugEnabled()) {
240 LOG.debug("Details of problem closing wal provider '" + provider + "'", e);
241 }
242 failure = e;
243 }
244 }
245 if (failure != null) {
246 throw failure;
247 }
248 }
249
250 static class IdentityGroupingStrategy implements RegionGroupingStrategy {
251 @Override
252 public void init(Configuration config, String providerId) {}
253 @Override
254 public String group(final byte[] identifier, final byte[] namespace) {
255 return Bytes.toString(identifier);
256 }
257 }
258
259 @Override
260 public long getNumLogFiles() {
261 long numLogFiles = 0;
262 for (WALProvider provider : cached.values()) {
263 numLogFiles += provider.getNumLogFiles();
264 }
265 return numLogFiles;
266 }
267
268 @Override
269 public long getLogFileSize() {
270 long logFileSize = 0;
271 for (WALProvider provider : cached.values()) {
272 logFileSize += provider.getLogFileSize();
273 }
274 return logFileSize;
275 }
276 }