1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.filter;
21
22 import java.util.Iterator;
23 import java.util.List;
24
25 import org.apache.mina.common.ByteBuffer;
26 import org.apache.mina.common.DefaultIoFilterChainBuilder;
27 import org.apache.mina.common.IoFilterAdapter;
28 import org.apache.mina.common.IoFilterChain;
29 import org.apache.mina.common.IoSession;
30 import org.apache.mina.filter.executor.ExecutorFilter;
31
32
33
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 public class ReadThrottleFilterBuilder {
62 public static final String COUNTER = ReadThrottleFilterBuilder.class
63 .getName()
64 + ".counter";
65
66 public static final String SUSPENDED_READS = ReadThrottleFilterBuilder.class
67 .getName()
68 + ".suspendedReads";
69
70 private volatile int maximumConnectionBufferSize = 1024 * 1024;
71
72
73
74
75
76
77
78
79 public void setMaximumConnectionBufferSize(int maximumConnectionBufferSize) {
80 this.maximumConnectionBufferSize = maximumConnectionBufferSize;
81 }
82
83
84
85
86
87
88
89 public void attach(IoFilterChain chain) {
90 String name = getThreadPoolFilterEntryName(chain.getAll());
91
92 chain.addBefore(name, getClass().getName() + ".add", new Add());
93 chain.addAfter(name, getClass().getName() + ".release", new Release());
94 }
95
96
97
98
99
100
101
102 public void attach(DefaultIoFilterChainBuilder builder) {
103 String name = getThreadPoolFilterEntryName(builder.getAll());
104
105 builder.addBefore(name, getClass().getName() + ".add", new Add());
106 builder
107 .addAfter(name, getClass().getName() + ".release",
108 new Release());
109 }
110
111 private String getThreadPoolFilterEntryName(List entries) {
112 Iterator i = entries.iterator();
113
114 while (i.hasNext()) {
115 IoFilterChain.Entry entry = (IoFilterChain.Entry) i.next();
116
117 if (entry.getFilter().getClass().isAssignableFrom(
118 ExecutorFilter.class)) {
119 return entry.getName();
120 }
121 }
122
123 throw new IllegalStateException(
124 "Chain does not contain a ExecutorFilter");
125 }
126
127 private void add(IoSession session, int size) {
128 synchronized (session) {
129 int counter = getCounter(session) + size;
130
131 session.setAttribute(COUNTER, new Integer(counter));
132
133 if (counter >= maximumConnectionBufferSize
134 && session.getTrafficMask().isReadable()) {
135 session.suspendRead();
136 session.setAttribute(SUSPENDED_READS);
137 }
138 }
139 }
140
141 private void release(IoSession session, int size) {
142 synchronized (session) {
143 int counter = Math.max(0, getCounter(session) - size);
144
145 session.setAttribute(COUNTER, new Integer(counter));
146
147 if (counter < maximumConnectionBufferSize
148 && isSuspendedReads(session)) {
149 session.resumeRead();
150 session.removeAttribute(SUSPENDED_READS);
151 }
152
153 }
154 }
155
156 private boolean isSuspendedReads(IoSession session) {
157 Boolean flag = (Boolean) session.getAttribute(SUSPENDED_READS);
158
159 return null != flag && flag.booleanValue();
160 }
161
162 private int getCounter(IoSession session) {
163 Integer i = (Integer) session.getAttribute(COUNTER);
164 return null == i ? 0 : i.intValue();
165 }
166
167 private class Add extends IoFilterAdapter {
168 public void messageReceived(NextFilter nextFilter, IoSession session,
169 Object message) throws Exception {
170 if (message instanceof ByteBuffer) {
171 add(session, ((ByteBuffer) message).remaining());
172 }
173
174 nextFilter.messageReceived(session, message);
175 }
176 }
177
178 private class Release extends IoFilterAdapter {
179 public void messageReceived(NextFilter nextFilter, IoSession session,
180 Object message) throws Exception {
181 if (message instanceof ByteBuffer) {
182 release(session, ((ByteBuffer) message).remaining());
183 }
184
185 nextFilter.messageReceived(session, message);
186 }
187 }
188 }