Coverage Report - sk.baka.webvm.Threads
 
Classes in this File Line Coverage Branch Coverage Complexity
Threads
0%
0/33
0%
0/21
4.714
Threads$1
0%
0/1
N/A
4.714
Threads$ThreadListModel
0%
0/5
0%
0/2
4.714
Threads$ThreadListView
0%
0/23
0%
0/10
4.714
 
 1  
 /**
 2  
  * Copyright 2009 Martin Vysny.
 3  
  *
 4  
  * This file is part of WebVM.
 5  
  *
 6  
  * WebVM is free software: you can redistribute it and/or modify
 7  
  * it under the terms of the GNU General Public License as published by
 8  
  * the Free Software Foundation, either version 3 of the License, or
 9  
  * (at your option) any later version.
 10  
  *
 11  
  * WebVM is distributed in the hope that it will be useful,
 12  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  
  * GNU General Public License for more details.
 15  
  *
 16  
  * You should have received a copy of the GNU General Public License
 17  
  * along with WebVM.  If not, see <http://www.gnu.org/licenses/>.
 18  
  */
 19  
 package sk.baka.webvm;
 20  
 
 21  
 import java.lang.management.ThreadInfo;
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.SortedMap;
 26  
 import java.util.TreeMap;
 27  
 import org.apache.wicket.behavior.SimpleAttributeModifier;
 28  
 import org.apache.wicket.markup.html.basic.Label;
 29  
 import org.apache.wicket.markup.html.list.ListItem;
 30  
 import org.apache.wicket.markup.html.list.ListView;
 31  
 import org.apache.wicket.model.IModel;
 32  
 import org.apache.wicket.model.LoadableDetachableModel;
 33  
 import sk.baka.webvm.analyzer.HistorySample;
 34  
 
 35  
 /**
 36  
  * Shows the thread history.
 37  
  * @author vyzivus
 38  
  */
 39  0
 public final class Threads extends WebVMPage {
 40  
 
 41  
     private static final long serialVersionUID = 1L;
 42  
     private static final int MAX_THREAD_NAME_LENGTH = 30;
 43  
 
 44  
     /**
 45  
      * Constructor.
 46  
      */
 47  0
     public Threads() {
 48  0
         border.add(new ThreadListView("threads", new ThreadListModel()));
 49  0
     }
 50  
 
 51  
     private static SortedMap<Long, List<ThreadInfo>> analyzeThreads() {
 52  0
         final List<HistorySample> samples = WicketApplication.getHistory().getVmstatHistory();
 53  0
         final SortedMap<Long, List<ThreadInfo>> history = new TreeMap<Long, List<ThreadInfo>>();
 54  
         // compute the map
 55  0
         int i = 0;
 56  0
         for (final HistorySample sample : samples) {
 57  0
             for (final ThreadInfo info : sample.threads) {
 58  0
                 if (info == null) {
 59  0
                     continue;
 60  
                 }
 61  0
                 List<ThreadInfo> list = history.get(info.getThreadId());
 62  0
                 if (list == null) {
 63  0
                     list = new ArrayList<ThreadInfo>(samples.size());
 64  0
                     history.put(info.getThreadId(), list);
 65  
                 }
 66  0
                 ensureSize(list, i);
 67  0
                 list.add(info);
 68  
             }
 69  0
             i++;
 70  
         }
 71  
         // align dead threads' list for a proper length.
 72  0
         for (final List<ThreadInfo> infos : history.values()) {
 73  0
             ensureSize(infos, i);
 74  
         }
 75  0
         return history;
 76  
     }
 77  
 
 78  
     /**
 79  
      * Returns an ASCII-graphic character representing the thread state.
 80  
      * @param info the thread.
 81  
      * @return the thread character.
 82  
      */
 83  
     private static char getStateChar(final ThreadInfo info) {
 84  0
         if (info == null) {
 85  0
             return ' ';
 86  
         }
 87  0
         switch (info.getThreadState()) {
 88  
             case NEW:
 89  0
                 return '.';
 90  
             case BLOCKED:
 91  0
                 return 'x';
 92  
             case RUNNABLE:
 93  0
                 return '|';
 94  
             case TERMINATED:
 95  0
                 return '_';
 96  
             case TIMED_WAITING:
 97  
             case WAITING:
 98  0
                 return 'z';
 99  
         }
 100  0
         throw new AssertionError();
 101  
     }
 102  
 
 103  0
     private static class ThreadListModel extends LoadableDetachableModel<List<List<ThreadInfo>>> {
 104  
 
 105  
         private static final long serialVersionUID = 1L;
 106  
         private transient Map<Long, List<ThreadInfo>> map;
 107  
 
 108  
         @Override
 109  
         protected List<List<ThreadInfo>> load() {
 110  0
             if (map == null) {
 111  0
                 map = analyzeThreads();
 112  
             }
 113  0
             final List<List<ThreadInfo>> result = new ArrayList<List<ThreadInfo>>(map.values());
 114  0
             return result;
 115  
         }
 116  
     }
 117  
 
 118  
     /**
 119  
      * Ensures that the given list is of given size, appending nulls as necessary.
 120  
      * @param list the list to enlarge. Will be modified.
 121  
      * @param size the desired size
 122  
      * @return the list itself.
 123  
      */
 124  
     private static List<ThreadInfo> ensureSize(List<ThreadInfo> list, final int size) {
 125  0
         while (list.size() < size) {
 126  0
             list.add(null);
 127  
         }
 128  0
         return list;
 129  
     }
 130  
 
 131  
     /**
 132  
      * Wicket ListView showing thread names and thread states.
 133  
      */
 134  
     private static class ThreadListView extends ListView<List<ThreadInfo>> {
 135  
 
 136  
         private static final long serialVersionUID = 1L;
 137  
 
 138  
         public ThreadListView(String id, IModel<? extends List<? extends List<ThreadInfo>>> model) {
 139  0
             super(id, model);
 140  0
         }
 141  
 
 142  
         @Override
 143  
         protected void populateItem(ListItem<List<ThreadInfo>> item) {
 144  0
             final List<ThreadInfo> infos = item.getModelObject();
 145  0
             ThreadInfo ti = null;
 146  0
             for (final ThreadInfo info : infos) {
 147  0
                 if (info != null) {
 148  0
                     ti = info;
 149  0
                     break;
 150  
                 }
 151  
             }
 152  0
             final ThreadInfo last = infos.get(infos.size() - 1);
 153  0
             String name = ti.getThreadName();
 154  0
             String title = name;
 155  0
             if (name.length() > MAX_THREAD_NAME_LENGTH) {
 156  0
                 name = name.substring(0, MAX_THREAD_NAME_LENGTH) + "...";
 157  
             }
 158  0
             final Label l = new Label("threadName", name);
 159  0
             item.add(l);
 160  0
             l.add(new SimpleAttributeModifier("title", title));
 161  0
             final String state = last == null ? "dead" : last.getThreadState().toString();
 162  0
             item.add(new Label("threadState", state));
 163  0
             final StringBuilder sb = new StringBuilder();
 164  0
             for (final ThreadInfo info : infos) {
 165  0
                 sb.append(getStateChar(info));
 166  
             }
 167  0
             item.add(new Label("threadHistory", sb.toString()));
 168  0
         }
 169  
     }
 170  
 }
 171