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}