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  
19  package org.apache.hadoop.hbase.master.procedure;
20  
21  import java.io.IOException;
22  
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.classification.InterfaceStability;
25  import org.apache.hadoop.hbase.master.MasterServices;
26  import org.apache.hadoop.hbase.procedure2.Procedure;
27  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
28  import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.UserInformation;
29  import org.apache.hadoop.hbase.security.User;
30  import org.apache.hadoop.hbase.util.NonceKey;
31  import org.apache.hadoop.security.UserGroupInformation;
32  
33  @InterfaceAudience.Private
34  @InterfaceStability.Evolving
35  public final class MasterProcedureUtil {
36  
37    private MasterProcedureUtil() {}
38  
39    public static UserInformation toProtoUserInfo(User user) {
40      UserInformation.Builder userInfoPB = UserInformation.newBuilder();
41      userInfoPB.setEffectiveUser(user.getName());
42      if (user.getUGI().getRealUser() != null) {
43        userInfoPB.setRealUser(user.getUGI().getRealUser().getUserName());
44      }
45      return userInfoPB.build();
46    }
47  
48    public static User toUserInfo(UserInformation userInfoProto) {
49      if (userInfoProto.hasEffectiveUser()) {
50        String effectiveUser = userInfoProto.getEffectiveUser();
51        if (userInfoProto.hasRealUser()) {
52          String realUser = userInfoProto.getRealUser();
53          UserGroupInformation realUserUgi = UserGroupInformation.createRemoteUser(realUser);
54          return User.create(UserGroupInformation.createProxyUser(effectiveUser, realUserUgi));
55        }
56        return User.create(UserGroupInformation.createRemoteUser(effectiveUser));
57      }
58      return null;
59    }
60  
61    /**
62     * Helper Runnable used in conjunction with submitProcedure() to deal with
63     * submitting procs with nonce.
64     * See submitProcedure() for an example.
65     */
66    public static abstract class NonceProcedureRunnable {
67      private final MasterServices master;
68      private final NonceKey nonceKey;
69      private Long procId;
70  
71      public NonceProcedureRunnable(final MasterServices master,
72          final long nonceGroup, final long nonce) {
73        this.master = master;
74        this.nonceKey = getProcedureExecutor().createNonceKey(nonceGroup, nonce);
75      }
76  
77      protected NonceKey getNonceKey() {
78        return nonceKey;
79      }
80  
81      protected MasterServices getMaster() {
82        return master;
83      }
84  
85      protected ProcedureExecutor<MasterProcedureEnv> getProcedureExecutor() {
86        return master.getMasterProcedureExecutor();
87      }
88  
89      protected long getProcId() {
90        return procId != null ? procId.longValue() : -1;
91      }
92  
93      protected long setProcId(final long procId) {
94        this.procId = procId;
95        return procId;
96      }
97  
98      protected abstract void run() throws IOException;
99      protected abstract String getDescription();
100 
101     protected long submitProcedure(final Procedure proc) {
102       assert procId == null : "submitProcedure() was already called, running procId=" + procId;
103       procId = getProcedureExecutor().submitProcedure(proc, nonceKey);
104       return procId;
105     }
106   }
107 
108   /**
109    * Helper used to deal with submitting procs with nonce.
110    * Internally the NonceProcedureRunnable.run() will be called only if no one else
111    * registered the nonce. any Exception thrown by the run() method will be
112    * collected/handled and rethrown.
113    * <code>
114    * long procId = MasterProcedureUtil.submitProcedure(
115    *      new NonceProcedureRunnable(procExec, nonceGroup, nonce) {
116    *   {@literal @}Override
117    *   public void run() {
118    *     cpHost.preOperation();
119    *     submitProcedure(new MyProc());
120    *     cpHost.postOperation();
121    *   }
122    * });
123    * </code>
124    */
125   public static long submitProcedure(final NonceProcedureRunnable runnable) throws IOException {
126     final ProcedureExecutor<MasterProcedureEnv> procExec = runnable.getProcedureExecutor();
127     final long procId = procExec.registerNonce(runnable.getNonceKey());
128     if (procId >= 0) return procId; // someone already registered the nonce
129     try {
130       runnable.run();
131     } catch (IOException e) {
132       procExec.setFailureResultForNonce(runnable.getNonceKey(),
133           runnable.getDescription(),
134           procExec.getEnvironment().getRequestUser(), e);
135       throw e;
136     } finally {
137       procExec.unregisterNonceIfProcedureWasNotSubmitted(runnable.getNonceKey());
138     }
139     return runnable.getProcId();
140   }
141 }