View Javadoc

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