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