1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.vmpipe.support;
21
22 import java.util.Queue;
23 import java.util.concurrent.ConcurrentLinkedQueue;
24
25 import org.apache.mina.common.ByteBuffer;
26 import org.apache.mina.common.IdleStatus;
27 import org.apache.mina.common.IoSession;
28 import org.apache.mina.common.IoFilter.WriteRequest;
29 import org.apache.mina.common.support.AbstractIoFilterChain;
30
31
32
33
34
35
36
37 public class VmPipeFilterChain extends AbstractIoFilterChain {
38
39 private final Queue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
40
41 private volatile boolean flushEnabled;
42 private volatile boolean sessionOpened;
43
44 public VmPipeFilterChain(IoSession session) {
45 super(session);
46 }
47
48 public void start() {
49 flushEnabled = true;
50 flushEvents();
51 flushPendingDataQueues( (VmPipeSessionImpl) getSession() );
52 }
53
54 private void pushEvent(Event e) {
55 eventQueue.offer(e);
56 if ( flushEnabled ) {
57 flushEvents();
58 }
59 }
60
61 private void flushEvents() {
62 Event e;
63 while ((e = eventQueue.poll()) != null) {
64 fireEvent(e);
65 }
66 }
67
68 private void fireEvent(Event e) {
69 IoSession session = getSession();
70 EventType type = e.getType();
71 Object data = e.getData();
72
73 if (type == EventType.RECEIVED) {
74 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
75
76 if( sessionOpened && s.getTrafficMask().isReadable() && s.getLock().tryLock()) {
77 try {
78 int byteCount = 1;
79 if (data instanceof ByteBuffer) {
80 byteCount = ((ByteBuffer) data).remaining();
81 }
82
83 s.increaseReadBytes(byteCount);
84
85 super.fireMessageReceived(s, data);
86 } finally {
87 s.getLock().unlock();
88 }
89
90 flushPendingDataQueues( s );
91 } else {
92 s.pendingDataQueue.add(data);
93 }
94 } else if (type == EventType.WRITE) {
95 super.fireFilterWrite(session, (WriteRequest) data);
96 } else if (type == EventType.SENT) {
97 super.fireMessageSent(session, (WriteRequest) data);
98 } else if (type == EventType.EXCEPTION) {
99 super.fireExceptionCaught(session, (Throwable) data);
100 } else if (type == EventType.IDLE) {
101 super.fireSessionIdle(session, (IdleStatus) data);
102 } else if (type == EventType.OPENED) {
103 super.fireSessionOpened(session);
104 sessionOpened = true;
105 } else if (type == EventType.CREATED) {
106 super.fireSessionCreated(session);
107 } else if (type == EventType.CLOSED) {
108 super.fireSessionClosed(session);
109 } else if (type == EventType.CLOSE) {
110 super.fireFilterClose(session);
111 }
112 }
113
114 private static void flushPendingDataQueues( VmPipeSessionImpl s ) {
115 s.updateTrafficMask();
116 s.getRemoteSession().updateTrafficMask();
117 }
118
119 @Override
120 public void fireFilterClose(IoSession session) {
121 pushEvent(new Event(EventType.CLOSE, null));
122 }
123
124 @Override
125 public void fireFilterWrite(IoSession session, WriteRequest writeRequest) {
126 pushEvent(new Event(EventType.WRITE, writeRequest));
127 }
128
129 @Override
130 public void fireExceptionCaught(IoSession session, Throwable cause) {
131 pushEvent(new Event(EventType.EXCEPTION, cause));
132 }
133
134 @Override
135 public void fireMessageSent(IoSession session, WriteRequest request) {
136 pushEvent(new Event(EventType.SENT, request));
137 }
138
139 @Override
140 public void fireSessionClosed(IoSession session) {
141 pushEvent(new Event(EventType.CLOSED, null));
142 }
143
144 @Override
145 public void fireSessionCreated(IoSession session) {
146 pushEvent(new Event(EventType.CREATED, null));
147 }
148
149 @Override
150 public void fireSessionIdle(IoSession session, IdleStatus status) {
151 pushEvent(new Event(EventType.IDLE, status));
152 }
153
154 @Override
155 public void fireSessionOpened(IoSession session) {
156 pushEvent(new Event(EventType.OPENED, null));
157 }
158
159 @Override
160 public void fireMessageReceived(IoSession session, Object message) {
161 pushEvent(new Event(EventType.RECEIVED, message));
162 }
163
164 @Override
165 protected void doWrite(IoSession session, WriteRequest writeRequest) {
166 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
167 if (s.isConnected()) {
168 if ( s.getTrafficMask().isWritable() && s.getLock().tryLock()) {
169 try {
170 Object message = writeRequest.getMessage();
171
172 int byteCount = 1;
173 Object messageCopy = message;
174 if (message instanceof ByteBuffer) {
175 ByteBuffer rb = (ByteBuffer) message;
176 rb.mark();
177 byteCount = rb.remaining();
178 ByteBuffer wb = ByteBuffer.allocate(rb.remaining());
179 wb.put(rb);
180 wb.flip();
181 rb.reset();
182 messageCopy = wb;
183 }
184
185
186
187 s.increaseScheduledWriteBytes(byteCount);
188 s.increaseScheduledWriteRequests();
189
190 s.increaseWrittenBytes(byteCount);
191 s.increaseWrittenMessages();
192
193 s.getRemoteSession().getFilterChain().fireMessageReceived(
194 s.getRemoteSession(), messageCopy);
195 s.getFilterChain().fireMessageSent(s, writeRequest);
196 } finally {
197 s.getLock().unlock();
198 }
199
200 flushPendingDataQueues( s );
201 } else {
202 s.pendingDataQueue.add(writeRequest);
203 }
204 } else {
205 writeRequest.getFuture().setWritten(false);
206 }
207 }
208
209 @Override
210 protected void doClose(IoSession session) {
211 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
212
213 try {
214 s.getLock().lock();
215
216 if (!session.getCloseFuture().isClosed()) {
217 s.getServiceListeners().fireSessionDestroyed(s);
218 s.getRemoteSession().close();
219 }
220 } finally {
221 s.getLock().unlock();
222 }
223 }
224
225
226 private static class EventType {
227 public static final EventType CREATED = new EventType("CREATED");
228
229 public static final EventType OPENED = new EventType("OPENED");
230
231 public static final EventType CLOSED = new EventType("CLOSED");
232
233 public static final EventType RECEIVED = new EventType("RECEIVED");
234
235 public static final EventType SENT = new EventType("SENT");
236
237 public static final EventType IDLE = new EventType("IDLE");
238
239 public static final EventType EXCEPTION = new EventType("EXCEPTION");
240
241 public static final EventType WRITE = new EventType("WRITE");
242
243 public static final EventType CLOSE = new EventType("CLOSE");
244
245 private final String value;
246
247 private EventType(String value) {
248 this.value = value;
249 }
250
251 @Override
252 public String toString() {
253 return value;
254 }
255 }
256
257 private static class Event {
258 private final EventType type;
259
260 private final Object data;
261
262 private Event(EventType type, Object data) {
263 this.type = type;
264 this.data = data;
265 }
266
267 public Object getData() {
268 return data;
269 }
270
271 public EventType getType() {
272 return type;
273 }
274 }
275 }