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.wal;
21  
22  import java.io.Closeable;
23  import java.io.IOException;
24  import java.util.List;
25  import java.util.concurrent.atomic.AtomicLong;
26  
27  import org.apache.hadoop.hbase.classification.InterfaceStability;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.Cell;
30  import org.apache.hadoop.hbase.HRegionInfo;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  
33  // imports we use from yet-to-be-moved regionsever.wal
34  import org.apache.hadoop.hbase.regionserver.wal.CompressionContext;
35  import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
36  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
37  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
38  import org.apache.hadoop.hbase.regionserver.wal.WALCoprocessorHost;
39  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
40  
41  /**
42   * A Write Ahead Log (WAL) provides service for reading, writing waledits. This interface provides
43   * APIs for WAL users (such as RegionServer) to use the WAL (do append, sync, etc).
44   *
45   * Note that some internals, such as log rolling and performance evaluation tools, will use
46   * WAL.equals to determine if they have already seen a given WAL.
47   */
48  @InterfaceAudience.Private
49  @InterfaceStability.Evolving
50  public interface WAL {
51  
52    /**
53     * Registers WALActionsListener
54     */
55    void registerWALActionsListener(final WALActionsListener listener);
56  
57    /**
58     * Unregisters WALActionsListener
59     */
60    boolean unregisterWALActionsListener(final WALActionsListener listener);
61  
62    /**
63     * Roll the log writer. That is, start writing log messages to a new file.
64     *
65     * <p>
66     * The implementation is synchronized in order to make sure there's one rollWriter
67     * running at any given time.
68     *
69     * @return If lots of logs, flush the returned regions so next time through we
70     *         can clean logs. Returns null if nothing to flush. Names are actual
71     *         region names as returned by {@link HRegionInfo#getEncodedName()}
72     */
73    byte[][] rollWriter() throws FailedLogCloseException, IOException;
74  
75    /**
76     * Roll the log writer. That is, start writing log messages to a new file.
77     *
78     * <p>
79     * The implementation is synchronized in order to make sure there's one rollWriter
80     * running at any given time.
81     *
82     * @param force
83     *          If true, force creation of a new writer even if no entries have
84     *          been written to the current writer
85     * @return If lots of logs, flush the returned regions so next time through we
86     *         can clean logs. Returns null if nothing to flush. Names are actual
87     *         region names as returned by {@link HRegionInfo#getEncodedName()}
88     */
89    byte[][] rollWriter(boolean force) throws FailedLogCloseException, IOException;
90  
91    /**
92     * Stop accepting new writes. If we have unsynced writes still in buffer, sync them.
93     * Extant edits are left in place in backing storage to be replayed later.
94     */
95    void shutdown() throws IOException;
96  
97    /**
98     * Caller no longer needs any edits from this WAL. Implementers are free to reclaim
99     * underlying resources after this call; i.e. filesystem based WALs can archive or
100    * delete files.
101    */
102   void close() throws IOException;
103 
104   /**
105    * Append a set of edits to the WAL. The WAL is not flushed/sync'd after this transaction
106    * completes BUT on return this edit must have its region edit/sequence id assigned
107    * else it messes up our unification of mvcc and sequenceid.  On return <code>key</code> will
108    * have the region edit/sequence id filled in.
109    * @param info
110    * @param key Modified by this call; we add to it this edits region edit/sequence id.
111    * @param edits Edits to append. MAY CONTAIN NO EDITS for case where we want to get an edit
112    * sequence id that is after all currently appended edits.
113    * @param htd used to give scope for replication TODO refactor out in favor of table name and info
114    * @param sequenceId A reference to the atomic long the <code>info</code> region is using as
115    * source of its incrementing edits sequence id.  Inside in this call we will increment it and
116    * attach the sequence to the edit we apply the WAL.
117    * @param inMemstore Always true except for case where we are writing a compaction completion
118    * record into the WAL; in this case the entry is just so we can finish an unfinished compaction
119    * -- it is not an edit for memstore.
120    * @param memstoreKVs list of KVs added into memstore
121    * @return Returns a 'transaction id' and <code>key</code> will have the region edit/sequence id
122    * in it.
123    */
124   long append(HTableDescriptor htd, HRegionInfo info, WALKey key, WALEdit edits,
125       AtomicLong sequenceId, boolean inMemstore, List<Cell> memstoreKVs)
126   throws IOException;
127 
128   /**
129    * Sync what we have in the WAL.
130    * @throws IOException
131    */
132   void sync() throws IOException;
133 
134   /**
135    * Sync the WAL if the txId was not already sync'd.
136    * @param txid Transaction id to sync to.
137    * @throws IOException
138    */
139   void sync(long txid) throws IOException;
140 
141   /**
142    * WAL keeps track of the sequence numbers that were not yet flushed from memstores
143    * in order to be able to do cleanup. This method tells WAL that some region is about
144    * to flush memstore.
145    *
146    * <p>We stash the oldest seqNum for the region, and let the the next edit inserted in this
147    * region be recorded in {@link #append(HTableDescriptor, HRegionInfo, WALKey, WALEdit,
148    * AtomicLong, boolean, List)} as new oldest seqnum.
149    * In case of flush being aborted, we put the stashed value back; in case of flush succeeding,
150    * the seqNum of that first edit after start becomes the valid oldest seqNum for this region.
151    *
152    * @return true if the flush can proceed, false in case wal is closing (ususally, when server is
153    * closing) and flush couldn't be started.
154    */
155   boolean startCacheFlush(final byte[] encodedRegionName);
156 
157   /**
158    * Complete the cache flush.
159    * @param encodedRegionName Encoded region name.
160    */
161   void completeCacheFlush(final byte[] encodedRegionName);
162 
163   /**
164    * Abort a cache flush. Call if the flush fails. Note that the only recovery
165    * for an aborted flush currently is a restart of the regionserver so the
166    * snapshot content dropped by the failure gets restored to the memstore.v
167    * @param encodedRegionName Encoded region name.
168    */
169   void abortCacheFlush(byte[] encodedRegionName);
170 
171   /**
172    * @return Coprocessor host.
173    */
174   WALCoprocessorHost getCoprocessorHost();
175 
176 
177   /** Gets the earliest sequence number in the memstore for this particular region.
178    * This can serve as best-effort "recent" WAL number for this region.
179    * @param encodedRegionName The region to get the number for.
180    * @return The number if present, HConstants.NO_SEQNUM if absent.
181    */
182   long getEarliestMemstoreSeqNum(byte[] encodedRegionName);
183 
184   /**
185    * Human readable identifying information about the state of this WAL.
186    * Implementors are encouraged to include information appropriate for debugging.
187    * Consumers are advised not to rely on the details of the returned String; it does
188    * not have a defined structure.
189    */
190   @Override
191   String toString();
192 
193   /**
194    * When outside clients need to consume persisted WALs, they rely on a provided
195    * Reader.
196    */
197   interface Reader extends Closeable {
198     Entry next() throws IOException;
199     Entry next(Entry reuse) throws IOException;
200     void seek(long pos) throws IOException;
201     long getPosition() throws IOException;
202     void reset() throws IOException;
203   }
204 
205   /**
206    * Utility class that lets us keep track of the edit with it's key.
207    */
208   class Entry {
209     private WALEdit edit;
210     private WALKey key;
211 
212     public Entry() {
213       edit = new WALEdit();
214       // we use HLogKey here instead of WALKey directly to support legacy coprocessors.
215       key = new HLogKey();
216     }
217 
218     /**
219      * Constructor for both params
220      *
221      * @param edit log's edit
222      * @param key log's key
223      */
224     public Entry(WALKey key, WALEdit edit) {
225       super();
226       this.key = key;
227       this.edit = edit;
228     }
229 
230     /**
231      * Gets the edit
232      *
233      * @return edit
234      */
235     public WALEdit getEdit() {
236       return edit;
237     }
238 
239     /**
240      * Gets the key
241      *
242      * @return key
243      */
244     public WALKey getKey() {
245       return key;
246     }
247 
248     /**
249      * Set compression context for this entry.
250      *
251      * @param compressionContext
252      *          Compression context
253      */
254     public void setCompressionContext(CompressionContext compressionContext) {
255       edit.setCompressionContext(compressionContext);
256       key.setCompressionContext(compressionContext);
257     }
258 
259     @Override
260     public String toString() {
261       return this.key + "=" + this.edit;
262     }
263 
264   }
265 
266 }