1 /**
2 * Copyright The Apache Software Foundation
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with this
6 * work for additional information regarding copyright ownership. The ASF
7 * licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the License.
9 * 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, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.hadoop.hbase.regionserver;
20
21 import java.io.IOException;
22 import java.util.List;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.classification.InterfaceStability;
26 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
27 import org.apache.hadoop.hbase.HRegionInfo;
28 import org.apache.hadoop.hbase.Server;
29 import org.apache.hadoop.hbase.security.User;
30
31 /**
32 * Executes region merge as a "transaction". It is similar with
33 * SplitTransaction. Call {@link #prepare(RegionServerServices)} to setup the
34 * transaction, {@link #execute(Server, RegionServerServices)} to run the
35 * transaction and {@link #rollback(Server, RegionServerServices)} to cleanup if
36 * execute fails.
37 *
38 * <p>Here is an example of how you would use this interface:
39 * <pre>
40 * RegionMergeTransactionFactory factory = new RegionMergeTransactionFactory(conf);
41 * RegionMergeTransaction mt = factory.create(parent, midKey)
42 * .registerTransactionListener(new TransactionListener() {
43 * public void transition(RegionMergeTransaction transaction,
44 * RegionMergeTransactionPhase from, RegionMergeTransactionPhase to) throws IOException {
45 * // ...
46 * }
47 * public void rollback(RegionMergeTransaction transaction,
48 * RegionMergeTransactionPhase from, RegionMergeTransactionPhase to) {
49 * // ...
50 * }
51 * });
52 * if (!mt.prepare()) return;
53 * try {
54 * mt.execute(server, services);
55 * } catch (IOException ioe) {
56 * try {
57 * mt.rollback(server, services);
58 * return;
59 * } catch (RuntimeException e) {
60 * // abort the server
61 * }
62 * }
63 * </Pre>
64 * <p>A merge transaction is not thread safe. Callers must ensure a split is run by
65 * one thread only.
66 */
67 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
68 @InterfaceStability.Evolving
69 public interface RegionMergeTransaction {
70 /**
71 * Each enum is a step in the merge transaction.
72 */
73 enum RegionMergeTransactionPhase {
74 STARTED,
75 /**
76 * Prepared
77 */
78 PREPARED,
79 /**
80 * Set region as in transition, set it into MERGING state.
81 */
82 SET_MERGING,
83 /**
84 * We created the temporary merge data directory.
85 */
86 CREATED_MERGE_DIR,
87 /**
88 * Closed the merging region A.
89 */
90 CLOSED_REGION_A,
91 /**
92 * The merging region A has been taken out of the server's online regions list.
93 */
94 OFFLINED_REGION_A,
95 /**
96 * Closed the merging region B.
97 */
98 CLOSED_REGION_B,
99 /**
100 * The merging region B has been taken out of the server's online regions list.
101 */
102 OFFLINED_REGION_B,
103 /**
104 * Started in on creation of the merged region.
105 */
106 STARTED_MERGED_REGION_CREATION,
107 /**
108 * Point of no return. If we got here, then transaction is not recoverable
109 * other than by crashing out the regionserver.
110 */
111 PONR,
112 /**
113 * Completed
114 */
115 COMPLETED
116 }
117
118 /**
119 * Split transaction journal entry
120 */
121 public interface JournalEntry {
122
123 /** @return the completed phase marked by this journal entry */
124 RegionMergeTransactionPhase getPhase();
125
126 /** @return the time of phase completion */
127 long getTimeStamp();
128 }
129
130 /**
131 * Split transaction listener
132 */
133 public interface TransactionListener {
134
135 /**
136 * Invoked when transitioning forward from one transaction phase to another
137 * @param transaction the transaction
138 * @param from the current phase
139 * @param to the next phase
140 * @throws IOException listener can throw this to abort
141 */
142 void transition(RegionMergeTransaction transaction, RegionMergeTransactionPhase from,
143 RegionMergeTransactionPhase to) throws IOException;
144
145 /**
146 * Invoked when rolling back a transaction from one transaction phase to the
147 * previous
148 * @param transaction the transaction
149 * @param from the current phase
150 * @param to the previous phase
151 */
152 void rollback(RegionMergeTransaction transaction, RegionMergeTransactionPhase from,
153 RegionMergeTransactionPhase to);
154 }
155
156 /**
157 * Check merge inputs and prepare the transaction.
158 * @param services
159 * @return <code>true</code> if the regions are mergeable else
160 * <code>false</code> if they are not (e.g. its already closed, etc.).
161 * @throws IOException
162 */
163 boolean prepare(RegionServerServices services) throws IOException;
164
165 /**
166 * Run the transaction.
167 * @param server Hosting server instance. Can be null when testing
168 * @param services Used to online/offline regions.
169 * @throws IOException If thrown, transaction failed. Call
170 * {@link #rollback(Server, RegionServerServices)}
171 * @return merged region
172 * @throws IOException
173 * @see #rollback(Server, RegionServerServices)
174 * @deprecated use #execute(Server, RegionServerServices, User)
175 */
176 @Deprecated
177 Region execute(Server server, RegionServerServices services) throws IOException;
178
179 /**
180 * Run the transaction.
181 * @param server Hosting server instance. Can be null when testing
182 * @param services Used to online/offline regions.
183 * @param user
184 * @throws IOException If thrown, transaction failed. Call
185 * {@link #rollback(Server, RegionServerServices)}
186 * @return merged region
187 * @throws IOException
188 * @see #rollback(Server, RegionServerServices, User)
189 */
190 Region execute(Server server, RegionServerServices services, User user) throws IOException;
191
192 /**
193 * Roll back a failed transaction
194 * @param server Hosting server instance (May be null when testing).
195 * @param services Services of regionserver, used to online regions.
196 * @throws IOException If thrown, rollback failed. Take drastic action.
197 * @return True if we successfully rolled back, false if we got to the point
198 * of no return and so now need to abort the server to minimize
199 * damage.
200 * @deprecated use #rollback(Server, RegionServerServices, User)
201 */
202 @Deprecated
203 boolean rollback(Server server, RegionServerServices services) throws IOException;
204
205 /**
206 * Roll back a failed transaction
207 * @param server Hosting server instance (May be null when testing).
208 * @param services Services of regionserver, used to online regions.
209 * @param user
210 * @throws IOException If thrown, rollback failed. Take drastic action.
211 * @return True if we successfully rolled back, false if we got to the point
212 * of no return and so now need to abort the server to minimize
213 * damage.
214 */
215 boolean rollback(Server server, RegionServerServices services, User user) throws IOException;
216
217 /**
218 * Register a listener for transaction preparation, execution, and possibly
219 * rollback phases.
220 * <p>A listener can abort a transaction by throwing an exception.
221 * @param listener the listener
222 * @return 'this' for chaining
223 */
224 RegionMergeTransaction registerTransactionListener(TransactionListener listener);
225
226 /** @return merged region info */
227 HRegionInfo getMergedRegionInfo();
228
229 /**
230 * Get the journal for the transaction.
231 * <p>Journal entries are an opaque type represented as JournalEntry. They can
232 * also provide useful debugging information via their toString method.
233 * @return the transaction journal
234 */
235 List<JournalEntry> getJournal();
236
237 /**
238 * Get the Server running the transaction or rollback
239 * @return server instance
240 */
241 Server getServer();
242
243 /**
244 * Get the RegonServerServices of the server running the transaction or rollback
245 * @return region server services
246 */
247 RegionServerServices getRegionServerServices();
248 }