001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.wal;
019
020import java.io.Closeable;
021import java.io.IOException;
022import java.util.Map;
023import java.util.Set;
024import org.apache.hadoop.hbase.HConstants;
025import org.apache.hadoop.hbase.client.RegionInfo;
026import org.apache.hadoop.hbase.regionserver.wal.CompressionContext;
027import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
028import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
029import org.apache.hadoop.hbase.regionserver.wal.WALCoprocessorHost;
030import org.apache.hadoop.hbase.replication.regionserver.WALFileLengthProvider;
031import org.apache.yetus.audience.InterfaceAudience;
032import org.apache.yetus.audience.InterfaceStability;
033
034import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
035
036/**
037 * A Write Ahead Log (WAL) provides service for reading, writing waledits. This interface provides
038 * APIs for WAL users (such as RegionServer) to use the WAL (do append, sync, etc).
039 *
040 * Note that some internals, such as log rolling and performance evaluation tools, will use
041 * WAL.equals to determine if they have already seen a given WAL.
042 */
043@InterfaceAudience.Private
044@InterfaceStability.Evolving
045public interface WAL extends Closeable, WALFileLengthProvider {
046
047  /**
048   * Registers WALActionsListener
049   */
050  void registerWALActionsListener(final WALActionsListener listener);
051
052  /**
053   * Unregisters WALActionsListener
054   */
055  boolean unregisterWALActionsListener(final WALActionsListener listener);
056
057  /**
058   * Roll the log writer. That is, start writing log messages to a new file.
059   *
060   * <p>
061   * The implementation is synchronized in order to make sure there's one rollWriter
062   * running at any given time.
063   *
064   * @return If lots of logs, flush the returned regions so next time through we
065   *         can clean logs. Returns null if nothing to flush. Names are actual
066   *         region names as returned by {@link RegionInfo#getEncodedName()}
067   */
068  byte[][] rollWriter() throws FailedLogCloseException, IOException;
069
070  /**
071   * Roll the log writer. That is, start writing log messages to a new file.
072   *
073   * <p>
074   * The implementation is synchronized in order to make sure there's one rollWriter
075   * running at any given time.
076   *
077   * @param force
078   *          If true, force creation of a new writer even if no entries have
079   *          been written to the current writer
080   * @return If lots of logs, flush the returned regions so next time through we
081   *         can clean logs. Returns null if nothing to flush. Names are actual
082   *         region names as returned by {@link RegionInfo#getEncodedName()}
083   */
084  byte[][] rollWriter(boolean force) throws FailedLogCloseException, IOException;
085
086  /**
087   * Stop accepting new writes. If we have unsynced writes still in buffer, sync them.
088   * Extant edits are left in place in backing storage to be replayed later.
089   */
090  void shutdown() throws IOException;
091
092  /**
093   * Caller no longer needs any edits from this WAL. Implementers are free to reclaim
094   * underlying resources after this call; i.e. filesystem based WALs can archive or
095   * delete files.
096   */
097  @Override
098  void close() throws IOException;
099
100  /**
101   * Append a set of edits to the WAL. The WAL is not flushed/sync'd after this transaction
102   * completes BUT on return this edit must have its region edit/sequence id assigned
103   * else it messes up our unification of mvcc and sequenceid.  On return <code>key</code> will
104   * have the region edit/sequence id filled in.
105   * @param info the regioninfo associated with append
106   * @param key Modified by this call; we add to it this edits region edit/sequence id.
107   * @param edits Edits to append. MAY CONTAIN NO EDITS for case where we want to get an edit
108   * sequence id that is after all currently appended edits.
109   * @param inMemstore Always true except for case where we are writing a compaction completion
110   * record into the WAL; in this case the entry is just so we can finish an unfinished compaction
111   * -- it is not an edit for memstore.
112   * @return Returns a 'transaction id' and <code>key</code> will have the region edit/sequence id
113   * in it.
114   */
115  long append(RegionInfo info, WALKeyImpl key, WALEdit edits, boolean inMemstore) throws IOException;
116
117  /**
118   * updates the seuence number of a specific store.
119   * depending on the flag: replaces current seq number if the given seq id is bigger,
120   * or even if it is lower than existing one
121   * @param encodedRegionName
122   * @param familyName
123   * @param sequenceid
124   * @param onlyIfGreater
125   */
126  void updateStore(byte[] encodedRegionName, byte[] familyName, Long sequenceid,
127      boolean onlyIfGreater);
128
129  /**
130   * Sync what we have in the WAL.
131   * @throws IOException
132   */
133  void sync() throws IOException;
134
135  /**
136   * Sync the WAL if the txId was not already sync'd.
137   * @param txid Transaction id to sync to.
138   * @throws IOException
139   */
140  void sync(long txid) throws IOException;
141
142  /**
143   * WAL keeps track of the sequence numbers that are as yet not flushed im memstores
144   * in order to be able to do accounting to figure which WALs can be let go. This method tells WAL
145   * that some region is about to flush. The flush can be the whole region or for a column family
146   * of the region only.
147   *
148   * <p>Currently, it is expected that the update lock is held for the region; i.e. no
149   * concurrent appends while we set up cache flush.
150   * @param families Families to flush. May be a subset of all families in the region.
151   * @return Returns {@link HConstants#NO_SEQNUM} if we are flushing the whole region OR if
152   * we are flushing a subset of all families but there are no edits in those families not
153   * being flushed; in other words, this is effectively same as a flush of all of the region
154   * though we were passed a subset of regions. Otherwise, it returns the sequence id of the
155   * oldest/lowest outstanding edit.
156   * @see #completeCacheFlush(byte[])
157   * @see #abortCacheFlush(byte[])
158   */
159  Long startCacheFlush(final byte[] encodedRegionName, Set<byte[]> families);
160
161  Long startCacheFlush(final byte[] encodedRegionName, Map<byte[], Long> familyToSeq);
162
163  /**
164   * Complete the cache flush.
165   * @param encodedRegionName Encoded region name.
166   * @see #startCacheFlush(byte[], Set)
167   * @see #abortCacheFlush(byte[])
168   */
169  void completeCacheFlush(final byte[] encodedRegionName);
170
171  /**
172   * Abort a cache flush. Call if the flush fails. Note that the only recovery
173   * for an aborted flush currently is a restart of the regionserver so the
174   * snapshot content dropped by the failure gets restored to the memstore.
175   * @param encodedRegionName Encoded region name.
176   */
177  void abortCacheFlush(byte[] encodedRegionName);
178
179  /**
180   * @return Coprocessor host.
181   */
182  WALCoprocessorHost getCoprocessorHost();
183
184  /**
185   * Gets the earliest unflushed sequence id in the memstore for the region.
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.2.0. 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 unflushed sequence id in the memstore for the store.
197   * @param encodedRegionName The region to get the number for.
198   * @param familyName The family to get the number for.
199   * @return The earliest/lowest/oldest sequence id 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 final WALEdit edit;
229    private final WALKeyImpl key;
230
231    public Entry() {
232      this(new WALKeyImpl(), new WALEdit());
233    }
234
235    /**
236     * Constructor for both params
237     *
238     * @param edit log's edit
239     * @param key log's key
240     */
241    public Entry(WALKeyImpl key, WALEdit edit) {
242      this.key = key;
243      this.edit = edit;
244    }
245
246    /**
247     * Gets the edit
248     *
249     * @return edit
250     */
251    public WALEdit getEdit() {
252      return edit;
253    }
254
255    /**
256     * Gets the key
257     *
258     * @return key
259     */
260    public WALKeyImpl getKey() {
261      return key;
262    }
263
264    /**
265     * Set compression context for this entry.
266     *
267     * @param compressionContext
268     *          Compression context
269     */
270    public void setCompressionContext(CompressionContext compressionContext) {
271      key.setCompressionContext(compressionContext);
272    }
273
274    @Override
275    public String toString() {
276      return this.key + "=" + this.edit;
277    }
278  }
279}