001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.mapred;
020
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.Collection;
026import java.util.Collections;
027
028import org.apache.hadoop.classification.InterfaceAudience;
029import org.apache.hadoop.classification.InterfaceStability;
030import org.apache.hadoop.io.Text;
031import org.apache.hadoop.io.Writable;
032import org.apache.hadoop.io.WritableUtils;
033import org.apache.hadoop.mapreduce.Cluster.JobTrackerStatus;
034import org.apache.hadoop.util.StringInterner;
035
036/**
037 * Status information on the current state of the Map-Reduce cluster.
038 * 
039 * <p><code>ClusterStatus</code> provides clients with information such as:
040 * <ol>
041 *   <li>
042 *   Size of the cluster. 
043 *   </li>
044 *   <li>
045 *   Name of the trackers. 
046 *   </li>
047 *   <li>
048 *   Task capacity of the cluster. 
049 *   </li>
050 *   <li>
051 *   The number of currently running map and reduce tasks.
052 *   </li>
053 *   <li>
054 *   State of the <code>JobTracker</code>.
055 *   </li>
056 *   <li>
057 *   Details regarding black listed trackers.
058 *   </li>
059 * </ol>
060 * 
061 * <p>Clients can query for the latest <code>ClusterStatus</code>, via 
062 * {@link JobClient#getClusterStatus()}.</p>
063 * 
064 * @see JobClient
065 */
066@InterfaceAudience.Public
067@InterfaceStability.Stable
068public class ClusterStatus implements Writable {
069  /**
070   * Class which encapsulates information about a blacklisted tasktracker.
071   *  
072   * The information includes the tasktracker's name and reasons for
073   * getting blacklisted. The toString method of the class will print
074   * the information in a whitespace separated fashion to enable parsing.
075   */
076  public static class BlackListInfo implements Writable {
077
078    private String trackerName;
079
080    private String reasonForBlackListing;
081    
082    private String blackListReport;
083    
084    BlackListInfo() {
085    }
086    
087
088    /**
089     * Gets the blacklisted tasktracker's name.
090     * 
091     * @return tracker's name.
092     */
093    public String getTrackerName() {
094      return trackerName;
095    }
096
097    /**
098     * Gets the reason for which the tasktracker was blacklisted.
099     * 
100     * @return reason which tracker was blacklisted
101     */
102    public String getReasonForBlackListing() {
103      return reasonForBlackListing;
104    }
105
106    /**
107     * Sets the blacklisted tasktracker's name.
108     * 
109     * @param trackerName of the tracker.
110     */
111    void setTrackerName(String trackerName) {
112      this.trackerName = trackerName;
113    }
114
115    /**
116     * Sets the reason for which the tasktracker was blacklisted.
117     * 
118     * @param reasonForBlackListing
119     */
120    void setReasonForBlackListing(String reasonForBlackListing) {
121      this.reasonForBlackListing = reasonForBlackListing;
122    }
123
124    /**
125     * Gets a descriptive report about why the tasktracker was blacklisted.
126     * 
127     * @return report describing why the tasktracker was blacklisted.
128     */
129    public String getBlackListReport() {
130      return blackListReport;
131    }
132
133    /**
134     * Sets a descriptive report about why the tasktracker was blacklisted.
135     * @param blackListReport report describing why the tasktracker 
136     *                        was blacklisted.
137     */
138    void setBlackListReport(String blackListReport) {
139      this.blackListReport = blackListReport;
140    }
141
142    @Override
143    public void readFields(DataInput in) throws IOException {
144      trackerName = StringInterner.weakIntern(Text.readString(in));
145      reasonForBlackListing = StringInterner.weakIntern(Text.readString(in));
146      blackListReport = StringInterner.weakIntern(Text.readString(in));
147    }
148
149    @Override
150    public void write(DataOutput out) throws IOException {
151      Text.writeString(out, trackerName);
152      Text.writeString(out, reasonForBlackListing);
153      Text.writeString(out, blackListReport);
154    }
155
156    @Override
157    /**
158     * Print information related to the blacklisted tasktracker in a
159     * whitespace separated fashion.
160     * 
161     * The method changes any newlines in the report describing why
162     * the tasktracker was blacklisted to a ':' for enabling better
163     * parsing.
164     */
165    public String toString() {
166      StringBuilder sb = new StringBuilder();
167      sb.append(trackerName);
168      sb.append("\t");
169      sb.append(reasonForBlackListing);
170      sb.append("\t");
171      sb.append(blackListReport.replace("\n", ":"));
172      return sb.toString();
173    }
174
175    @Override
176    public int hashCode() {
177      int result = trackerName != null ? trackerName.hashCode() : 0;
178      result = 31 * result + (reasonForBlackListing != null ?
179          reasonForBlackListing.hashCode() : 0);
180      result = 31 * result + (blackListReport != null ?
181          blackListReport.hashCode() : 0);
182      return result;
183    }
184
185    @Override
186    public boolean equals(Object obj) {
187      if (this == obj) {
188        return true;
189      }
190      if (obj == null || getClass() != obj.getClass()) {
191        return false;
192      }
193      final BlackListInfo that = (BlackListInfo) obj;
194      if (trackerName == null ? that.trackerName != null :
195          !trackerName.equals(that.trackerName)) {
196        return false;
197      }
198      if (reasonForBlackListing == null ? that.reasonForBlackListing != null :
199          !reasonForBlackListing.equals(that.reasonForBlackListing)) {
200        return false;
201      }
202      if (blackListReport == null ? that.blackListReport != null :
203          !blackListReport.equals(that.blackListReport)) {
204        return false;
205      }
206      return true;
207    }
208  }
209  
210  public static final long UNINITIALIZED_MEMORY_VALUE = -1;
211  
212  private int numActiveTrackers;
213  private Collection<String> activeTrackers = new ArrayList<String>();
214  private int numBlacklistedTrackers;
215  private int numExcludedNodes;
216  private long ttExpiryInterval;
217  private int map_tasks;
218  private int reduce_tasks;
219  private int max_map_tasks;
220  private int max_reduce_tasks;
221  private JobTrackerStatus status;
222  private Collection<BlackListInfo> blacklistedTrackersInfo =
223    new ArrayList<BlackListInfo>();
224  private int grayListedTrackers;
225
226  ClusterStatus() {}
227  
228  /**
229   * Construct a new cluster status.
230   * 
231   * @param trackers no. of tasktrackers in the cluster
232   * @param blacklists no of blacklisted task trackers in the cluster
233   * @param ttExpiryInterval the tasktracker expiry interval
234   * @param maps no. of currently running map-tasks in the cluster
235   * @param reduces no. of currently running reduce-tasks in the cluster
236   * @param maxMaps the maximum no. of map tasks in the cluster
237   * @param maxReduces the maximum no. of reduce tasks in the cluster
238   * @param status the {@link JobTrackerStatus} of the <code>JobTracker</code>
239   */
240  ClusterStatus(int trackers, int blacklists, long ttExpiryInterval, 
241                int maps, int reduces,
242                int maxMaps, int maxReduces, JobTrackerStatus status) {
243    this(trackers, blacklists, ttExpiryInterval, maps, reduces, maxMaps, 
244         maxReduces, status, 0);
245  }
246
247  /**
248   * Construct a new cluster status.
249   * 
250   * @param trackers no. of tasktrackers in the cluster
251   * @param blacklists no of blacklisted task trackers in the cluster
252   * @param ttExpiryInterval the tasktracker expiry interval
253   * @param maps no. of currently running map-tasks in the cluster
254   * @param reduces no. of currently running reduce-tasks in the cluster
255   * @param maxMaps the maximum no. of map tasks in the cluster
256   * @param maxReduces the maximum no. of reduce tasks in the cluster
257   * @param status the {@link JobTrackerStatus} of the <code>JobTracker</code>
258   * @param numDecommissionedNodes number of decommission trackers
259   */
260  ClusterStatus(int trackers, int blacklists, long ttExpiryInterval, int maps,
261      int reduces, int maxMaps, int maxReduces, JobTrackerStatus status,
262      int numDecommissionedNodes) {
263    this(trackers, blacklists, ttExpiryInterval, maps, reduces, maxMaps,
264      maxReduces, status, numDecommissionedNodes, 0);
265  }
266
267  /**
268   * Construct a new cluster status.
269   * 
270   * @param trackers no. of tasktrackers in the cluster
271   * @param blacklists no of blacklisted task trackers in the cluster
272   * @param ttExpiryInterval the tasktracker expiry interval
273   * @param maps no. of currently running map-tasks in the cluster
274   * @param reduces no. of currently running reduce-tasks in the cluster
275   * @param maxMaps the maximum no. of map tasks in the cluster
276   * @param maxReduces the maximum no. of reduce tasks in the cluster
277   * @param status the {@link JobTrackerStatus} of the <code>JobTracker</code>
278   * @param numDecommissionedNodes number of decommission trackers
279   * @param numGrayListedTrackers number of graylisted trackers
280   */
281  ClusterStatus(int trackers, int blacklists, long ttExpiryInterval, int maps,
282      int reduces, int maxMaps, int maxReduces, JobTrackerStatus status,
283      int numDecommissionedNodes, int numGrayListedTrackers) {
284    numActiveTrackers = trackers;
285    numBlacklistedTrackers = blacklists;
286    this.numExcludedNodes = numDecommissionedNodes;
287    this.ttExpiryInterval = ttExpiryInterval;
288    map_tasks = maps;
289    reduce_tasks = reduces;
290    max_map_tasks = maxMaps;
291    max_reduce_tasks = maxReduces;
292    this.status = status;
293    this.grayListedTrackers = numGrayListedTrackers;
294  }
295
296  /**
297   * Construct a new cluster status.
298   * 
299   * @param activeTrackers active tasktrackers in the cluster
300   * @param blacklistedTrackers blacklisted tasktrackers in the cluster
301   * @param ttExpiryInterval the tasktracker expiry interval
302   * @param maps no. of currently running map-tasks in the cluster
303   * @param reduces no. of currently running reduce-tasks in the cluster
304   * @param maxMaps the maximum no. of map tasks in the cluster
305   * @param maxReduces the maximum no. of reduce tasks in the cluster
306   * @param status the {@link JobTrackerStatus} of the <code>JobTracker</code>
307   */
308  ClusterStatus(Collection<String> activeTrackers, 
309      Collection<BlackListInfo> blacklistedTrackers,
310      long ttExpiryInterval,
311      int maps, int reduces, int maxMaps, int maxReduces, 
312      JobTrackerStatus status) {
313    this(activeTrackers, blacklistedTrackers, ttExpiryInterval, maps, reduces, 
314         maxMaps, maxReduces, status, 0);
315  }
316
317
318  /**
319   * Construct a new cluster status.
320   * 
321   * @param activeTrackers active tasktrackers in the cluster
322   * @param blackListedTrackerInfo blacklisted tasktrackers information 
323   * in the cluster
324   * @param ttExpiryInterval the tasktracker expiry interval
325   * @param maps no. of currently running map-tasks in the cluster
326   * @param reduces no. of currently running reduce-tasks in the cluster
327   * @param maxMaps the maximum no. of map tasks in the cluster
328   * @param maxReduces the maximum no. of reduce tasks in the cluster
329   * @param status the {@link JobTrackerStatus} of the <code>JobTracker</code>
330   * @param numDecommissionNodes number of decommission trackers
331   */
332  
333  ClusterStatus(Collection<String> activeTrackers,
334      Collection<BlackListInfo> blackListedTrackerInfo, long ttExpiryInterval,
335      int maps, int reduces, int maxMaps, int maxReduces,
336      JobTrackerStatus status, int numDecommissionNodes) {
337    this(activeTrackers.size(), blackListedTrackerInfo.size(),
338        ttExpiryInterval, maps, reduces, maxMaps, maxReduces, status,
339        numDecommissionNodes);
340    this.activeTrackers = activeTrackers;
341    this.blacklistedTrackersInfo = blackListedTrackerInfo;
342  }
343
344  /**
345   * Get the number of task trackers in the cluster.
346   * 
347   * @return the number of task trackers in the cluster.
348   */
349  public int getTaskTrackers() {
350    return numActiveTrackers;
351  }
352  
353  /**
354   * Get the names of task trackers in the cluster.
355   * 
356   * @return the active task trackers in the cluster.
357   */
358  public Collection<String> getActiveTrackerNames() {
359    return activeTrackers;
360  }
361
362  /**
363   * Get the names of task trackers in the cluster.
364   * 
365   * @return the blacklisted task trackers in the cluster.
366   */
367  public Collection<String> getBlacklistedTrackerNames() {
368    ArrayList<String> blacklistedTrackers = new ArrayList<String>();
369    for(BlackListInfo bi : blacklistedTrackersInfo) {
370      blacklistedTrackers.add(bi.getTrackerName());
371    }
372    return blacklistedTrackers;
373  }
374
375  /**
376   * Get the names of graylisted task trackers in the cluster.
377   *
378   * The gray list of trackers is no longer available on M/R 2.x. The function
379   * is kept to be compatible with M/R 1.x applications.
380   *
381   * @return an empty graylisted task trackers in the cluster.
382   */
383  @Deprecated
384  public Collection<String> getGraylistedTrackerNames() {
385    return Collections.emptySet();
386  }
387
388  /**
389   * Get the number of graylisted task trackers in the cluster.
390   *
391   * The gray list of trackers is no longer available on M/R 2.x. The function
392   * is kept to be compatible with M/R 1.x applications.
393   *
394   * @return 0 graylisted task trackers in the cluster.
395   */
396  @Deprecated
397  public int getGraylistedTrackers() {
398    return grayListedTrackers;
399  }
400
401  /**
402   * Get the number of blacklisted task trackers in the cluster.
403   * 
404   * @return the number of blacklisted task trackers in the cluster.
405   */
406  public int getBlacklistedTrackers() {
407    return numBlacklistedTrackers;
408  }
409  
410  /**
411   * Get the number of excluded hosts in the cluster.
412   * @return the number of excluded hosts in the cluster.
413   */
414  public int getNumExcludedNodes() {
415    return numExcludedNodes;
416  }
417  
418  /**
419   * Get the tasktracker expiry interval for the cluster
420   * @return the expiry interval in msec
421   */
422  public long getTTExpiryInterval() {
423    return ttExpiryInterval;
424  }
425  
426  /**
427   * Get the number of currently running map tasks in the cluster.
428   * 
429   * @return the number of currently running map tasks in the cluster.
430   */
431  public int getMapTasks() {
432    return map_tasks;
433  }
434  
435  /**
436   * Get the number of currently running reduce tasks in the cluster.
437   * 
438   * @return the number of currently running reduce tasks in the cluster.
439   */
440  public int getReduceTasks() {
441    return reduce_tasks;
442  }
443  
444  /**
445   * Get the maximum capacity for running map tasks in the cluster.
446   * 
447   * @return the maximum capacity for running map tasks in the cluster.
448   */
449  public int getMaxMapTasks() {
450    return max_map_tasks;
451  }
452
453  /**
454   * Get the maximum capacity for running reduce tasks in the cluster.
455   * 
456   * @return the maximum capacity for running reduce tasks in the cluster.
457   */
458  public int getMaxReduceTasks() {
459    return max_reduce_tasks;
460  }
461  
462  /**
463   * Get the JobTracker's status.
464   * 
465   * @return {@link JobTrackerStatus} of the JobTracker
466   */
467  public JobTrackerStatus getJobTrackerStatus() {
468    return status;
469  }
470  
471  /**
472   * Returns UNINITIALIZED_MEMORY_VALUE (-1)
473   */
474  @Deprecated
475  public long getMaxMemory() {
476    return UNINITIALIZED_MEMORY_VALUE;
477  }
478  
479  /**
480   * Returns UNINITIALIZED_MEMORY_VALUE (-1)
481   */
482  @Deprecated
483  public long getUsedMemory() {
484    return UNINITIALIZED_MEMORY_VALUE;
485  }
486
487  /**
488   * Gets the list of blacklisted trackers along with reasons for blacklisting.
489   * 
490   * @return the collection of {@link BlackListInfo} objects. 
491   * 
492   */
493  public Collection<BlackListInfo> getBlackListedTrackersInfo() {
494    return blacklistedTrackersInfo;
495  }
496
497  /**
498   * Get the current state of the <code>JobTracker</code>,
499   * as {@link JobTracker.State}
500   *
501   * {@link JobTracker.State} should no longer be used on M/R 2.x. The function
502   * is kept to be compatible with M/R 1.x applications.
503   *
504   * @return the invalid state of the <code>JobTracker</code>.
505   */
506  @Deprecated
507  public JobTracker.State getJobTrackerState() {
508    return JobTracker.State.RUNNING;
509  }
510
511  public void write(DataOutput out) throws IOException {
512    if (activeTrackers.size() == 0) {
513      out.writeInt(numActiveTrackers);
514      out.writeInt(0);
515    } else {
516      out.writeInt(activeTrackers.size());
517      out.writeInt(activeTrackers.size());
518      for (String tracker : activeTrackers) {
519        Text.writeString(out, tracker);
520      }
521    }
522    if (blacklistedTrackersInfo.size() == 0) {
523      out.writeInt(numBlacklistedTrackers);
524      out.writeInt(blacklistedTrackersInfo.size());
525    } else {
526      out.writeInt(blacklistedTrackersInfo.size());
527      out.writeInt(blacklistedTrackersInfo.size());
528      for (BlackListInfo tracker : blacklistedTrackersInfo) {
529        tracker.write(out);
530      }
531    }
532    out.writeInt(numExcludedNodes);
533    out.writeLong(ttExpiryInterval);
534    out.writeInt(map_tasks);
535    out.writeInt(reduce_tasks);
536    out.writeInt(max_map_tasks);
537    out.writeInt(max_reduce_tasks);
538    WritableUtils.writeEnum(out, status);
539    out.writeInt(grayListedTrackers);
540  }
541
542  public void readFields(DataInput in) throws IOException {
543    numActiveTrackers = in.readInt();
544    int numTrackerNames = in.readInt();
545    if (numTrackerNames > 0) {
546      for (int i = 0; i < numTrackerNames; i++) {
547        String name = StringInterner.weakIntern(Text.readString(in));
548        activeTrackers.add(name);
549      }
550    }
551    numBlacklistedTrackers = in.readInt();
552    int blackListTrackerInfoSize = in.readInt();
553    if(blackListTrackerInfoSize > 0) {
554      for (int i = 0; i < blackListTrackerInfoSize; i++) {
555        BlackListInfo info = new BlackListInfo();
556        info.readFields(in);
557        blacklistedTrackersInfo.add(info);
558      }
559    }
560    numExcludedNodes = in.readInt();
561    ttExpiryInterval = in.readLong();
562    map_tasks = in.readInt();
563    reduce_tasks = in.readInt();
564    max_map_tasks = in.readInt();
565    max_reduce_tasks = in.readInt();
566    status = WritableUtils.readEnum(in, JobTrackerStatus.class);
567    grayListedTrackers = in.readInt();
568  }
569}