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