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;
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.protobuf.generated.ErrorHandlingProtos.ForeignExceptionMessage;
26  import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos;
27  import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureState;
28  import org.apache.hadoop.hbase.security.User;
29  import org.apache.hadoop.hbase.util.ByteStringer;
30  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
31  import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
32  import org.apache.hadoop.hbase.util.NonceKey;
33  import org.apache.hadoop.util.StringUtils;
34  
35  /**
36   * Procedure information
37   */
38  @InterfaceAudience.Public
39  @InterfaceStability.Evolving
40  public class ProcedureInfo implements Cloneable {
41    private final long procId;
42    private final String procName;
43    private final String procOwner;
44    private final ProcedureState procState;
45    private final long parentId;
46    private final NonceKey nonceKey;
47    private final ForeignExceptionMessage exception;
48    private final long lastUpdate;
49    private final long startTime;
50    private final byte[] result;
51  
52    private long clientAckTime = -1;
53  
54    @InterfaceAudience.Private
55    public ProcedureInfo(
56        final long procId,
57        final String procName,
58        final String procOwner,
59        final ProcedureState procState,
60        final long parentId,
61        final NonceKey nonceKey,
62        final ForeignExceptionMessage exception,
63        final long lastUpdate,
64        final long startTime,
65        final byte[] result) {
66      this.procId = procId;
67      this.procName = procName;
68      this.procOwner = procOwner;
69      this.procState = procState;
70      this.parentId = parentId;
71      this.nonceKey = nonceKey;
72      this.lastUpdate = lastUpdate;
73      this.startTime = startTime;
74  
75      // If the procedure is completed, we should treat exception and result differently
76      this.exception = exception;
77      this.result = result;
78    }
79  
80    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="CN_IDIOM_NO_SUPER_CALL",
81        justification="Intentional; calling super class clone doesn't make sense here.")
82    public ProcedureInfo clone() {
83      return new ProcedureInfo(procId, procName, procOwner, procState, parentId, nonceKey,
84        exception, lastUpdate, startTime, result);
85    }
86  
87    @Override
88    public String toString() {
89      StringBuilder sb = new StringBuilder();
90      sb.append("Procedure=");
91      sb.append(procName);
92      sb.append(" (id=");
93      sb.append(procId);
94      if (hasParentId()) {
95        sb.append(", parent=");
96        sb.append(parentId);
97      }
98      if (hasOwner()) {
99        sb.append(", owner=");
100       sb.append(procOwner);
101     }
102     sb.append(", state=");
103     sb.append(procState);
104 
105     long now = EnvironmentEdgeManager.currentTime();
106     sb.append(", startTime=");
107     sb.append(StringUtils.formatTime(now - startTime));
108     sb.append(" ago, lastUpdate=");
109     sb.append(StringUtils.formatTime(now - startTime));
110     sb.append(" ago");
111 
112     if (isFailed()) {
113       sb.append(", exception=\"");
114       sb.append(getExceptionMessage());
115       sb.append("\"");
116     }
117     sb.append(")");
118     return sb.toString();
119   }
120 
121   public long getProcId() {
122     return procId;
123   }
124 
125   public String getProcName() {
126     return procName;
127   }
128 
129   private boolean hasOwner() {
130     return procOwner != null;
131   }
132 
133   public String getProcOwner() {
134     return procOwner;
135   }
136 
137   public ProcedureState getProcState() {
138     return procState;
139   }
140 
141   public boolean hasParentId() {
142     return (parentId != -1);
143   }
144 
145   public long getParentId() {
146     return parentId;
147   }
148 
149   public NonceKey getNonceKey() {
150     return nonceKey;
151   }
152 
153   public boolean isFailed() {
154     return exception != null;
155   }
156 
157   public IOException getException() {
158     if (isFailed()) {
159       return ForeignExceptionUtil.toIOException(exception);
160     }
161     return null;
162   }
163 
164   @InterfaceAudience.Private
165   @Deprecated
166   public ForeignExceptionMessage getForeignExceptionMessage() {
167     return exception;
168   }
169 
170   public String getExceptionCause() {
171     assert isFailed();
172     return exception.getGenericException().getClassName();
173   }
174 
175   public String getExceptionMessage() {
176     assert isFailed();
177     return exception.getGenericException().getMessage();
178   }
179 
180   public String getExceptionFullMessage() {
181     assert isFailed();
182     return getExceptionCause() + " - " + getExceptionMessage();
183   }
184 
185   public boolean hasResultData() {
186     return result != null;
187   }
188 
189   public byte[] getResult() {
190     return result;
191   }
192 
193   public long getStartTime() {
194     return startTime;
195   }
196 
197   public long getLastUpdate() {
198     return lastUpdate;
199   }
200 
201   public long executionTime() {
202     return lastUpdate - startTime;
203   }
204 
205   @InterfaceAudience.Private
206   public boolean hasClientAckTime() {
207     return clientAckTime != -1;
208   }
209 
210   @InterfaceAudience.Private
211   public long getClientAckTime() {
212     return clientAckTime;
213   }
214 
215   @InterfaceAudience.Private
216   public void setClientAckTime(final long timestamp) {
217     this.clientAckTime = timestamp;
218   }
219 
220   /**
221    * @return Convert the current {@link ProcedureInfo} into a Protocol Buffers Procedure
222    * instance.
223    */
224   @InterfaceAudience.Private
225   @Deprecated
226   public static ProcedureProtos.Procedure convertToProcedureProto(
227       final ProcedureInfo procInfo) {
228     ProcedureProtos.Procedure.Builder builder = ProcedureProtos.Procedure.newBuilder();
229 
230     builder.setClassName(procInfo.getProcName());
231     builder.setProcId(procInfo.getProcId());
232     builder.setStartTime(procInfo.getStartTime());
233     builder.setState(procInfo.getProcState());
234     builder.setLastUpdate(procInfo.getLastUpdate());
235 
236     if (procInfo.hasParentId()) {
237       builder.setParentId(procInfo.getParentId());
238     }
239 
240     if (procInfo.getProcOwner() != null) {
241        builder.setOwner(procInfo.getProcOwner());
242     }
243 
244     if (procInfo.isFailed()) {
245         builder.setException(procInfo.getForeignExceptionMessage());
246     }
247 
248     if (procInfo.hasResultData()) {
249       builder.setResult(ByteStringer.wrap(procInfo.getResult()));
250     }
251 
252     return builder.build();
253   }
254 
255   /**
256    * Helper to convert the protobuf object.
257    * @return Convert the current Protocol Buffers Procedure to {@link ProcedureInfo}
258    * instance.
259    */
260   @InterfaceAudience.Private
261   @Deprecated
262   public static ProcedureInfo convert(final ProcedureProtos.Procedure procProto) {
263     NonceKey nonceKey = null;
264     if (procProto.getNonce() != HConstants.NO_NONCE) {
265       nonceKey = new NonceKey(procProto.getNonceGroup(), procProto.getNonce());
266     }
267 
268     return new ProcedureInfo(
269       procProto.getProcId(),
270       procProto.getClassName(),
271       procProto.getOwner(),
272       procProto.getState(),
273       procProto.hasParentId() ? procProto.getParentId() : -1,
274       nonceKey,
275       procProto.hasException() ? procProto.getException() : null,
276       procProto.getLastUpdate(),
277       procProto.getStartTime(),
278       procProto.hasResult() ? procProto.getResult().toByteArray() : null);
279   }
280 
281   /**
282   * Check if the user is this procedure's owner
283   * @param owner the owner field of the procedure
284   * @param user the user
285   * @return true if the user is the owner of the procedure,
286   *   false otherwise or the owner is unknown.
287   */
288   @InterfaceAudience.Private
289   public static boolean isProcedureOwner(final ProcedureInfo procInfo, final User user) {
290     if (user == null) {
291       return false;
292     }
293     String procOwner = procInfo.getProcOwner();
294     if (procOwner == null) {
295       return false;
296     }
297     return procOwner.equals(user.getShortName());
298   }
299 }