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 java.io.Closeable;
22 import java.io.DataInput;
23 import java.io.DataOutput;
24 import java.io.IOException;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import java.util.regex.Pattern;
28
29 import com.google.common.annotations.VisibleForTesting;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.classification.InterfaceStability;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.fs.FSDataInputStream;
36 import org.apache.hadoop.fs.FileSystem;
37 import org.apache.hadoop.fs.Path;
38 import org.apache.hadoop.hbase.HConstants;
39 import org.apache.hadoop.hbase.ServerName;
40 import org.apache.hadoop.hbase.util.FSUtils;
41
42
43 import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
44 import org.apache.hadoop.hbase.regionserver.wal.ProtobufLogWriter;
45 import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
46
47
48
49
50
51
52
53
54
55
56
57
58 @InterfaceAudience.Private
59 @InterfaceStability.Evolving
60 public class DefaultWALProvider implements WALProvider {
61 private static final Log LOG = LogFactory.getLog(DefaultWALProvider.class);
62
63
64 public interface Reader extends WAL.Reader {
65
66
67
68
69
70
71 void init(FileSystem fs, Path path, Configuration c, FSDataInputStream s) throws IOException;
72 }
73
74
75 public interface Writer extends WALProvider.Writer {
76 void init(FileSystem fs, Path path, Configuration c, boolean overwritable) throws IOException;
77 }
78
79 protected volatile FSHLog log = null;
80 private WALFactory factory = null;
81 private Configuration conf = null;
82 private List<WALActionsListener> listeners = null;
83 private String providerId = null;
84 private AtomicBoolean initialized = new AtomicBoolean(false);
85
86 private String logPrefix = null;
87
88
89
90
91 private final Object walCreateLock = new Object();
92
93
94
95
96
97
98
99
100 @Override
101 public void init(final WALFactory factory, final Configuration conf,
102 final List<WALActionsListener> listeners, String providerId) throws IOException {
103 if (!initialized.compareAndSet(false, true)) {
104 throw new IllegalStateException("WALProvider.init should only be called once.");
105 }
106 this.factory = factory;
107 this.conf = conf;
108 this.listeners = listeners;
109 this.providerId = providerId;
110
111 StringBuilder sb = new StringBuilder().append(factory.factoryId);
112 if (providerId != null) {
113 if (providerId.startsWith(WAL_FILE_NAME_DELIMITER)) {
114 sb.append(providerId);
115 } else {
116 sb.append(WAL_FILE_NAME_DELIMITER).append(providerId);
117 }
118 }
119 logPrefix = sb.toString();
120 }
121
122 @Override
123 public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
124 if (log == null) {
125
126
127 synchronized (walCreateLock) {
128 if (log == null) {
129 log = new FSHLog(FileSystem.get(conf), FSUtils.getRootDir(conf),
130 getWALDirectoryName(factory.factoryId), HConstants.HREGION_OLDLOGDIR_NAME, conf,
131 listeners, true, logPrefix,
132 META_WAL_PROVIDER_ID.equals(providerId) ? META_WAL_PROVIDER_ID : null);
133 }
134 }
135 }
136 return log;
137 }
138
139 @Override
140 public void close() throws IOException {
141 if (log != null) log.close();
142 }
143
144 @Override
145 public void shutdown() throws IOException {
146 if (log != null) log.shutdown();
147 }
148
149
150 public static final String WAL_FILE_NAME_DELIMITER = ".";
151
152 @VisibleForTesting
153 public static final String META_WAL_PROVIDER_ID = ".meta";
154 static final String DEFAULT_PROVIDER_ID = "default";
155
156
157
158 public static final String SPLITTING_EXT = "-splitting";
159
160
161
162
163
164
165 @Override
166 public long getNumLogFiles() {
167 return log == null ? 0 : this.log.getNumLogFiles();
168 }
169
170
171
172
173
174
175 @Override
176 public long getLogFileSize() {
177 return log == null ? 0 : this.log.getLogFileSize();
178 }
179
180
181
182
183 @VisibleForTesting
184 public static int getNumRolledLogFiles(WAL wal) {
185 return ((FSHLog)wal).getNumRolledLogFiles();
186 }
187
188
189
190
191 @VisibleForTesting
192 public static Path getCurrentFileName(final WAL wal) {
193 return ((FSHLog)wal).getCurrentFileName();
194 }
195
196
197
198
199 @VisibleForTesting
200 static void requestLogRoll(final WAL wal) {
201 ((FSHLog)wal).requestLogRoll();
202 }
203
204
205
206
207
208
209
210
211 @VisibleForTesting
212 public static long extractFileNumFromWAL(final WAL wal) {
213 final Path walName = ((FSHLog)wal).getCurrentFileName();
214 if (walName == null) {
215 throw new IllegalArgumentException("The WAL path couldn't be null");
216 }
217 final String[] walPathStrs = walName.toString().split("\\" + WAL_FILE_NAME_DELIMITER);
218 return Long.parseLong(walPathStrs[walPathStrs.length - (isMetaFile(walName) ? 2:1)]);
219 }
220
221
222
223
224
225 private static final Pattern pattern = Pattern.compile(".*\\.\\d*("+META_WAL_PROVIDER_ID+")*");
226
227
228
229
230
231
232
233
234
235
236
237 public static boolean validateWALFilename(String filename) {
238 return pattern.matcher(filename).matches();
239 }
240
241
242
243
244
245
246
247
248
249
250
251 public static String getWALDirectoryName(final String serverName) {
252 StringBuilder dirName = new StringBuilder(HConstants.HREGION_LOGDIR_NAME);
253 dirName.append("/");
254 dirName.append(serverName);
255 return dirName.toString();
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public static ServerName getServerNameFromWALDirectoryName(Configuration conf, String path)
275 throws IOException {
276 if (path == null
277 || path.length() <= HConstants.HREGION_LOGDIR_NAME.length()) {
278 return null;
279 }
280
281 if (conf == null) {
282 throw new IllegalArgumentException("parameter conf must be set");
283 }
284
285 final String rootDir = conf.get(HConstants.HBASE_DIR);
286 if (rootDir == null || rootDir.isEmpty()) {
287 throw new IllegalArgumentException(HConstants.HBASE_DIR
288 + " key not found in conf.");
289 }
290
291 final StringBuilder startPathSB = new StringBuilder(rootDir);
292 if (!rootDir.endsWith("/"))
293 startPathSB.append('/');
294 startPathSB.append(HConstants.HREGION_LOGDIR_NAME);
295 if (!HConstants.HREGION_LOGDIR_NAME.endsWith("/"))
296 startPathSB.append('/');
297 final String startPath = startPathSB.toString();
298
299 String fullPath;
300 try {
301 fullPath = FileSystem.get(conf).makeQualified(new Path(path)).toString();
302 } catch (IllegalArgumentException e) {
303 LOG.info("Call to makeQualified failed on " + path + " " + e.getMessage());
304 return null;
305 }
306
307 if (!fullPath.startsWith(startPath)) {
308 return null;
309 }
310
311 final String serverNameAndFile = fullPath.substring(startPath.length());
312
313 if (serverNameAndFile.indexOf('/') < "a,0,0".length()) {
314
315 return null;
316 }
317
318 Path p = new Path(path);
319 return getServerNameFromWALDirectoryName(p);
320 }
321
322
323
324
325
326
327
328
329
330
331
332 public static ServerName getServerNameFromWALDirectoryName(Path logFile) {
333 String logDirName = logFile.getParent().getName();
334
335 if (logDirName.equals(HConstants.HREGION_LOGDIR_NAME)) {
336 logDirName = logFile.getName();
337 }
338 ServerName serverName = null;
339 if (logDirName.endsWith(SPLITTING_EXT)) {
340 logDirName = logDirName.substring(0, logDirName.length() - SPLITTING_EXT.length());
341 }
342 try {
343 serverName = ServerName.parseServerName(logDirName);
344 } catch (IllegalArgumentException ex) {
345 serverName = null;
346 LOG.warn("Cannot parse a server name from path=" + logFile + "; " + ex.getMessage());
347 }
348 if (serverName != null && serverName.getStartcode() < 0) {
349 LOG.warn("Invalid log file path=" + logFile);
350 serverName = null;
351 }
352 return serverName;
353 }
354
355 public static boolean isMetaFile(Path p) {
356 return isMetaFile(p.getName());
357 }
358
359 public static boolean isMetaFile(String p) {
360 if (p != null && p.endsWith(META_WAL_PROVIDER_ID)) {
361 return true;
362 }
363 return false;
364 }
365
366
367
368
369 public static Writer createWriter(final Configuration conf, final FileSystem fs, final Path path,
370 final boolean overwritable)
371 throws IOException {
372
373 Class<? extends Writer> logWriterClass = conf.getClass("hbase.regionserver.hlog.writer.impl",
374 ProtobufLogWriter.class, Writer.class);
375 Writer writer = null;
376 try {
377 writer = logWriterClass.newInstance();
378 writer.init(fs, path, conf, overwritable);
379 return writer;
380 } catch (Exception e) {
381 LOG.debug("Error instantiating log writer.", e);
382 if (writer != null) {
383 try{
384 writer.close();
385 } catch(IOException ee){
386 LOG.error("cannot close log writer", ee);
387 }
388 }
389 throw new IOException("cannot get log writer", e);
390 }
391 }
392
393
394
395
396
397
398
399 public static String getWALPrefixFromWALName(String name) {
400 int endIndex = name.replaceAll(META_WAL_PROVIDER_ID, "").lastIndexOf(".");
401 return name.substring(0, endIndex);
402 }
403
404 }