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