View Javadoc

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 }