1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.regionserver.wal;
22
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.io.InterruptedIOException;
26 import java.util.List;
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.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.regionserver.wal.HLog.Reader;
37 import org.apache.hadoop.hbase.regionserver.wal.HLog.Writer;
38 import org.apache.hadoop.hbase.util.CancelableProgressable;
39 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
40
41 @InterfaceAudience.Private
42 public class HLogFactory {
43 private static final Log LOG = LogFactory.getLog(HLogFactory.class);
44
45 public static HLog createHLog(final FileSystem fs, final Path root, final String logName,
46 final Configuration conf) throws IOException {
47 return new FSHLog(fs, root, logName, conf);
48 }
49
50 public static HLog createHLog(final FileSystem fs, final Path root, final String logName,
51 final String oldLogName, final Configuration conf) throws IOException {
52 return new FSHLog(fs, root, logName, oldLogName, conf);
53 }
54
55 public static HLog createHLog(final FileSystem fs, final Path root, final String logName,
56 final Configuration conf, final List<WALActionsListener> listeners,
57 final String prefix) throws IOException {
58 return new FSHLog(fs, root, logName, conf, listeners, prefix);
59 }
60
61 public static HLog createMetaHLog(final FileSystem fs, final Path root, final String logName,
62 final Configuration conf, final List<WALActionsListener> listeners,
63 final String prefix) throws IOException {
64 return new FSHLog(fs, root, logName, HConstants.HREGION_OLDLOGDIR_NAME,
65 conf, listeners, false, prefix, true);
66 }
67
68
69
70
71 private static Class<? extends Reader> logReaderClass;
72
73 static void resetLogReaderClass() {
74 logReaderClass = null;
75 }
76
77 public static HLog.Reader createReader(final FileSystem fs,
78 final Path path, Configuration conf) throws IOException {
79 return createReader(fs, path, conf, null);
80 }
81
82
83
84
85
86
87
88
89 public static HLog.Reader createReader(final FileSystem fs, final Path path,
90 Configuration conf, CancelableProgressable reporter) throws IOException {
91 return createReader(fs, path, conf, reporter, true);
92 }
93
94 public static HLog.Reader createReader(final FileSystem fs, final Path path,
95 Configuration conf, CancelableProgressable reporter, boolean allowCustom)
96 throws IOException {
97 if (allowCustom && (logReaderClass == null)) {
98 logReaderClass = conf.getClass("hbase.regionserver.hlog.reader.impl",
99 ProtobufLogReader.class, Reader.class);
100 }
101 Class<? extends Reader> lrClass = allowCustom ? logReaderClass : ProtobufLogReader.class;
102
103 try {
104
105
106
107 long startWaiting = EnvironmentEdgeManager.currentTimeMillis();
108 long openTimeout = conf.getInt("hbase.hlog.open.timeout", 300000) + startWaiting;
109 int nbAttempt = 0;
110 FSDataInputStream stream = null;
111 while (true) {
112 try {
113 if (lrClass != ProtobufLogReader.class) {
114
115 HLog.Reader reader = lrClass.newInstance();
116 reader.init(fs, path, conf, null);
117 return reader;
118 } else {
119 stream = fs.open(path);
120
121
122
123
124 byte[] magic = new byte[ProtobufLogReader.PB_WAL_MAGIC.length];
125 boolean isPbWal = (stream.read(magic) == magic.length)
126 && Arrays.equals(magic, ProtobufLogReader.PB_WAL_MAGIC);
127 HLog.Reader reader =
128 isPbWal ? new ProtobufLogReader() : new SequenceFileLogReader();
129 reader.init(fs, path, conf, stream);
130 return reader;
131 }
132 } catch (IOException e) {
133 try {
134 if (stream != null) {
135 stream.close();
136 }
137 } catch (IOException exception) {
138 LOG.warn("Could not close FSDataInputStream" + exception.getMessage());
139 LOG.debug("exception details", exception);
140 }
141 String msg = e.getMessage();
142 if (msg != null && (msg.contains("Cannot obtain block length")
143 || msg.contains("Could not obtain the last block")
144 || msg.matches("Blocklist for [^ ]* has changed.*"))) {
145 if (++nbAttempt == 1) {
146 LOG.warn("Lease should have recovered. This is not expected. Will retry", e);
147 }
148 if (reporter != null && !reporter.progress()) {
149 throw new InterruptedIOException("Operation is cancelled");
150 }
151 if (nbAttempt > 2 && openTimeout < EnvironmentEdgeManager.currentTimeMillis()) {
152 LOG.error("Can't open after " + nbAttempt + " attempts and "
153 + (EnvironmentEdgeManager.currentTimeMillis() - startWaiting)
154 + "ms " + " for " + path);
155 } else {
156 try {
157 Thread.sleep(nbAttempt < 3 ? 500 : 1000);
158 continue;
159 } catch (InterruptedException ie) {
160 InterruptedIOException iioe = new InterruptedIOException();
161 iioe.initCause(ie);
162 throw iioe;
163 }
164 }
165 }
166 throw e;
167 }
168 }
169 } catch (IOException ie) {
170 throw ie;
171 } catch (Exception e) {
172 throw new IOException("Cannot get log reader", e);
173 }
174 }
175
176
177
178
179 private static Class<? extends Writer> logWriterClass;
180
181 static void resetLogWriterClass() {
182 logWriterClass = null;
183 }
184
185
186
187
188
189
190 public static HLog.Writer createWALWriter(final FileSystem fs,
191 final Path path, Configuration conf) throws IOException {
192 return createWriter(fs, path, conf, false);
193 }
194
195 public static HLog.Writer createRecoveredEditsWriter(final FileSystem fs,
196 final Path path, Configuration conf) throws IOException {
197 return createWriter(fs, path, conf, true);
198 }
199
200 private static HLog.Writer createWriter(final FileSystem fs,
201 final Path path, Configuration conf, boolean overwritable)
202 throws IOException {
203 try {
204 if (logWriterClass == null) {
205 logWriterClass = conf.getClass("hbase.regionserver.hlog.writer.impl",
206 ProtobufLogWriter.class, Writer.class);
207 }
208 HLog.Writer writer = (HLog.Writer)logWriterClass.newInstance();
209 writer.init(fs, path, conf, overwritable);
210 return writer;
211 } catch (Exception e) {
212 throw new IOException("cannot get log writer", e);
213 }
214 }
215 }