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 }