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    @Override
83    public ProcedureInfo clone() {
84      return new ProcedureInfo(procId, procName, procOwner, procState, parentId, nonceKey,
85        exception, lastUpdate, startTime, result);
86    }
87  
88    @Override
89    public String toString() {
90      StringBuilder sb = new StringBuilder();
91      sb.append("Procedure=");
92      sb.append(procName);
93      sb.append(" (id=");
94      sb.append(procId);
95      if (hasParentId()) {
96        sb.append(", parent=");
97        sb.append(parentId);
98      }
99      if (hasOwner()) {
100       sb.append(", owner=");
101       sb.append(procOwner);
102     }
103     sb.append(", state=");
104     sb.append(procState);
105 
106     long now = EnvironmentEdgeManager.currentTime();
107     sb.append(", startTime=");
108     sb.append(StringUtils.formatTime(now - startTime));
109     sb.append(" ago, lastUpdate=");
110     sb.append(StringUtils.formatTime(now - startTime));
111     sb.append(" ago");
112 
113     if (isFailed()) {
114       sb.append(", exception=\"");
115       sb.append(getExceptionMessage());
116       sb.append("\"");
117     }
118     sb.append(")");
119     return sb.toString();
120   }
121 
122   public long getProcId() {
123     return procId;
124   }
125 
126   public String getProcName() {
127     return procName;
128   }
129 
130   private boolean hasOwner() {
131     return procOwner != null;
132   }
133 
134   public String getProcOwner() {
135     return procOwner;
136   }
137 
138   public ProcedureState getProcState() {
139     return procState;
140   }
141 
142   public boolean hasParentId() {
143     return (parentId != -1);
144   }
145 
146   public long getParentId() {
147     return parentId;
148   }
149 
150   public NonceKey getNonceKey() {
151     return nonceKey;
152   }
153 
154   public boolean isFailed() {
155     return exception != null;
156   }
157 
158   public IOException getException() {
159     if (isFailed()) {
160       return ForeignExceptionUtil.toIOException(exception);
161     }
162     return null;
163   }
164 
165   @InterfaceAudience.Private
166   @Deprecated
167   public ForeignExceptionMessage getForeignExceptionMessage() {
168     return exception;
169   }
170 
171   public String getExceptionCause() {
172     assert isFailed();
173     return exception.getGenericException().getClassName();
174   }
175 
176   public String getExceptionMessage() {
177     assert isFailed();
178     return exception.getGenericException().getMessage();
179   }
180 
181   public String getExceptionFullMessage() {
182     assert isFailed();
183     return getExceptionCause() + " - " + getExceptionMessage();
184   }
185 
186   public boolean hasResultData() {
187     return result != null;
188   }
189 
190   public byte[] getResult() {
191     return result;
192   }
193 
194   public long getStartTime() {
195     return startTime;
196   }
197 
198   public long getLastUpdate() {
199     return lastUpdate;
200   }
201 
202   public long executionTime() {
203     return lastUpdate - startTime;
204   }
205 
206   @InterfaceAudience.Private
207   public boolean hasClientAckTime() {
208     return clientAckTime != -1;
209   }
210 
211   @InterfaceAudience.Private
212   public long getClientAckTime() {
213     return clientAckTime;
214   }
215 
216   @InterfaceAudience.Private
217   public void setClientAckTime(final long timestamp) {
218     this.clientAckTime = timestamp;
219   }
220 
221   /**
222    * @return Convert the current {@link ProcedureInfo} into a Protocol Buffers Procedure
223    * instance.
224    */
225   @InterfaceAudience.Private
226   @Deprecated
227   public static ProcedureProtos.Procedure convertToProcedureProto(
228       final ProcedureInfo procInfo) {
229     ProcedureProtos.Procedure.Builder builder = ProcedureProtos.Procedure.newBuilder();
230 
231     builder.setClassName(procInfo.getProcName());
232     builder.setProcId(procInfo.getProcId());
233     builder.setStartTime(procInfo.getStartTime());
234     builder.setState(procInfo.getProcState());
235     builder.setLastUpdate(procInfo.getLastUpdate());
236 
237     if (procInfo.hasParentId()) {
238       builder.setParentId(procInfo.getParentId());
239     }
240 
241     if (procInfo.getProcOwner() != null) {
242        builder.setOwner(procInfo.getProcOwner());
243     }
244 
245     if (procInfo.isFailed()) {
246         builder.setException(procInfo.getForeignExceptionMessage());
247     }
248 
249     if (procInfo.hasResultData()) {
250       builder.setResult(ByteStringer.wrap(procInfo.getResult()));
251     }
252 
253     return builder.build();
254   }
255 
256   /**
257    * Helper to convert the protobuf object.
258    * @return Convert the current Protocol Buffers Procedure to {@link ProcedureInfo}
259    * instance.
260    */
261   @InterfaceAudience.Private
262   @Deprecated
263   public static ProcedureInfo convert(final ProcedureProtos.Procedure procProto) {
264     NonceKey nonceKey = null;
265     if (procProto.getNonce() != HConstants.NO_NONCE) {
266       nonceKey = new NonceKey(procProto.getNonceGroup(), procProto.getNonce());
267     }
268 
269     return new ProcedureInfo(
270       procProto.getProcId(),
271       procProto.getClassName(),
272       procProto.getOwner(),
273       procProto.getState(),
274       procProto.hasParentId() ? procProto.getParentId() : -1,
275       nonceKey,
276       procProto.hasException() ? procProto.getException() : null,
277       procProto.getLastUpdate(),
278       procProto.getStartTime(),
279       procProto.hasResult() ? procProto.getResult().toByteArray() : null);
280   }
281 
282   /**
283   * Check if the user is this procedure's owner
284   * @param owner the owner field of the procedure
285   * @param user the user
286   * @return true if the user is the owner of the procedure,
287   *   false otherwise or the owner is unknown.
288   */
289   @InterfaceAudience.Private
290   public static boolean isProcedureOwner(final ProcedureInfo procInfo, final User user) {
291     if (user == null) {
292       return false;
293     }
294     String procOwner = procInfo.getProcOwner();
295     if (procOwner == null) {
296       return false;
297     }
298     return procOwner.equals(user.getShortName());
299   }
300 }