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.Set;
26 import java.util.concurrent.atomic.AtomicLong;
27
28 import org.apache.hadoop.hbase.Cell;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.HRegionInfo;
31 import org.apache.hadoop.hbase.HTableDescriptor;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.classification.InterfaceStability;
34 // imports we use from yet-to-be-moved regionsever.wal
35 import org.apache.hadoop.hbase.regionserver.wal.CompressionContext;
36 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
37 import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
38 import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
39 import org.apache.hadoop.hbase.regionserver.wal.WALCoprocessorHost;
40 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
41
42 import com.google.common.annotations.VisibleForTesting;
43
44 /**
45 * A Write Ahead Log (WAL) provides service for reading, writing waledits. This interface provides
46 * APIs for WAL users (such as RegionServer) to use the WAL (do append, sync, etc).
47 *
48 * Note that some internals, such as log rolling and performance evaluation tools, will use
49 * WAL.equals to determine if they have already seen a given WAL.
50 */
51 @InterfaceAudience.Private
52 @InterfaceStability.Evolving
53 public interface WAL extends Closeable {
54
55 /**
56 * Registers WALActionsListener
57 */
58 void registerWALActionsListener(final WALActionsListener listener);
59
60 /**
61 * Unregisters WALActionsListener
62 */
63 boolean unregisterWALActionsListener(final WALActionsListener listener);
64
65 /**
66 * Roll the log writer. That is, start writing log messages to a new file.
67 *
68 * <p>
69 * The implementation is synchronized in order to make sure there's one rollWriter
70 * running at any given time.
71 *
72 * @return If lots of logs, flush the returned regions so next time through we
73 * can clean logs. Returns null if nothing to flush. Names are actual
74 * region names as returned by {@link HRegionInfo#getEncodedName()}
75 */
76 byte[][] rollWriter() throws FailedLogCloseException, IOException;
77
78 /**
79 * Roll the log writer. That is, start writing log messages to a new file.
80 *
81 * <p>
82 * The implementation is synchronized in order to make sure there's one rollWriter
83 * running at any given time.
84 *
85 * @param force
86 * If true, force creation of a new writer even if no entries have
87 * been written to the current writer
88 * @return If lots of logs, flush the returned regions so next time through we
89 * can clean logs. Returns null if nothing to flush. Names are actual
90 * region names as returned by {@link HRegionInfo#getEncodedName()}
91 */
92 byte[][] rollWriter(boolean force) throws FailedLogCloseException, IOException;
93
94 /**
95 * Stop accepting new writes. If we have unsynced writes still in buffer, sync them.
96 * Extant edits are left in place in backing storage to be replayed later.
97 */
98 void shutdown() throws IOException;
99
100 /**
101 * Caller no longer needs any edits from this WAL. Implementers are free to reclaim
102 * underlying resources after this call; i.e. filesystem based WALs can archive or
103 * delete files.
104 */
105 void close() throws IOException;
106
107 /**
108 * Append a set of edits to the WAL. The WAL is not flushed/sync'd after this transaction
109 * completes BUT on return this edit must have its region edit/sequence id assigned
110 * else it messes up our unification of mvcc and sequenceid. On return <code>key</code> will
111 * have the region edit/sequence id filled in.
112 * @param info
113 * @param key Modified by this call; we add to it this edits region edit/sequence id.
114 * @param edits Edits to append. MAY CONTAIN NO EDITS for case where we want to get an edit
115 * sequence id that is after all currently appended edits.
116 * @param htd used to give scope for replication TODO refactor out in favor of table name and info
117 * @param sequenceId A reference to the atomic long the <code>info</code> region is using as
118 * source of its incrementing edits sequence id. Inside in this call we will increment it and
119 * attach the sequence to the edit we apply the WAL.
120 * @param inMemstore Always true except for case where we are writing a compaction completion
121 * record into the WAL; in this case the entry is just so we can finish an unfinished compaction
122 * -- it is not an edit for memstore.
123 * @param memstoreKVs list of KVs added into memstore
124 * @return Returns a 'transaction id' and <code>key</code> will have the region edit/sequence id
125 * in it.
126 */
127 long append(HTableDescriptor htd, HRegionInfo info, WALKey key, WALEdit edits,
128 AtomicLong sequenceId, boolean inMemstore, List<Cell> memstoreKVs)
129 throws IOException;
130
131 /**
132 * Sync what we have in the WAL.
133 * @throws IOException
134 */
135 void sync() throws IOException;
136
137 /**
138 * Sync the WAL if the txId was not already sync'd.
139 * @param txid Transaction id to sync to.
140 * @throws IOException
141 */
142 void sync(long txid) throws IOException;
143
144 /**
145 * WAL keeps track of the sequence numbers that are as yet not flushed im memstores
146 * in order to be able to do accounting to figure which WALs can be let go. This method tells WAL
147 * that some region is about to flush. The flush can be the whole region or for a column family
148 * of the region only.
149 *
150 * <p>Currently, it is expected that the update lock is held for the region; i.e. no
151 * concurrent appends while we set up cache flush.
152 * @param families Families to flush. May be a subset of all families in the region.
153 * @return Returns {@link HConstants#NO_SEQNUM} if we are flushing the whole region OR if
154 * we are flushing a subset of all families but there are no edits in those families not
155 * being flushed; in other words, this is effectively same as a flush of all of the region
156 * though we were passed a subset of regions. Otherwise, it returns the sequence id of the
157 * oldest/lowest outstanding edit.
158 * @see #completeCacheFlush(byte[])
159 * @see #abortCacheFlush(byte[])
160 */
161 Long startCacheFlush(final byte[] encodedRegionName, Set<byte[]> flushedFamilyNames);
162
163 /**
164 * Complete the cache flush.
165 * @param encodedRegionName Encoded region name.
166 */
167 void completeCacheFlush(final byte[] encodedRegionName);
168
169 /**
170 * Abort a cache flush. Call if the flush fails. Note that the only recovery
171 * for an aborted flush currently is a restart of the regionserver so the
172 * snapshot content dropped by the failure gets restored to the memstore.v
173 * @param encodedRegionName Encoded region name.
174 */
175 void abortCacheFlush(byte[] encodedRegionName);
176
177 /**
178 * @return Coprocessor host.
179 */
180 WALCoprocessorHost getCoprocessorHost();
181
182
183 /**
184 * Gets the earliest unflushed sequence id in the memstore for the region.
185
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.1.1. 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 sequence number in the memstore for this particular region and store.
197 * @param encodedRegionName The region to get the number for.
198 * @param familyName The family to get the number for.
199 * @return The number 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 WALEdit edit;
229 private WALKey key;
230
231 public Entry() {
232 edit = new WALEdit();
233 // we use HLogKey here instead of WALKey directly to support legacy coprocessors.
234 key = new HLogKey();
235 }
236
237 /**
238 * Constructor for both params
239 *
240 * @param edit log's edit
241 * @param key log's key
242 */
243 public Entry(WALKey key, WALEdit edit) {
244 super();
245 this.key = key;
246 this.edit = edit;
247 }
248
249 /**
250 * Gets the edit
251 *
252 * @return edit
253 */
254 public WALEdit getEdit() {
255 return edit;
256 }
257
258 /**
259 * Gets the key
260 *
261 * @return key
262 */
263 public WALKey getKey() {
264 return key;
265 }
266
267 /**
268 * Set compression context for this entry.
269 *
270 * @param compressionContext
271 * Compression context
272 */
273 public void setCompressionContext(CompressionContext compressionContext) {
274 edit.setCompressionContext(compressionContext);
275 key.setCompressionContext(compressionContext);
276 }
277
278 @Override
279 public String toString() {
280 return this.key + "=" + this.edit;
281 }
282
283 }
284
285 }