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 }