1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 package org.apache.hadoop.hbase.regionserver.wal;
21
22 import java.io.DataInput;
23 import java.io.DataOutput;
24 import java.io.IOException;
25 import java.util.UUID;
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.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.HRegionInfo;
36 import org.apache.hadoop.hbase.HTableDescriptor;
37 import org.apache.hadoop.hbase.exceptions.FailedLogCloseException;
38 import org.apache.hadoop.io.Writable;
39
40
41 @InterfaceAudience.Private
42 public interface HLog {
43 public static final Log LOG = LogFactory.getLog(HLog.class);
44
45 /** File Extension used while splitting an HLog into regions (HBASE-2312) */
46 public static final String SPLITTING_EXT = "-splitting";
47 public static final boolean SPLIT_SKIP_ERRORS_DEFAULT = false;
48 /** The META region's HLog filename extension */
49 public static final String META_HLOG_FILE_EXTN = ".meta";
50
51 static final Pattern EDITFILES_NAME_PATTERN = Pattern.compile("-?[0-9]+");
52 public static final String RECOVERED_LOG_TMPFILE_SUFFIX = ".temp";
53
54 public interface Reader {
55
56 /**
57 * @param fs File system.
58 * @param path Path.
59 * @param c Config.
60 * @param s Input stream that may have been pre-opened by the caller; may be null.
61 */
62 void init(FileSystem fs, Path path, Configuration c, FSDataInputStream s) throws IOException;
63
64 void close() throws IOException;
65
66 Entry next() throws IOException;
67
68 Entry next(Entry reuse) throws IOException;
69
70 void seek(long pos) throws IOException;
71
72 long getPosition() throws IOException;
73 void reset() throws IOException;
74 }
75
76 public interface Writer {
77 void init(FileSystem fs, Path path, Configuration c) throws IOException;
78
79 void close() throws IOException;
80
81 void sync() throws IOException;
82
83 void append(Entry entry) throws IOException;
84
85 long getLength() throws IOException;
86 }
87
88 /**
89 * Utility class that lets us keep track of the edit with it's key Only used
90 * when splitting logs
91 */
92 public static class Entry implements Writable {
93 private WALEdit edit;
94 private HLogKey key;
95
96 public Entry() {
97 edit = new WALEdit();
98 key = new HLogKey();
99 }
100
101 /**
102 * Constructor for both params
103 *
104 * @param edit
105 * log's edit
106 * @param key
107 * log's key
108 */
109 public Entry(HLogKey key, WALEdit edit) {
110 super();
111 this.key = key;
112 this.edit = edit;
113 }
114
115 /**
116 * Gets the edit
117 *
118 * @return edit
119 */
120 public WALEdit getEdit() {
121 return edit;
122 }
123
124 /**
125 * Gets the key
126 *
127 * @return key
128 */
129 public HLogKey getKey() {
130 return key;
131 }
132
133 /**
134 * Set compression context for this entry.
135 *
136 * @param compressionContext
137 * Compression context
138 */
139 public void setCompressionContext(CompressionContext compressionContext) {
140 edit.setCompressionContext(compressionContext);
141 key.setCompressionContext(compressionContext);
142 }
143
144 @Override
145 public String toString() {
146 return this.key + "=" + this.edit;
147 }
148
149 @Override
150 public void write(DataOutput dataOutput) throws IOException {
151 this.key.write(dataOutput);
152 this.edit.write(dataOutput);
153 }
154
155 @Override
156 public void readFields(DataInput dataInput) throws IOException {
157 this.key.readFields(dataInput);
158 this.edit.readFields(dataInput);
159 }
160 }
161
162 /**
163 * registers WALActionsListener
164 *
165 * @param listener
166 */
167 public void registerWALActionsListener(final WALActionsListener listener);
168
169 /**
170 * unregisters WALActionsListener
171 *
172 * @param listener
173 */
174 public boolean unregisterWALActionsListener(final WALActionsListener listener);
175
176 /**
177 * @return Current state of the monotonically increasing file id.
178 */
179 public long getFilenum();
180
181 /**
182 * Called by HRegionServer when it opens a new region to ensure that log
183 * sequence numbers are always greater than the latest sequence number of the
184 * region being brought on-line.
185 *
186 * @param newvalue
187 * We'll set log edit/sequence number to this value if it is greater
188 * than the current value.
189 */
190 public void setSequenceNumber(final long newvalue);
191
192 /**
193 * @return log sequence number
194 */
195 public long getSequenceNumber();
196
197 /**
198 * Roll the log writer. That is, start writing log messages to a new file.
199 *
200 * <p>
201 * The implementation is synchronized in order to make sure there's one rollWriter
202 * running at any given time.
203 *
204 * @return If lots of logs, flush the returned regions so next time through we
205 * can clean logs. Returns null if nothing to flush. Names are actual
206 * region names as returned by {@link HRegionInfo#getEncodedName()}
207 * @throws org.apache.hadoop.hbase.exceptions.FailedLogCloseException
208 * @throws IOException
209 */
210 public byte[][] rollWriter() throws FailedLogCloseException, IOException;
211
212 /**
213 * Roll the log writer. That is, start writing log messages to a new file.
214 *
215 * <p>
216 * The implementation is synchronized in order to make sure there's one rollWriter
217 * running at any given time.
218 *
219 * @param force
220 * If true, force creation of a new writer even if no entries have
221 * been written to the current writer
222 * @return If lots of logs, flush the returned regions so next time through we
223 * can clean logs. Returns null if nothing to flush. Names are actual
224 * region names as returned by {@link HRegionInfo#getEncodedName()}
225 * @throws org.apache.hadoop.hbase.exceptions.FailedLogCloseException
226 * @throws IOException
227 */
228 public byte[][] rollWriter(boolean force) throws FailedLogCloseException,
229 IOException;
230
231 /**
232 * Shut down the log.
233 *
234 * @throws IOException
235 */
236 public void close() throws IOException;
237
238 /**
239 * Shut down the log and delete the log directory
240 *
241 * @throws IOException
242 */
243 public void closeAndDelete() throws IOException;
244
245 /**
246 * Only used in tests.
247 *
248 * @param info
249 * @param tableName
250 * @param edits
251 * @param now
252 * @param htd
253 * @throws IOException
254 */
255 public void append(HRegionInfo info, byte[] tableName, WALEdit edits,
256 final long now, HTableDescriptor htd) throws IOException;
257
258 /**
259 * Append a set of edits to the log. Log edits are keyed by (encoded)
260 * regionName, rowname, and log-sequence-id. The HLog is not flushed after
261 * this transaction is written to the log.
262 *
263 * @param info
264 * @param tableName
265 * @param edits
266 * @param clusterId
267 * The originating clusterId for this edit (for replication)
268 * @param now
269 * @return txid of this transaction
270 * @throws IOException
271 */
272 public long appendNoSync(HRegionInfo info, byte[] tableName, WALEdit edits,
273 UUID clusterId, final long now, HTableDescriptor htd) throws IOException;
274
275 /**
276 * Append a set of edits to the log. Log edits are keyed by (encoded)
277 * regionName, rowname, and log-sequence-id. The HLog is flushed after this
278 * transaction is written to the log.
279 *
280 * @param info
281 * @param tableName
282 * @param edits
283 * @param clusterId
284 * The originating clusterId for this edit (for replication)
285 * @param now
286 * @param htd
287 * @return txid of this transaction
288 * @throws IOException
289 */
290 public long append(HRegionInfo info, byte[] tableName, WALEdit edits,
291 UUID clusterId, final long now, HTableDescriptor htd) throws IOException;
292
293 public void hsync() throws IOException;
294
295 public void hflush() throws IOException;
296
297 public void sync() throws IOException;
298
299 public void sync(long txid) throws IOException;
300
301 /**
302 * Obtain a log sequence number.
303 */
304 public long obtainSeqNum();
305
306 /**
307 * WAL keeps track of the sequence numbers that were not yet flushed from memstores
308 * in order to be able to do cleanup. This method tells WAL that some region is about
309 * to flush memstore.
310 *
311 * We stash the oldest seqNum for the region, and let the the next edit inserted in this
312 * region be recorded in {@link #append(HRegionInfo, byte[], WALEdit, long, HTableDescriptor)}
313 * as new oldest seqnum. In case of flush being aborted, we put the stashed value back;
314 * in case of flush succeeding, the seqNum of that first edit after start becomes the
315 * valid oldest seqNum for this region.
316 *
317 * @return current seqNum, to pass on to flushers (who will put it into the metadata of
318 * the resulting file as an upper-bound seqNum for that file), or NULL if flush
319 * should not be started.
320 */
321 public Long startCacheFlush(final byte[] encodedRegionName);
322
323 /**
324 * Complete the cache flush.
325 * @param encodedRegionName Encoded region name.
326 */
327 public void completeCacheFlush(final byte[] encodedRegionName);
328
329 /**
330 * Abort a cache flush. Call if the flush fails. Note that the only recovery
331 * for an aborted flush currently is a restart of the regionserver so the
332 * snapshot content dropped by the failure gets restored to the memstore.v
333 * @param encodedRegionName Encoded region name.
334 */
335 public void abortCacheFlush(byte[] encodedRegionName);
336
337 /**
338 * @return Coprocessor host.
339 */
340 public WALCoprocessorHost getCoprocessorHost();
341
342 /**
343 * Get LowReplication-Roller status
344 *
345 * @return lowReplicationRollEnabled
346 */
347 public boolean isLowReplicationRollEnabled();
348
349 /** Gets the earliest sequence number in the memstore for this particular region.
350 * This can serve as best-effort "recent" WAL number for this region.
351 * @param encodedRegionName The region to get the number for.
352 * @return The number if present, HConstants.NO_SEQNUM if absent.
353 */
354 public long getEarliestMemstoreSeqNum(byte[] encodedRegionName);
355 }