00001 package edu.rice.cs.hpc.common.util;
00002
00003
00004
00005
00006
00007
00008
00009 import org.eclipse.swt.*;
00010 import org.eclipse.swt.graphics.*;
00011 import org.eclipse.swt.widgets.*;
00012 import java.io.*;
00013
00014 public class Sleak {
00015 Display display;
00016 Shell shell = null;
00017 List list;
00018 Canvas canvas;
00019 Button start, stop, check;
00020 Text text;
00021 Label label;
00022
00023 Object [] oldObjects = new Object [0];
00024 Error [] oldErrors = new Error [0];
00025 Object [] objects = new Object [0];
00026 Error [] errors = new Error [0];
00027
00028 public void open () {
00029 if (shell != null)
00030 return;
00031
00032 display = Display.getCurrent ();
00033 shell = new Shell (display);
00034
00035 shell.setText ("S-Leak");
00036
00037 list = new List (shell, SWT.BORDER | SWT.V_SCROLL);
00038 list.addListener (SWT.Selection, new Listener () {
00039 public void handleEvent (Event event) {
00040 refreshObject ();
00041 }
00042 });
00043 text = new Text (shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
00044 canvas = new Canvas (shell, SWT.BORDER);
00045 canvas.addListener (SWT.Paint, new Listener () {
00046 public void handleEvent (Event event) {
00047 paintCanvas (event);
00048 }
00049 });
00050 check = new Button (shell, SWT.CHECK);
00051 check.setText ("Stack");
00052 check.addListener (SWT.Selection, new Listener () {
00053 public void handleEvent (Event e) {
00054 toggleStackTrace ();
00055 }
00056 });
00057 start = new Button (shell, SWT.PUSH);
00058 start.setText ("Snap");
00059 start.addListener (SWT.Selection, new Listener () {
00060 public void handleEvent (Event event) {
00061 refreshAll ();
00062 }
00063 });
00064 stop = new Button (shell, SWT.PUSH);
00065 stop.setText ("Diff");
00066 stop.addListener (SWT.Selection, new Listener () {
00067 public void handleEvent (Event event) {
00068 refreshDifference ();
00069 }
00070 });
00071 label = new Label (shell, SWT.BORDER);
00072 label.setText ("0 object(s)");
00073 shell.addListener (SWT.Resize, new Listener () {
00074 public void handleEvent (Event e) {
00075 layout ();
00076 }
00077 });
00078 check.setSelection (false);
00079 text.setVisible (false);
00080 Point size = shell.getSize ();
00081 shell.setSize (size.x / 2, size.y / 2);
00082 shell.open ();
00083 }
00084
00085
00086
00087 void refreshLabel () {
00088 String string = getCount();
00089
00090 if (string.length () != 0) {
00091 string = string.substring (0, string.length () - 1);
00092 }
00093 label.setText (string);
00094 }
00095
00096
00097
00098
00099
00100
00101 String getCount() {
00102 int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0, regions = 0;
00103 for (int i=0; i<objects.length; i++) {
00104 Object object = objects [i];
00105 if (object instanceof Color) colors++;
00106 if (object instanceof Cursor) cursors++;
00107 if (object instanceof Font) fonts++;
00108 if (object instanceof GC) gcs++;
00109 if (object instanceof Image) images++;
00110 if (object instanceof Region) regions++;
00111 }
00112 String string = "";
00113 if (colors != 0) string += colors + " Color(s)\n";
00114 if (cursors != 0) string += cursors + " Cursor(s)\n";
00115 if (fonts != 0) string += fonts + " Font(s)\n";
00116 if (gcs != 0) string += gcs + " GC(s)\n";
00117 if (images != 0) string += images + " Image(s)\n";
00118 if (regions != 0) string += regions + " Region(s)\n";
00119
00120 return string;
00121 }
00122
00123 void refreshDifference () {
00124 DeviceData info = display.getDeviceData ();
00125 if (!info.tracking) {
00126 MessageBox dialog = new MessageBox (shell, SWT.ICON_WARNING | SWT.OK);
00127 dialog.setText (shell.getText ());
00128 dialog.setMessage ("Warning: Device is not tracking resource allocation");
00129 dialog.open ();
00130 }
00131 Object [] newObjects = info.objects;
00132 Error [] newErrors = info.errors;
00133 Object [] diffObjects = new Object [newObjects.length];
00134 Error [] diffErrors = new Error [newErrors.length];
00135 int count = 0;
00136
00137 for (int i=0; i<newObjects.length; i++) {
00138 int index = 0;
00139 while (index < oldObjects.length) {
00140 if (newObjects [i] == oldObjects [index]) break;
00141 index++;
00142 }
00143 if (index == oldObjects.length) {
00144 diffObjects [count] = newObjects [i];
00145 diffErrors [count] = newErrors [i];
00146 count++;
00147 }
00148 }
00149 objects = new Object [count];
00150 errors = new Error [count];
00151 System.arraycopy (diffObjects, 0, objects, 0, count);
00152 System.arraycopy (diffErrors, 0, errors, 0, count);
00153 list.removeAll ();
00154 text.setText ("");
00155 canvas.redraw ();
00156 for (int i=0; i<objects.length; i++) {
00157 list.add (objectName (objects [i]));
00158 }
00159 refreshLabel ();
00160 layout ();
00161 }
00162
00163 String objectName (Object object) {
00164 String string = object.toString ();
00165 int index = string.lastIndexOf ('.');
00166 if (index == -1) return string;
00167 return string.substring (index + 1, string.length ());
00168 }
00169
00170 void toggleStackTrace () {
00171 refreshObject ();
00172 layout ();
00173 }
00174
00175 void paintCanvas (Event event) {
00176 canvas.setCursor (null);
00177 int index = list.getSelectionIndex ();
00178 if (index == -1) return;
00179 GC gc = event.gc;
00180 Object object = objects [index];
00181 if (object instanceof Color) {
00182 if (((Color)object).isDisposed ()) return;
00183 gc.setBackground ((Color) object);
00184 gc.fillRectangle (canvas.getClientArea());
00185 return;
00186 }
00187 if (object instanceof Cursor) {
00188 if (((Cursor)object).isDisposed ()) return;
00189 canvas.setCursor ((Cursor) object);
00190 return;
00191 }
00192 if (object instanceof Font) {
00193 if (((Font)object).isDisposed ()) return;
00194 gc.setFont ((Font) object);
00195 FontData [] array = gc.getFont ().getFontData ();
00196 String string = "";
00197 String lf = text.getLineDelimiter ();
00198 for (int i=0; i<array.length; i++) {
00199 FontData data = array [i];
00200 String style = "NORMAL";
00201 int bits = data.getStyle ();
00202 if (bits != 0) {
00203 if ((bits & SWT.BOLD) != 0) style = "BOLD ";
00204 if ((bits & SWT.ITALIC) != 0) style += "ITALIC";
00205 }
00206 string += data.getName () + " " + data.getHeight () + " " + style + lf;
00207 }
00208 gc.drawString (string, 0, 0);
00209 return;
00210 }
00211
00212
00213
00214
00215 if (object instanceof Image) {
00216 if (((Image)object).isDisposed ()) return;
00217 gc.drawImage ((Image) object, 0, 0);
00218 return;
00219 }
00220 if (object instanceof Region) {
00221 if (((Region)object).isDisposed ()) return;
00222 String string = ((Region)object).getBounds().toString();
00223 gc.drawString (string, 0, 0);
00224 return;
00225 }
00226 }
00227
00228 void refreshObject () {
00229 int index = list.getSelectionIndex ();
00230 if (index == -1) return;
00231 if (check.getSelection ()) {
00232 ByteArrayOutputStream stream = new ByteArrayOutputStream ();
00233 PrintStream s = new PrintStream (stream);
00234 errors [index].printStackTrace (s);
00235 text.setText (stream.toString ());
00236 text.setVisible (true);
00237 canvas.setVisible (false);
00238 } else {
00239 canvas.setVisible (true);
00240 text.setVisible (false);
00241 canvas.redraw ();
00242 }
00243 }
00244
00245 void refreshAll () {
00246 oldObjects = new Object [0];
00247 oldErrors = new Error [0];
00248 refreshDifference ();
00249 oldObjects = objects;
00250 oldErrors = errors;
00251 }
00252
00253 void layout () {
00254 Rectangle rect = shell.getClientArea ();
00255
00256 int width = 0;
00257 String [] items = list.getItems ();
00258 GC gc = new GC (list);
00259 for (int i=0; i<objects.length; i++) {
00260 width = Math.max (width, gc.stringExtent (items [i]).x);
00261 }
00262 gc.dispose ();
00263 Point size1 = start.computeSize (SWT.DEFAULT, SWT.DEFAULT);
00264 Point size2 = stop.computeSize (SWT.DEFAULT, SWT.DEFAULT);
00265 Point size3 = check.computeSize (SWT.DEFAULT, SWT.DEFAULT);
00266 Point size4 = label.computeSize (SWT.DEFAULT, SWT.DEFAULT);
00267
00268 width = Math.max (size1.x, Math.max (size2.x, Math.max (size3.x, width)));
00269 width = Math.max (64, Math.max (size4.x, list.computeSize (width, SWT.DEFAULT).x));
00270
00271 start.setBounds (0, 0, width, size1.y);
00272 stop.setBounds (0, size1.y, width, size2.y);
00273 check.setBounds (0, size1.y + size2.y, width, size3.y);
00274 label.setBounds (0, rect.height - size4.y, width, size4.y);
00275
00276 int height = size1.y + size2.y + size3.y;
00277
00278 list.setBounds (0, height, width, rect.height - height - size4.y);
00279 text.setBounds (width, 0, rect.width - width, rect.height);
00280 canvas.setBounds (width, 0, rect.width - width, rect.height);
00281 }
00282
00283 public static void main (String [] args) {
00284 Display display = new Display ();
00285 Sleak sleak = new Sleak ();
00286 sleak.open ();
00287 while (!sleak.shell.isDisposed ()) {
00288 if (!display.readAndDispatch ()) display.sleep ();
00289 }
00290 display.dispose ();
00291 }
00292
00293 }