View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.monitoring;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.hbase.util.GsonUtil;
29  import org.apache.hbase.thirdparty.com.google.gson.Gson;
30  
31  @InterfaceAudience.Private
32  class MonitoredTaskImpl implements MonitoredTask {
33    private long startTime;
34    private long statusTime;
35    private long stateTime;
36    private long warnTime;
37  
38    private volatile String status;
39    private volatile String description;
40    
41    protected volatile State state = State.RUNNING;
42  
43    private boolean journalEnabled = false;
44    private List<StatusJournalEntry> journal;
45  
46    private static final Gson GSON = GsonUtil.createGson().create();
47  
48    public MonitoredTaskImpl() {
49      startTime = System.currentTimeMillis();
50      statusTime = startTime;
51      stateTime = startTime;
52      warnTime = startTime;
53    }
54  
55    private static class StatusJournalEntryImpl implements StatusJournalEntry {
56      private long statusTime;
57      private String status;
58  
59      public StatusJournalEntryImpl(String status, long statusTime) {
60        this.status = status;
61        this.statusTime = statusTime;
62      }
63  
64      @Override
65      public String getStatus() {
66        return status;
67      }
68  
69      @Override
70      public long getTimeStamp() {
71        return statusTime;
72      }
73  
74      @Override
75      public String toString() {
76        StringBuilder sb = new StringBuilder();
77        sb.append(status);
78        sb.append(" at ");
79        sb.append(statusTime);
80        return sb.toString();
81      }
82    }
83  
84    @Override
85    public synchronized MonitoredTaskImpl clone() {
86      try {
87        return (MonitoredTaskImpl) super.clone();
88      } catch (CloneNotSupportedException e) {
89        throw new AssertionError(); // Won't happen
90      }
91    }
92  
93    @Override
94    public long getStartTime() {
95      return startTime;
96    }
97    
98    @Override
99    public String getDescription() {
100     return description;
101   }
102 
103   @Override
104   public String getStatus() {
105     return status;
106   }
107 
108   @Override
109   public long getStatusTime() {
110     return statusTime;
111   }
112   
113   @Override
114   public State getState() {
115     return state;
116   }
117   
118   @Override
119   public long getStateTime() {
120     return stateTime;
121   }
122 
123   @Override
124   public long getWarnTime() {
125     return warnTime;
126   }
127 
128   @Override
129   public long getCompletionTimestamp() {
130     if (state == State.COMPLETE || state == State.ABORTED) {
131       return stateTime;
132     }
133     return -1;
134   }
135 
136   @Override
137   public void markComplete(String status) {
138     setState(State.COMPLETE);
139     setStatus(status);
140   }
141 
142   @Override
143   public void pause(String msg) {
144     setState(State.WAITING);
145     setStatus(msg);
146   }
147 
148   @Override
149   public void resume(String msg) {
150     setState(State.RUNNING);
151     setStatus(msg);
152   }
153 
154   @Override
155   public void abort(String msg) {
156     setStatus(msg);
157     setState(State.ABORTED);
158   }
159   
160   @Override
161   public void setStatus(String status) {
162     this.status = status;
163     statusTime = System.currentTimeMillis();
164     if (journalEnabled) {
165       journal.add(new StatusJournalEntryImpl(this.status, statusTime));
166     }
167   }
168 
169   protected void setState(State state) {
170     this.state = state;
171     stateTime = System.currentTimeMillis();
172   }
173 
174   @Override
175   public void setDescription(String description) {
176     this.description = description;
177   }
178 
179   @Override
180   public void setWarnTime(long t) {
181     this.warnTime = t;
182   }
183 
184   @Override
185   public void cleanup() {
186     if (state == State.RUNNING) {
187       setState(State.ABORTED);
188     }
189   }
190 
191   /**
192    * Force the completion timestamp backwards so that
193    * it expires now.
194    */
195   public void expireNow() {
196     stateTime -= 180 * 1000;
197   }
198 
199   @Override
200   public Map<String, Object> toMap() {
201     Map<String, Object> map = new HashMap<String, Object>();
202     map.put("description", getDescription());
203     map.put("status", getStatus());
204     map.put("state", getState());
205     map.put("starttimems", getStartTime());
206     map.put("statustimems", getCompletionTimestamp());
207     map.put("statetimems", getCompletionTimestamp());
208     return map;
209   }
210 
211   @Override
212   public String toJSON() throws IOException {
213     return GSON.toJson(toMap());
214   }
215 
216   @Override
217   public String toString() {
218     StringBuilder sb = new StringBuilder(512);
219     sb.append(getDescription());
220     sb.append(": status=");
221     sb.append(getStatus());
222     sb.append(", state=");
223     sb.append(getState());
224     sb.append(", startTime=");
225     sb.append(getStartTime());
226     sb.append(", completionTime=");
227     sb.append(getCompletionTimestamp());
228     return sb.toString();
229   }
230 
231   /**
232    * Returns the status journal. This implementation of status journal is not thread-safe. Currently
233    * we use this to track various stages of flushes and compactions where we can use this/pretty
234    * print for post task analysis, by which time we are already done changing states (writing to
235    * journal)
236    */
237   @Override
238   public List<StatusJournalEntry> getStatusJournal() {
239     if (journal == null) {
240       return Collections.emptyList();
241     } else {
242       return Collections.unmodifiableList(journal);
243     }
244   }
245 
246   /**
247    * Enables journaling of this monitored task, the first invocation will lazily initialize the
248    * journal. The journal implementation itself and this method are not thread safe
249    */
250   @Override
251   public void enableStatusJournal(boolean includeCurrentStatus) {
252     if (journalEnabled && journal != null) {
253       return;
254     }
255     journalEnabled = true;
256     if (journal == null) {
257       journal = new ArrayList<StatusJournalEntry>();
258     }
259     if (includeCurrentStatus && status != null) {
260       journal.add(new StatusJournalEntryImpl(status, statusTime));
261     }
262   }
263 
264   @Override
265   public void disableStatusJournal() {
266     journalEnabled = false;
267   }
268 
269   @Override
270   public String prettyPrintJournal() {
271     StringBuilder sb = new StringBuilder();
272     for (int i = 0; i < journal.size(); i++) {
273       StatusJournalEntry je = journal.get(i);
274       sb.append(je.toString());
275       if (i != 0) {
276         StatusJournalEntry jep = journal.get(i-1);
277         long delta = je.getTimeStamp() - jep.getTimeStamp();
278         if (delta != 0) {
279           sb.append(" (+" + delta + " ms)");
280         }
281       }
282       sb.append("\n");
283     }
284     return sb.toString();
285   }
286 
287 }