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.List;
023import java.util.Map;
024import java.util.Set;
025import org.apache.hadoop.hbase.HConstants;
026import org.apache.hadoop.hbase.client.RegionInfo;
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
034/**
035 * A Write Ahead Log (WAL) provides service for reading, writing waledits. This interface provides
036 * APIs for WAL users (such as RegionServer) to use the WAL (do append, sync, etc). Note that some
037 * internals, such as log rolling and performance evaluation tools, will use WAL.equals to determine
038 * if they have already seen a given WAL.
039 */
040@InterfaceAudience.Private
041@InterfaceStability.Evolving
042public interface WAL extends Closeable, WALFileLengthProvider {
043
044  /**
045   * Registers WALActionsListener
046   */
047  void registerWALActionsListener(final WALActionsListener listener);
048
049  /**
050   * Unregisters WALActionsListener
051   */
052  boolean unregisterWALActionsListener(final WALActionsListener listener);
053
054  /**
055   * Roll the log writer. That is, start writing log messages to a new file.
056   * <p/>
057   * The implementation is synchronized in order to make sure there's one rollWriter running at any
058   * given time.
059   * @return If lots of logs, flush the stores of returned regions so next time through we can clean
060   *         logs. Returns null if nothing to flush. Names are actual region names as returned by
061   *         {@link RegionInfo#getEncodedName()}
062   */
063  Map<byte[], List<byte[]>> rollWriter() throws FailedLogCloseException, IOException;
064
065  /**
066   * Roll the log writer. That is, start writing log messages to a new file.
067   * <p/>
068   * The implementation is synchronized in order to make sure there's one rollWriter running at any
069   * given time. n * If true, force creation of a new writer even if no entries have been written to
070   * the current writer
071   * @return If lots of logs, flush the stores of returned regions so next time through we can clean
072   *         logs. Returns null if nothing to flush. Names are actual region names as returned by
073   *         {@link RegionInfo#getEncodedName()}
074   */
075  Map<byte[], List<byte[]>> rollWriter(boolean force) throws IOException;
076
077  /**
078   * Stop accepting new writes. If we have unsynced writes still in buffer, sync them. Extant edits
079   * are left in place in backing storage to be replayed later.
080   */
081  void shutdown() throws IOException;
082
083  /**
084   * Caller no longer needs any edits from this WAL. Implementers are free to reclaim underlying
085   * resources after this call; i.e. filesystem based WALs can archive or delete files.
086   */
087  @Override
088  void close() throws IOException;
089
090  /**
091   * Append a set of data edits to the WAL. 'Data' here means that the content in the edits will
092   * also have transitioned through the memstore.
093   * <p/>
094   * The WAL is not flushed/sync'd after this transaction completes BUT on return this edit must
095   * have its region edit/sequence id assigned else it messes up our unification of mvcc and
096   * sequenceid. On return <code>key</code> will have the region edit/sequence id filled in.
097   * @param info  the regioninfo associated with append
098   * @param key   Modified by this call; we add to it this edits region edit/sequence id.
099   * @param edits Edits to append. MAY CONTAIN NO EDITS for case where we want to get an edit
100   *              sequence id that is after all currently appended edits.
101   * @return Returns a 'transaction id' and <code>key</code> will have the region edit/sequence id
102   *         in it.
103   * @see #appendMarker(RegionInfo, WALKeyImpl, WALEdit)
104   */
105  long appendData(RegionInfo info, WALKeyImpl key, WALEdit edits) throws IOException;
106
107  /**
108   * Append an operational 'meta' event marker edit to the WAL. A marker meta edit could be a
109   * FlushDescriptor, a compaction marker, or a region event marker; e.g. region open or region
110   * close. The difference between a 'marker' append and a 'data' append as in
111   * {@link #appendData(RegionInfo, WALKeyImpl, WALEdit)}is that a marker will not have transitioned
112   * through the memstore.
113   * <p/>
114   * The WAL is not flushed/sync'd after this transaction completes BUT on return this edit must
115   * have its region edit/sequence id assigned else it messes up our unification of mvcc and
116   * sequenceid. On return <code>key</code> will have the region edit/sequence id filled in.
117   * @param info  the regioninfo associated with append
118   * @param key   Modified by this call; we add to it this edits region edit/sequence id.
119   * @param edits Edits to append. MAY CONTAIN NO EDITS for case where we want to get an edit
120   *              sequence id that is after all currently appended edits.
121   * @return Returns a 'transaction id' and <code>key</code> will have the region edit/sequence id
122   *         in it.
123   * @see #appendData(RegionInfo, WALKeyImpl, WALEdit)
124   */
125  long appendMarker(RegionInfo info, WALKeyImpl key, WALEdit edits) throws IOException;
126
127  /**
128   * updates the seuence number of a specific store. depending on the flag: replaces current seq
129   * number if the given seq id is bigger, or even if it is lower than existing one
130   */
131  void updateStore(byte[] encodedRegionName, byte[] familyName, Long sequenceid,
132    boolean onlyIfGreater);
133
134  /**
135   * Sync what we have in the WAL.
136   */
137  void sync() throws IOException;
138
139  /**
140   * Sync the WAL if the txId was not already sync'd.
141   * @param txid Transaction id to sync to.
142   */
143  void sync(long txid) throws IOException;
144
145  /**
146   * @param forceSync Flag to force sync rather than flushing to the buffer. Example - Hadoop hflush
147   *                  vs hsync.
148   */
149  default void sync(boolean forceSync) throws IOException {
150    sync();
151  }
152
153  /**
154   * @param txid      Transaction id to sync to.
155   * @param forceSync Flag to force sync rather than flushing to the buffer. Example - Hadoop hflush
156   *                  vs hsync.
157   */
158  default void sync(long txid, boolean forceSync) throws IOException {
159    sync(txid);
160  }
161
162  /**
163   * WAL keeps track of the sequence numbers that are as yet not flushed im memstores in order to be
164   * able to do accounting to figure which WALs can be let go. This method tells WAL that some
165   * region is about to flush. The flush can be the whole region or for a column family of the
166   * region only.
167   * <p>
168   * Currently, it is expected that the update lock is held for the region; i.e. no concurrent
169   * appends while we set up cache flush.
170   * @param families Families to flush. May be a subset of all families in the region.
171   * @return Returns {@link HConstants#NO_SEQNUM} if we are flushing the whole region OR if we are
172   *         flushing a subset of all families but there are no edits in those families not being
173   *         flushed; in other words, this is effectively same as a flush of all of the region
174   *         though we were passed a subset of regions. Otherwise, it returns the sequence id of the
175   *         oldest/lowest outstanding edit.
176   * @see #completeCacheFlush(byte[], long)
177   * @see #abortCacheFlush(byte[])
178   */
179  Long startCacheFlush(final byte[] encodedRegionName, Set<byte[]> families);
180
181  Long startCacheFlush(final byte[] encodedRegionName, Map<byte[], Long> familyToSeq);
182
183  /**
184   * Complete the cache flush.
185   * @param encodedRegionName Encoded region name.
186   * @param maxFlushedSeqId   The maxFlushedSeqId for this flush. There is no edit in memory that is
187   *                          less that this sequence id.
188   * @see #startCacheFlush(byte[], Set)
189   * @see #abortCacheFlush(byte[])
190   */
191  void completeCacheFlush(final byte[] encodedRegionName, long maxFlushedSeqId);
192
193  /**
194   * Abort a cache flush. Call if the flush fails. Note that the only recovery for an aborted flush
195   * currently is a restart of the regionserver so the snapshot content dropped by the failure gets
196   * restored to the memstore.
197   * @param encodedRegionName Encoded region name.
198   */
199  void abortCacheFlush(byte[] encodedRegionName);
200
201  /**
202   * @return Coprocessor host.
203   */
204  WALCoprocessorHost getCoprocessorHost();
205
206  /**
207   * Gets the earliest unflushed sequence id in the memstore for the region.
208   * @param encodedRegionName The region to get the number for.
209   * @return The earliest/lowest/oldest sequence id if present, HConstants.NO_SEQNUM if absent.
210   * @deprecated Since version 1.2.0. Removing because not used and exposes subtle internal
211   *             workings. Use {@link #getEarliestMemStoreSeqNum(byte[], byte[])}
212   */
213  @Deprecated
214  long getEarliestMemStoreSeqNum(byte[] encodedRegionName);
215
216  /**
217   * Gets the earliest unflushed sequence id in the memstore for the store.
218   * @param encodedRegionName The region to get the number for.
219   * @param familyName        The family to get the number for.
220   * @return The earliest/lowest/oldest sequence id if present, HConstants.NO_SEQNUM if absent.
221   */
222  long getEarliestMemStoreSeqNum(byte[] encodedRegionName, byte[] familyName);
223
224  /**
225   * Human readable identifying information about the state of this WAL. Implementors are encouraged
226   * to include information appropriate for debugging. Consumers are advised not to rely on the
227   * details of the returned String; it does not have a defined structure.
228   */
229  @Override
230  String toString();
231
232  /**
233   * When outside clients need to consume persisted WALs, they rely on a provided Reader.
234   */
235  interface Reader extends Closeable {
236    Entry next() throws IOException;
237
238    Entry next(Entry reuse) throws IOException;
239
240    void seek(long pos) throws IOException;
241
242    long getPosition() throws IOException;
243
244    void reset() throws IOException;
245  }
246
247  /**
248   * Utility class that lets us keep track of the edit with it's key.
249   */
250  class Entry {
251    private final WALEdit edit;
252    private final WALKeyImpl key;
253
254    public Entry() {
255      this(new WALKeyImpl(), new WALEdit());
256    }
257
258    /**
259     * Constructor for both params
260     * @param edit log's edit
261     * @param key  log's key
262     */
263    public Entry(WALKeyImpl key, WALEdit edit) {
264      this.key = key;
265      this.edit = edit;
266    }
267
268    /**
269     * Gets the edit n
270     */
271    public WALEdit getEdit() {
272      return edit;
273    }
274
275    /**
276     * Gets the key n
277     */
278    public WALKeyImpl getKey() {
279      return key;
280    }
281
282    @Override
283    public String toString() {
284      return this.key + "=" + this.edit;
285    }
286  }
287}