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.regionserver.wal; 21 22 import java.io.DataInput; 23 import java.io.DataOutput; 24 import java.io.IOException; 25 import java.util.UUID; 26 import java.util.regex.Pattern; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.apache.hadoop.classification.InterfaceAudience; 31 import org.apache.hadoop.conf.Configuration; 32 import org.apache.hadoop.fs.FSDataInputStream; 33 import org.apache.hadoop.fs.FileSystem; 34 import org.apache.hadoop.fs.Path; 35 import org.apache.hadoop.hbase.TableName; 36 import org.apache.hadoop.hbase.HRegionInfo; 37 import org.apache.hadoop.hbase.HTableDescriptor; 38 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.WALTrailer; 39 import org.apache.hadoop.io.Writable; 40 41 42 @InterfaceAudience.Private 43 public interface HLog { 44 Log LOG = LogFactory.getLog(HLog.class); 45 46 /** File Extension used while splitting an HLog into regions (HBASE-2312) */ 47 String SPLITTING_EXT = "-splitting"; 48 boolean SPLIT_SKIP_ERRORS_DEFAULT = false; 49 /** The META region's HLog filename extension */ 50 String META_HLOG_FILE_EXTN = ".meta"; 51 52 /** 53 * Configuration name of HLog Trailer's warning size. If a waltrailer's size is greater than the 54 * configured size, a warning is logged. This is used with Protobuf reader/writer. 55 */ 56 String WAL_TRAILER_WARN_SIZE = 57 "hbase.regionserver.waltrailer.warn.size"; 58 int DEFAULT_WAL_TRAILER_WARN_SIZE = 1024*1024; // 1MB 59 60 Pattern EDITFILES_NAME_PATTERN = Pattern.compile("-?[0-9]+"); 61 String RECOVERED_LOG_TMPFILE_SUFFIX = ".temp"; 62 63 interface Reader { 64 65 /** 66 * @param fs File system. 67 * @param path Path. 68 * @param c Config. 69 * @param s Input stream that may have been pre-opened by the caller; may be null. 70 */ 71 void init(FileSystem fs, Path path, Configuration c, FSDataInputStream s) throws IOException; 72 73 void close() throws IOException; 74 75 Entry next() throws IOException; 76 77 Entry next(Entry reuse) throws IOException; 78 79 void seek(long pos) throws IOException; 80 81 long getPosition() throws IOException; 82 void reset() throws IOException; 83 84 /** 85 * @return the WALTrailer of the current HLog. It may be null in case of legacy or corrupt WAL 86 * files. 87 */ 88 WALTrailer getWALTrailer(); 89 } 90 91 interface Writer { 92 void init(FileSystem fs, Path path, Configuration c) throws IOException; 93 94 void close() throws IOException; 95 96 void sync() throws IOException; 97 98 void append(Entry entry) throws IOException; 99 100 long getLength() throws IOException; 101 102 /** 103 * Sets HLog's WALTrailer. This trailer is appended at the end of WAL on closing. 104 * @param walTrailer trailer to append to WAL. 105 */ 106 void setWALTrailer(WALTrailer walTrailer); 107 } 108 109 /** 110 * Utility class that lets us keep track of the edit with it's key Only used 111 * when splitting logs 112 */ 113 class Entry implements Writable { 114 private WALEdit edit; 115 private HLogKey key; 116 117 public Entry() { 118 edit = new WALEdit(); 119 key = new HLogKey(); 120 } 121 122 /** 123 * Constructor for both params 124 * 125 * @param edit 126 * log's edit 127 * @param key 128 * log's key 129 */ 130 public Entry(HLogKey key, WALEdit edit) { 131 super(); 132 this.key = key; 133 this.edit = edit; 134 } 135 136 /** 137 * Gets the edit 138 * 139 * @return edit 140 */ 141 public WALEdit getEdit() { 142 return edit; 143 } 144 145 /** 146 * Gets the key 147 * 148 * @return key 149 */ 150 public HLogKey getKey() { 151 return key; 152 } 153 154 /** 155 * Set compression context for this entry. 156 * 157 * @param compressionContext 158 * Compression context 159 */ 160 public void setCompressionContext(CompressionContext compressionContext) { 161 edit.setCompressionContext(compressionContext); 162 key.setCompressionContext(compressionContext); 163 } 164 165 @Override 166 public String toString() { 167 return this.key + "=" + this.edit; 168 } 169 170 @Override 171 public void write(DataOutput dataOutput) throws IOException { 172 this.key.write(dataOutput); 173 this.edit.write(dataOutput); 174 } 175 176 @Override 177 public void readFields(DataInput dataInput) throws IOException { 178 this.key.readFields(dataInput); 179 this.edit.readFields(dataInput); 180 } 181 } 182 183 /** 184 * registers WALActionsListener 185 * 186 * @param listener 187 */ 188 void registerWALActionsListener(final WALActionsListener listener); 189 190 /** 191 * unregisters WALActionsListener 192 * 193 * @param listener 194 */ 195 boolean unregisterWALActionsListener(final WALActionsListener listener); 196 197 /** 198 * @return Current state of the monotonically increasing file id. 199 */ 200 long getFilenum(); 201 202 /** 203 * Called by HRegionServer when it opens a new region to ensure that log 204 * sequence numbers are always greater than the latest sequence number of the 205 * region being brought on-line. 206 * 207 * @param newvalue 208 * We'll set log edit/sequence number to this value if it is greater 209 * than the current value. 210 */ 211 void setSequenceNumber(final long newvalue); 212 213 /** 214 * @return log sequence number 215 */ 216 long getSequenceNumber(); 217 218 /** 219 * Roll the log writer. That is, start writing log messages to a new file. 220 * 221 * <p> 222 * The implementation is synchronized in order to make sure there's one rollWriter 223 * running at any given time. 224 * 225 * @return If lots of logs, flush the returned regions so next time through we 226 * can clean logs. Returns null if nothing to flush. Names are actual 227 * region names as returned by {@link HRegionInfo#getEncodedName()} 228 * @throws org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException 229 * @throws IOException 230 */ 231 byte[][] rollWriter() throws FailedLogCloseException, IOException; 232 233 /** 234 * Roll the log writer. That is, start writing log messages to a new file. 235 * 236 * <p> 237 * The implementation is synchronized in order to make sure there's one rollWriter 238 * running at any given time. 239 * 240 * @param force 241 * If true, force creation of a new writer even if no entries have 242 * been written to the current writer 243 * @return If lots of logs, flush the returned regions so next time through we 244 * can clean logs. Returns null if nothing to flush. Names are actual 245 * region names as returned by {@link HRegionInfo#getEncodedName()} 246 * @throws org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException 247 * @throws IOException 248 */ 249 byte[][] rollWriter(boolean force) throws FailedLogCloseException, 250 IOException; 251 252 /** 253 * Shut down the log. 254 * 255 * @throws IOException 256 */ 257 void close() throws IOException; 258 259 /** 260 * Shut down the log and delete the log directory 261 * 262 * @throws IOException 263 */ 264 void closeAndDelete() throws IOException; 265 266 /** 267 * Same as {@link #appendNoSync(HRegionInfo, TableName, WALEdit, UUID, long, HTableDescriptor)}, 268 * except it causes a sync on the log 269 */ 270 public void append(HRegionInfo info, TableName tableName, WALEdit edits, 271 final long now, HTableDescriptor htd) throws IOException; 272 273 /** 274 * Append a set of edits to the log. Log edits are keyed by (encoded) 275 * regionName, rowname, and log-sequence-id. The HLog is flushed after this 276 * transaction is written to the log. 277 * @param info 278 * @param tableName 279 * @param edits 280 * @param now 281 * @param htd 282 * @param isInMemstore Whether the record is in memstore. False for system records. 283 */ 284 public void append(HRegionInfo info, TableName tableName, WALEdit edits, 285 final long now, HTableDescriptor htd, boolean isInMemstore) throws IOException; 286 287 /** 288 * Append a set of edits to the log. Log edits are keyed by (encoded) 289 * regionName, rowname, and log-sequence-id. The HLog is not flushed after 290 * this transaction is written to the log. 291 * 292 * @param info 293 * @param tableName 294 * @param edits 295 * @param clusterId 296 * The originating clusterId for this edit (for replication) 297 * @param now 298 * @param htd 299 * @return txid of this transaction 300 * @throws IOException 301 */ 302 public long appendNoSync(HRegionInfo info, TableName tableName, WALEdit edits, 303 UUID clusterId, final long now, HTableDescriptor htd) throws IOException; 304 305 void hsync() throws IOException; 306 307 void hflush() throws IOException; 308 309 void sync() throws IOException; 310 311 void sync(long txid) throws IOException; 312 313 /** 314 * Obtain a log sequence number. 315 */ 316 long obtainSeqNum(); 317 318 /** 319 * WAL keeps track of the sequence numbers that were not yet flushed from memstores 320 * in order to be able to do cleanup. This method tells WAL that some region is about 321 * to flush memstore. 322 * 323 * We stash the oldest seqNum for the region, and let the the next edit inserted in this 324 * region be recorded in {@link #append(HRegionInfo, TableName, WALEdit, long, HTableDescriptor)} 325 * as new oldest seqnum. In case of flush being aborted, we put the stashed value back; 326 * in case of flush succeeding, the seqNum of that first edit after start becomes the 327 * valid oldest seqNum for this region. 328 * 329 * @return current seqNum, to pass on to flushers (who will put it into the metadata of 330 * the resulting file as an upper-bound seqNum for that file), or NULL if flush 331 * should not be started. 332 */ 333 Long startCacheFlush(final byte[] encodedRegionName); 334 335 /** 336 * Complete the cache flush. 337 * @param encodedRegionName Encoded region name. 338 */ 339 void completeCacheFlush(final byte[] encodedRegionName); 340 341 /** 342 * Abort a cache flush. Call if the flush fails. Note that the only recovery 343 * for an aborted flush currently is a restart of the regionserver so the 344 * snapshot content dropped by the failure gets restored to the memstore.v 345 * @param encodedRegionName Encoded region name. 346 */ 347 void abortCacheFlush(byte[] encodedRegionName); 348 349 /** 350 * @return Coprocessor host. 351 */ 352 WALCoprocessorHost getCoprocessorHost(); 353 354 /** 355 * Get LowReplication-Roller status 356 * 357 * @return lowReplicationRollEnabled 358 */ 359 boolean isLowReplicationRollEnabled(); 360 361 /** Gets the earliest sequence number in the memstore for this particular region. 362 * This can serve as best-effort "recent" WAL number for this region. 363 * @param encodedRegionName The region to get the number for. 364 * @return The number if present, HConstants.NO_SEQNUM if absent. 365 */ 366 long getEarliestMemstoreSeqNum(byte[] encodedRegionName); 367 }