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.Collection;
24 import java.util.List;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.util.CommonFSUtils;
34 import org.apache.hadoop.hbase.wal.WAL.Entry;
35
36 import static org.apache.hadoop.hbase.wal.DefaultWALProvider.DEFAULT_PROVIDER_ID;
37 import static org.apache.hadoop.hbase.wal.DefaultWALProvider.META_WAL_PROVIDER_ID;
38 import static org.apache.hadoop.hbase.wal.DefaultWALProvider.WAL_FILE_NAME_DELIMITER;
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @InterfaceAudience.Private
73 public class IOTestProvider implements WALProvider {
74 private static final Log LOG = LogFactory.getLog(IOTestProvider.class);
75
76 private static final String ALLOWED_OPERATIONS = "hbase.wal.iotestprovider.operations";
77 private enum AllowedOperations {
78 all,
79 append,
80 sync,
81 fileroll,
82 none;
83 }
84
85 private FSHLog log = null;
86
87
88
89
90
91
92
93
94 @Override
95 public void init(final WALFactory factory, final Configuration conf,
96 final List<WALActionsListener> listeners, String providerId) throws IOException {
97 if (null != log) {
98 throw new IllegalStateException("WALProvider.init should only be called once.");
99 }
100 if (null == providerId) {
101 providerId = DEFAULT_PROVIDER_ID;
102 }
103 final String logPrefix = factory.factoryId + WAL_FILE_NAME_DELIMITER + providerId;
104 log = new IOTestWAL(CommonFSUtils.getWALFileSystem(conf), CommonFSUtils.getWALRootDir(conf),
105 DefaultWALProvider.getWALDirectoryName(factory.factoryId),
106 HConstants.HREGION_OLDLOGDIR_NAME, conf, listeners,
107 true, logPrefix, META_WAL_PROVIDER_ID.equals(providerId) ? META_WAL_PROVIDER_ID : null);
108 }
109
110 @Override
111 public List<WAL> getWALs() throws IOException {
112 List<WAL> wals = new ArrayList<WAL>();
113 wals.add(log);
114 return wals;
115 }
116
117 @Override
118 public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
119 return log;
120 }
121
122 @Override
123 public void close() throws IOException {
124 log.close();
125 }
126
127 @Override
128 public void shutdown() throws IOException {
129 log.shutdown();
130 }
131
132 private static class IOTestWAL extends FSHLog {
133
134 private final boolean doFileRolls;
135
136
137 private final boolean initialized;
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public IOTestWAL(final FileSystem fs, final Path rootDir, final String logDir,
164 final String archiveDir, final Configuration conf,
165 final List<WALActionsListener> listeners,
166 final boolean failIfWALExists, final String prefix, final String suffix)
167 throws IOException {
168 super(fs, rootDir, logDir, archiveDir, conf, listeners, failIfWALExists, prefix, suffix);
169 Collection<String> operations = conf.getStringCollection(ALLOWED_OPERATIONS);
170 doFileRolls = operations.isEmpty() || operations.contains(AllowedOperations.all.name()) ||
171 operations.contains(AllowedOperations.fileroll.name());
172 initialized = true;
173 LOG.info("Initialized with file rolling " + (doFileRolls ? "enabled" : "disabled"));
174 }
175
176 private Writer noRollsWriter;
177
178
179
180 @Override
181 protected Writer createWriterInstance(final Path path) throws IOException {
182
183
184
185 if (!initialized || doFileRolls) {
186 LOG.info("creating new writer instance.");
187 final ProtobufLogWriter writer = new IOTestWriter();
188 try {
189 writer.init(fs, path, conf, false);
190 } catch (CommonFSUtils.StreamLacksCapabilityException exception) {
191 throw new IOException("Can't create writer instance because underlying FileSystem " +
192 "doesn't support needed stream capabilities.", exception);
193 }
194 if (!initialized) {
195 LOG.info("storing initial writer instance in case file rolling isn't allowed.");
196 noRollsWriter = writer;
197 }
198 return writer;
199 } else {
200 LOG.info("WAL rolling disabled, returning the first writer.");
201
202
203 return noRollsWriter;
204 }
205 }
206 }
207
208
209
210
211 private static class IOTestWriter extends ProtobufLogWriter {
212 private boolean doAppends;
213 private boolean doSyncs;
214
215 @Override
216 public void init(FileSystem fs, Path path, Configuration conf, boolean overwritable)
217 throws IOException, CommonFSUtils.StreamLacksCapabilityException {
218 Collection<String> operations = conf.getStringCollection(ALLOWED_OPERATIONS);
219 if (operations.isEmpty() || operations.contains(AllowedOperations.all.name())) {
220 doAppends = doSyncs = true;
221 } else if (operations.contains(AllowedOperations.none.name())) {
222 doAppends = doSyncs = false;
223 } else {
224 doAppends = operations.contains(AllowedOperations.append.name());
225 doSyncs = operations.contains(AllowedOperations.sync.name());
226 }
227 LOG.info("IOTestWriter initialized with appends " + (doAppends ? "enabled" : "disabled") +
228 " and syncs " + (doSyncs ? "enabled" : "disabled"));
229 super.init(fs, path, conf, overwritable);
230 }
231
232 @Override
233 public void append(Entry entry) throws IOException {
234 if (doAppends) {
235 super.append(entry);
236 }
237 }
238
239 @Override
240 public void sync(boolean forceSync) throws IOException {
241 if (doSyncs) {
242 super.sync(forceSync);
243 }
244 }
245 }
246
247 @Override
248 public long getNumLogFiles() {
249 return this.log.getNumLogFiles();
250 }
251
252 @Override
253 public long getLogFileSize() {
254 return this.log.getLogFileSize();
255 }
256 }