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