KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > terracotta > session > StuckRequestTracker


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.terracotta.session;
6
7 import java.io.File JavaDoc;
8 import java.io.IOException JavaDoc;
9 import java.io.InputStream JavaDoc;
10 import java.util.ArrayList JavaDoc;
11 import java.util.Collections JavaDoc;
12 import java.util.IdentityHashMap JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15 import java.util.TreeMap JavaDoc;
16 import java.util.Map.Entry;
17
18 import javax.servlet.http.HttpServletRequest JavaDoc;
19 import javax.servlet.http.HttpSession JavaDoc;
20
21 public class StuckRequestTracker implements RequestTracker {
22
23   private final Map JavaDoc requests = Collections.synchronizedMap(new IdentityHashMap JavaDoc());
24   private final Monitor monitor;
25
26   StuckRequestTracker(long sleepTime, long stuckThreshold, boolean dump) {
27     monitor = new Monitor(sleepTime, stuckThreshold, dump);
28   }
29
30   void start() {
31     monitor.start();
32   }
33
34   public void begin(HttpServletRequest JavaDoc request) {
35     getRequestDetail(true).begin(request);
36   }
37
38   public void recordSessionId(TerracottaRequest tr) {
39     getRequestDetail(false).recordSessionId(tr);
40   }
41
42   public boolean end() {
43     boolean done = getRequestDetail(false).end();
44     if (done) {
45       requests.remove(Thread.currentThread());
46     }
47     return done;
48   }
49
50   private RequestDetail getRequestDetail(boolean create) {
51     Thread JavaDoc t = Thread.currentThread();
52     RequestDetail rd = (RequestDetail) requests.get(t);
53     if (rd == null) {
54       if (!create) { throw new AssertionError JavaDoc("missing request detail"); }
55       rd = new RequestDetail(t);
56       requests.put(t, rd);
57     }
58
59     return rd;
60   }
61
62   private static class RequestDetail implements RequestTracker {
63     private final Thread JavaDoc thread;
64     private final List JavaDoc requests = new ArrayList JavaDoc();
65     private final long start = System.currentTimeMillis();
66     private String JavaDoc sid;
67     private int count;
68
69     RequestDetail(Thread JavaDoc thread) {
70       this.thread = thread;
71     }
72
73     public synchronized String JavaDoc toString() {
74       return "[" + thread.getName() + "], session " + sid + ", request(s) " + requests;
75     }
76
77     public synchronized void begin(HttpServletRequest JavaDoc req) {
78       count++;
79
80       StringBuffer JavaDoc buf = new StringBuffer JavaDoc(req.getRequestURI());
81
82       String JavaDoc query = req.getQueryString();
83       if (query != null && query.length() > 0) {
84         buf.append('?').append(query);
85       }
86
87       requests.add(buf.toString());
88     }
89
90     public synchronized boolean end() {
91       count--;
92       return count == 0;
93     }
94
95     public synchronized void recordSessionId(TerracottaRequest tr) {
96       if (sid == null) {
97         HttpSession JavaDoc s = tr.getSession(false);
98         if (s != null) {
99           sid = s.getId();
100         }
101       }
102     }
103   }
104
105   private static class ThreadDump {
106     private static final String JavaDoc[] CMD;
107     private static final boolean hasKillAll;
108
109     static {
110       String JavaDoc killall = findKillAll();
111
112       if (killall == null) {
113         hasKillAll = false;
114         CMD = null;
115       } else {
116         hasKillAll = true;
117         CMD = new String JavaDoc[] { killall, "-3", "java" };
118       }
119     }
120
121     private static String JavaDoc findKillAll() {
122       String JavaDoc[] variants = new String JavaDoc[] { "/usr/bin/killall", "/usr/sbin/killall", "/sbin/killall", "/bin/killall" };
123       for (int i = 0; i < variants.length; i++) {
124         String JavaDoc path = variants[i];
125         File JavaDoc f = new File JavaDoc(path);
126         if (f.exists()) { return path; }
127       }
128       return null;
129     }
130
131     static void dumpThreads() {
132       if (hasKillAll) {
133         try {
134           Process JavaDoc proc = Runtime.getRuntime().exec(CMD);
135           proc.getOutputStream().close();
136           consume(proc.getInputStream());
137           consume(proc.getErrorStream());
138           proc.waitFor();
139         } catch (Exception JavaDoc e) {
140           e.printStackTrace();
141         }
142       }
143     }
144
145     private static final byte[] buf = new byte[128];
146
147     private static void consume(InputStream JavaDoc is) throws IOException JavaDoc {
148       while (is.read(buf, 0, 128) >= 0) {
149         //
150
}
151     }
152
153   }
154
155   private class Monitor extends Thread JavaDoc {
156
157     private final long stuckThreshold;
158     private final long sleepTime;
159     private final boolean dump;
160
161     Monitor(long sleepTime, long stuckThreshold, boolean dump) {
162       this.sleepTime = sleepTime;
163       this.stuckThreshold = stuckThreshold;
164       this.dump = dump;
165       setDaemon(true);
166       setName("Session Stuck Thread Monitor");
167     }
168
169     public void run() {
170       while (true) {
171         try {
172           sleep(sleepTime);
173         } catch (InterruptedException JavaDoc e) {
174           continue;
175         }
176
177         long now = System.currentTimeMillis();
178         Map JavaDoc stuck = new TreeMap JavaDoc();
179         Object JavaDoc[] currentRequests = StuckRequestTracker.this.requests.values().toArray();
180         for (int i = 0, n = currentRequests.length; i < n; i++) {
181           RequestDetail rd = (RequestDetail) currentRequests[i];
182
183           long time = now - rd.start;
184           if (time > stuckThreshold) {
185             stuck.put(new Long JavaDoc(time), rd);
186           }
187         }
188
189         if (stuck.size() > 0) {
190           StringBuffer JavaDoc message = new StringBuffer JavaDoc("Stuck Threads (").append(stuck.size()).append(")\n");
191           Object JavaDoc[] stuckRequests = stuck.entrySet().toArray();
192           for (int i = stuckRequests.length - 1; i >= 0; i--) {
193             Map.Entry JavaDoc entry = (Entry) stuckRequests[i];
194             RequestDetail t = (RequestDetail) entry.getValue();
195             long time = ((Long JavaDoc) entry.getKey()).longValue();
196             message.append(" ").append(time).append(" ").append(t).append("\n");
197           }
198
199           System.err.println(message);
200           System.err.flush();
201           if (dump) {
202             ThreadDump.dumpThreads();
203           }
204         }
205       }
206     }
207   }
208
209 }
Popular Tags