1 package org.mortbay.servlet;
2
3 import java.io.IOException;
4 import java.util.Queue;
5 import java.util.concurrent.Semaphore;
6 import java.util.concurrent.TimeUnit;
7
8 import javax.servlet.Filter;
9 import javax.servlet.FilterChain;
10 import javax.servlet.FilterConfig;
11 import javax.servlet.ServletContext;
12 import javax.servlet.ServletException;
13 import javax.servlet.ServletRequest;
14 import javax.servlet.ServletResponse;
15 import javax.servlet.http.HttpServletResponse;
16
17 import org.mortbay.util.ArrayQueue;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public class QoSFilter implements Filter
34 {
35 final static int __DEFAULT_MAX_PRIORITY=10;
36 final static int __DEFAULT_PASSES=10;
37 final static int __DEFAULT_WAIT_MS=50;
38
39 ServletContext _context;
40 long _waitMs;
41 Semaphore _passes;
42 Queue<ServletRequest>[] _queue;
43 String _suspended="QoSFilter@"+this.hashCode();
44
45 public void init(FilterConfig filterConfig)
46 {
47 _context=filterConfig.getServletContext();
48
49 int max_priority=__DEFAULT_MAX_PRIORITY;
50 if (filterConfig.getInitParameter("maxPriority")!=null)
51 max_priority=Integer.parseInt(filterConfig.getInitParameter("maxPriority"));
52 _queue=new Queue[max_priority+1];
53 for (int p=0;p<_queue.length;p++)
54 _queue[p]=new ArrayQueue<ServletRequest>();
55
56 int passes=__DEFAULT_PASSES;
57 if (filterConfig.getInitParameter("maxRequests")!=null)
58 passes=Integer.parseInt(filterConfig.getInitParameter("maxRequests"));
59 _passes=new Semaphore(passes,true);
60
61 long wait = __DEFAULT_WAIT_MS;
62 if (filterConfig.getInitParameter("waitMs")!=null)
63 wait=Integer.parseInt(filterConfig.getInitParameter("waitMs"));
64 _waitMs=wait;
65 }
66
67 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
68 throws IOException, ServletException
69 {
70 boolean accepted=false;
71
72 try
73 {
74 if (request.isInitial() || request.getAttribute(_suspended)==null)
75 {
76 accepted=_passes.tryAcquire(_waitMs,TimeUnit.MILLISECONDS);
77
78 if (accepted)
79 {
80 request.setAttribute(_suspended,Boolean.FALSE);
81 }
82 else
83 {
84 request.setAttribute(_suspended,Boolean.TRUE);
85 request.suspend();
86 int priority = getPriority(request);
87 _queue[priority].add(request);
88 return;
89 }
90 }
91 else
92 {
93 Boolean suspended=(Boolean)request.getAttribute(_suspended);
94
95 if (suspended.booleanValue())
96 {
97 request.setAttribute(_suspended,Boolean.FALSE);
98 if (request.isResumed())
99 {
100 _passes.acquire();
101 accepted=true;
102 }
103 else
104 {
105
106 accepted = _passes.tryAcquire(_waitMs,TimeUnit.MILLISECONDS);
107 }
108 }
109 else
110 {
111
112 _passes.acquire();
113 accepted = true;
114 }
115 }
116
117
118 if (accepted)
119 chain.doFilter(request,response);
120 else
121 ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
122
123
124
125 }
126 catch(InterruptedException e)
127 {
128 _context.log("QoS",e);
129 ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
130 }
131 finally
132 {
133 if (accepted)
134 {
135 for (int p=_queue.length;p-->0;)
136 {
137 ServletRequest r=_queue[p].poll();
138 if (r!=null)
139 {
140 r.resume();
141 break;
142 }
143 }
144 _passes.release();
145 }
146 }
147 }
148
149
150
151
152
153 protected int getPriority(ServletRequest request)
154 {
155 return 0;
156 }
157
158
159 public void destroy(){}
160
161 }