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