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.ForeignExceptionUtil;
31  import org.apache.hadoop.hbase.util.NonceKey;
32  
33  /**
34   * Procedure information
35   */
36  @InterfaceAudience.Public
37  @InterfaceStability.Evolving
38  public class ProcedureInfo {
39    private final long procId;
40    private final String procName;
41    private final String procOwner;
42    private final ProcedureState procState;
43    private final long parentId;
44    private final ForeignExceptionMessage exception;
45    private final long lastUpdate;
46    private final long startTime;
47    private final byte[] result;
48  
49    private NonceKey nonceKey = null;
50    private long clientAckTime = -1;
51  
52    public ProcedureInfo(
53        final long procId,
54        final String procName,
55        final String procOwner,
56        final ProcedureState procState,
57        final long parentId,
58        final ForeignExceptionMessage exception,
59        final long lastUpdate,
60        final long startTime,
61        final byte[] result) {
62      this.procId = procId;
63      this.procName = procName;
64      this.procOwner = procOwner;
65      this.procState = procState;
66      this.parentId = parentId;
67      this.lastUpdate = lastUpdate;
68      this.startTime = startTime;
69  
70      // If the procedure is completed, we should treat exception and result differently
71      this.exception = exception;
72      this.result = result;
73    }
74  
75    public ProcedureInfo clone() {
76      return new ProcedureInfo(
77        procId, procName, procOwner, procState, parentId, exception, lastUpdate, startTime, result);
78    }
79  
80    public long getProcId() {
81      return procId;
82    }
83  
84    public String getProcName() {
85      return procName;
86    }
87  
88    public String getProcOwner() {
89      return procOwner;
90    }
91  
92    public ProcedureState getProcState() {
93      return procState;
94    }
95  
96    public boolean hasParentId() {
97      return (parentId != -1);
98    }
99  
100   public long getParentId() {
101     return parentId;
102   }
103 
104   public NonceKey getNonceKey() {
105     return nonceKey;
106   }
107 
108   public void setNonceKey(NonceKey nonceKey) {
109     this.nonceKey = nonceKey;
110   }
111 
112   public boolean isFailed() {
113     return exception != null;
114   }
115 
116   public IOException getException() {
117     if (isFailed()) {
118       return ForeignExceptionUtil.toIOException(exception);
119     }
120     return null;
121   }
122 
123   @InterfaceAudience.Private
124   public ForeignExceptionMessage getForeignExceptionMessage() {
125     return exception;
126   }
127 
128   public String getExceptionCause() {
129     assert isFailed();
130     return exception.getGenericException().getClassName();
131   }
132 
133   public String getExceptionMessage() {
134     assert isFailed();
135     return exception.getGenericException().getMessage();
136   }
137 
138   public String getExceptionFullMessage() {
139     assert isFailed();
140     return getExceptionCause() + " - " + getExceptionMessage();
141   }
142 
143   public boolean hasResultData() {
144     return result != null;
145   }
146 
147   public byte[] getResult() {
148     return result;
149   }
150 
151   public long getStartTime() {
152     return startTime;
153   }
154 
155   public long getLastUpdate() {
156     return lastUpdate;
157   }
158 
159   public long executionTime() {
160     return lastUpdate - startTime;
161   }
162 
163   @InterfaceAudience.Private
164   public boolean hasClientAckTime() {
165     return clientAckTime > 0;
166   }
167 
168   @InterfaceAudience.Private
169   public long getClientAckTime() {
170     return clientAckTime;
171   }
172 
173   @InterfaceAudience.Private
174   public void setClientAckTime(final long timestamp) {
175     this.clientAckTime = timestamp;
176   }
177 
178   /**
179    * @return Convert the current {@link ProcedureInfo} into a Protocol Buffers Procedure
180    * instance.
181    */
182   @InterfaceAudience.Private
183   public static ProcedureProtos.Procedure convertToProcedureProto(
184       final ProcedureInfo procInfo) {
185     ProcedureProtos.Procedure.Builder builder = ProcedureProtos.Procedure.newBuilder();
186 
187     builder.setClassName(procInfo.getProcName());
188     builder.setProcId(procInfo.getProcId());
189     builder.setStartTime(procInfo.getStartTime());
190     builder.setState(procInfo.getProcState());
191     builder.setLastUpdate(procInfo.getLastUpdate());
192 
193     if (procInfo.hasParentId()) {
194       builder.setParentId(procInfo.getParentId());
195     }
196 
197     if (procInfo.getProcOwner() != null) {
198        builder.setOwner(procInfo.getProcOwner());
199     }
200 
201     if (procInfo.isFailed()) {
202         builder.setException(procInfo.getForeignExceptionMessage());
203     }
204 
205     if (procInfo.hasResultData()) {
206       builder.setResult(ByteStringer.wrap(procInfo.getResult()));
207     }
208 
209     return builder.build();
210   }
211 
212   /**
213    * Helper to convert the protobuf object.
214    * @return Convert the current Protocol Buffers Procedure to {@link ProcedureInfo}
215    * instance.
216    */
217   @InterfaceAudience.Private
218   public static ProcedureInfo convert(final ProcedureProtos.Procedure procProto) {
219     return new ProcedureInfo(
220       procProto.getProcId(),
221       procProto.getClassName(),
222       procProto.getOwner(),
223       procProto.getState(),
224       procProto.hasParentId() ? procProto.getParentId() : -1,
225           procProto.getState() == ProcedureState.ROLLEDBACK ? procProto.getException() : null,
226       procProto.getLastUpdate(),
227       procProto.getStartTime(),
228       procProto.getState() == ProcedureState.FINISHED ? procProto.getResult().toByteArray() : null);
229   }
230 
231   /**
232   * Check if the user is this procedure's owner
233   * @param owner the owner field of the procedure
234   * @param user the user
235   * @return true if the user is the owner of the procedure,
236   *   false otherwise or the owner is unknown.
237   */
238   @InterfaceAudience.Private
239   public static boolean isProcedureOwner(final ProcedureInfo procInfo, final User user) {
240     if (user == null) {
241       return false;
242     }
243     String procOwner = procInfo.getProcOwner();
244     if (procOwner == null) {
245       return false;
246     }
247     return procOwner.equals(user.getShortName());
248   }
249 }