1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.servlet;
16
17 import java.io.IOException;
18 import java.util.Queue;
19 import java.util.concurrent.Semaphore;
20 import java.util.concurrent.TimeUnit;
21
22 import javax.servlet.Filter;
23 import javax.servlet.FilterChain;
24 import javax.servlet.FilterConfig;
25 import javax.servlet.ServletContext;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31 import javax.servlet.http.HttpSession;
32
33 import org.mortbay.util.ArrayQueue;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class QoSFilter implements Filter
66 {
67 final static int __DEFAULT_MAX_PRIORITY=10;
68 final static int __DEFAULT_PASSES=10;
69 final static int __DEFAULT_WAIT_MS=50;
70 final static long __DEFAULT_TIMEOUT_MS = -1;
71
72 final static String MAX_REQUESTS_INIT_PARAM="maxRequests";
73 final static String MAX_PRIORITY_INIT_PARAM="maxPriority";
74 final static String MAX_WAIT_INIT_PARAM="waitMs";
75 final static String SUSPEND_INIT_PARAM="suspendMs";
76
77 ServletContext _context;
78 long _waitMs;
79 long _suspendMs;
80 Semaphore _passes;
81 Queue<ServletRequest>[] _queue;
82 String _suspended="QoSFilter@"+this.hashCode();
83
84 public void init(FilterConfig filterConfig)
85 {
86 _context=filterConfig.getServletContext();
87
88 int max_priority=__DEFAULT_MAX_PRIORITY;
89 if (filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM)!=null)
90 max_priority=Integer.parseInt(filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM));
91 _queue=new Queue[max_priority+1];
92 for (int p=0;p<_queue.length;p++)
93 _queue[p]=new ArrayQueue<ServletRequest>();
94
95 int passes=__DEFAULT_PASSES;
96 if (filterConfig.getInitParameter(MAX_REQUESTS_INIT_PARAM)!=null)
97 passes=Integer.parseInt(filterConfig.getInitParameter(MAX_REQUESTS_INIT_PARAM));
98 _passes=new Semaphore(passes,true);
99
100 long wait = __DEFAULT_WAIT_MS;
101 if (filterConfig.getInitParameter(MAX_WAIT_INIT_PARAM)!=null)
102 wait=Integer.parseInt(filterConfig.getInitParameter(MAX_WAIT_INIT_PARAM));
103 _waitMs=wait;
104
105 long suspend = __DEFAULT_TIMEOUT_MS;
106 if (filterConfig.getInitParameter(SUSPEND_INIT_PARAM)!=null)
107 suspend=Integer.parseInt(filterConfig.getInitParameter(SUSPEND_INIT_PARAM));
108 _suspendMs=suspend;
109 }
110
111 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
112 throws IOException, ServletException
113 {
114 boolean accepted=false;
115 try
116 {
117 if (request.isInitial() || request.getAttribute(_suspended)==null)
118 {
119 accepted=_passes.tryAcquire(_waitMs,TimeUnit.MILLISECONDS);
120 if (accepted)
121 {
122 request.setAttribute(_suspended,Boolean.FALSE);
123 }
124 else
125 {
126 request.setAttribute(_suspended,Boolean.TRUE);
127 if (_suspendMs<=0)
128 request.suspend();
129 else
130 request.suspend(_suspendMs);
131 int priority = getPriority(request);
132 _queue[priority].add(request);
133 return;
134 }
135 }
136 else
137 {
138 Boolean suspended=(Boolean)request.getAttribute(_suspended);
139
140 if (suspended.booleanValue())
141 {
142 request.setAttribute(_suspended,Boolean.FALSE);
143 if (request.isResumed())
144 {
145 _passes.acquire();
146 accepted=true;
147 }
148 else
149 {
150
151 accepted = _passes.tryAcquire(_waitMs,TimeUnit.MILLISECONDS);
152 }
153 }
154 else
155 {
156
157 _passes.acquire();
158 accepted = true;
159 }
160 }
161
162
163 if (accepted)
164 {
165 chain.doFilter(request,response);
166 }
167 else
168 {
169 ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
170 }
171
172
173
174 }
175 catch(InterruptedException e)
176 {
177 _context.log("QoS",e);
178 ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
179 }
180 finally
181 {
182 if (accepted)
183 {
184 for (int p=_queue.length;p-->0;)
185 {
186 ServletRequest r=_queue[p].poll();
187 if (r!=null)
188 {
189 r.resume();
190 break;
191 }
192 }
193 _passes.release();
194 }
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210 protected int getPriority(ServletRequest request)
211 {
212 HttpServletRequest base_request = (HttpServletRequest)request;
213 if (base_request.getUserPrincipal() != null )
214 return 2;
215 else
216 {
217 HttpSession session = base_request.getSession(false);
218 if (session!=null && !session.isNew())
219 return 1;
220 else
221 return 0;
222 }
223 }
224
225
226 public void destroy(){}
227
228 }