1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.common.support;
21
22 import java.net.SocketAddress;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.apache.mina.common.CloseFuture;
29 import org.apache.mina.common.IdleStatus;
30 import org.apache.mina.common.IoFuture;
31 import org.apache.mina.common.IoFutureListener;
32 import org.apache.mina.common.IoService;
33 import org.apache.mina.common.IoSession;
34 import org.apache.mina.common.TrafficMask;
35 import org.apache.mina.common.WriteFuture;
36 import org.apache.mina.common.IoFilter.WriteRequest;
37
38 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
39 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
40
41
42
43
44
45
46
47 public abstract class BaseIoSession implements IoSession {
48
49 private static final IoFutureListener SCHEDULED_COUNTER_RESETTER =
50 new IoFutureListener() {
51 public void operationComplete(IoFuture future) {
52 BaseIoSession s = (BaseIoSession) future.getSession();
53 s.scheduledWriteBytes.set(0);
54 s.scheduledWriteRequests.set(0);
55 }
56 };
57
58 private final Map attributes = new HashMap(8);
59
60 private final long creationTime;
61
62
63
64
65 private final CloseFuture closeFuture = new DefaultCloseFuture(this);
66
67 private final AtomicBoolean scheduledForFlush = new AtomicBoolean();
68
69 private final AtomicInteger scheduledWriteBytes = new AtomicInteger();
70
71 private final AtomicInteger scheduledWriteRequests = new AtomicInteger();
72
73 private boolean closing;
74
75
76 private int idleTimeForRead;
77
78 private int idleTimeForWrite;
79
80 private int idleTimeForBoth;
81
82 private int writeTimeout;
83
84 private TrafficMask trafficMask = TrafficMask.ALL;
85
86
87 private long readBytes;
88
89 private long writtenBytes;
90
91 private long readMessages;
92
93 private long writtenMessages;
94
95 private long lastReadTime;
96
97 private long lastWriteTime;
98
99 private int idleCountForBoth;
100
101 private int idleCountForRead;
102
103 private int idleCountForWrite;
104
105 private long lastIdleTimeForBoth;
106
107 private long lastIdleTimeForRead;
108
109 private long lastIdleTimeForWrite;
110
111 protected BaseIoSession() {
112 creationTime = lastReadTime = lastWriteTime = lastIdleTimeForBoth = lastIdleTimeForRead = lastIdleTimeForWrite = System
113 .currentTimeMillis();
114 closeFuture.addListener(SCHEDULED_COUNTER_RESETTER);
115 }
116
117 public boolean isConnected() {
118 return !closeFuture.isClosed();
119 }
120
121 public synchronized boolean isClosing() {
122 return closing || closeFuture.isClosed();
123 }
124
125 public CloseFuture getCloseFuture() {
126 return closeFuture;
127 }
128
129 public boolean isScheduledForFlush() {
130 return scheduledForFlush.get();
131 }
132
133 public boolean setScheduledForFlush(boolean flag) {
134 if (flag) {
135 return scheduledForFlush.compareAndSet(false, true);
136 } else {
137 scheduledForFlush.set(false);
138 return true;
139 }
140 }
141
142 public CloseFuture close() {
143 synchronized (this) {
144 if (isClosing()) {
145 return closeFuture;
146 } else {
147 closing = true;
148 }
149 }
150
151 close0();
152 return closeFuture;
153 }
154
155
156
157
158
159
160 protected void close0() {
161 closeFuture.setClosed();
162 }
163
164 public WriteFuture write(Object message) {
165 return write(message, null);
166 }
167
168 public WriteFuture write(Object message, SocketAddress remoteAddress) {
169 synchronized (this) {
170 if (isClosing() || !isConnected()) {
171 return DefaultWriteFuture.newNotWrittenFuture(this);
172 }
173 }
174
175 WriteFuture future = new DefaultWriteFuture(this);
176 write0(new WriteRequest(message, future, remoteAddress));
177
178 return future;
179 }
180
181
182
183
184
185
186
187
188 protected void write0(WriteRequest writeRequest) {
189 writeRequest.getFuture().setWritten(false);
190 }
191
192 public Object getAttachment() {
193 synchronized (attributes) {
194 return attributes.get("");
195 }
196 }
197
198 public Object setAttachment(Object attachment) {
199 synchronized (attributes) {
200 return attributes.put("", attachment);
201 }
202 }
203
204 public Object getAttribute(String key) {
205 synchronized (attributes) {
206 return attributes.get(key);
207 }
208 }
209
210 public Object setAttribute(String key, Object value) {
211 synchronized (attributes) {
212 return attributes.put(key, value);
213 }
214 }
215
216 public Object setAttribute(String key) {
217 return setAttribute(key, Boolean.TRUE);
218 }
219
220 public Object removeAttribute(String key) {
221 synchronized (attributes) {
222 return attributes.remove(key);
223 }
224 }
225
226 public boolean containsAttribute(String key) {
227 return getAttribute(key) != null;
228 }
229
230 public Set getAttributeKeys() {
231 synchronized (attributes) {
232 return new HashSet(attributes.keySet());
233 }
234 }
235
236 public int getIdleTime(IdleStatus status) {
237 if (status == IdleStatus.BOTH_IDLE)
238 return idleTimeForBoth;
239
240 if (status == IdleStatus.READER_IDLE)
241 return idleTimeForRead;
242
243 if (status == IdleStatus.WRITER_IDLE)
244 return idleTimeForWrite;
245
246 throw new IllegalArgumentException("Unknown idle status: " + status);
247 }
248
249 public long getIdleTimeInMillis(IdleStatus status) {
250 return getIdleTime(status) * 1000L;
251 }
252
253 public void setIdleTime(IdleStatus status, int idleTime) {
254 if (idleTime < 0)
255 throw new IllegalArgumentException("Illegal idle time: " + idleTime);
256
257 if (status == IdleStatus.BOTH_IDLE)
258 idleTimeForBoth = idleTime;
259 else if (status == IdleStatus.READER_IDLE)
260 idleTimeForRead = idleTime;
261 else if (status == IdleStatus.WRITER_IDLE)
262 idleTimeForWrite = idleTime;
263 else
264 throw new IllegalArgumentException("Unknown idle status: " + status);
265 }
266
267 public int getWriteTimeout() {
268 return writeTimeout;
269 }
270
271 public long getWriteTimeoutInMillis() {
272 return writeTimeout * 1000L;
273 }
274
275 public void setWriteTimeout(int writeTimeout) {
276 if (writeTimeout < 0)
277 throw new IllegalArgumentException("Illegal write timeout: "
278 + writeTimeout);
279 this.writeTimeout = writeTimeout;
280 }
281
282 public TrafficMask getTrafficMask() {
283 return trafficMask;
284 }
285
286 public void setTrafficMask(TrafficMask trafficMask) {
287 if (trafficMask == null) {
288 throw new NullPointerException("trafficMask");
289 }
290
291 if (this.trafficMask == trafficMask) {
292 return;
293 }
294
295 this.trafficMask = trafficMask;
296 updateTrafficMask();
297 }
298
299 public void suspendRead() {
300 setTrafficMask(getTrafficMask().and(TrafficMask.READ.not()));
301 }
302
303 public void suspendWrite() {
304 setTrafficMask(getTrafficMask().and(TrafficMask.WRITE.not()));
305 }
306
307 public void resumeRead() {
308 setTrafficMask(getTrafficMask().or(TrafficMask.READ));
309 }
310
311 public void resumeWrite() {
312 setTrafficMask(getTrafficMask().or(TrafficMask.WRITE));
313 }
314
315
316
317
318
319 protected abstract void updateTrafficMask();
320
321 public long getReadBytes() {
322 return readBytes;
323 }
324
325 public long getWrittenBytes() {
326 return writtenBytes;
327 }
328
329 public long getWrittenWriteRequests() {
330 return writtenMessages;
331 }
332
333 public long getReadMessages() {
334 return readMessages;
335 }
336
337 public long getWrittenMessages() {
338 return writtenMessages;
339 }
340
341 public int getScheduledWriteBytes() {
342 return scheduledWriteBytes.get();
343 }
344
345 public int getScheduledWriteRequests() {
346 return scheduledWriteRequests.get();
347 }
348
349 public void increaseReadBytes(int increment) {
350 if (increment > 0) {
351 readBytes += increment;
352 lastReadTime = System.currentTimeMillis();
353 idleCountForBoth = 0;
354 idleCountForRead = 0;
355 }
356 }
357
358 public void increaseWrittenBytes(int increment) {
359 if (increment > 0) {
360 writtenBytes += increment;
361 lastWriteTime = System.currentTimeMillis();
362 idleCountForBoth = 0;
363 idleCountForWrite = 0;
364
365 scheduledWriteBytes.addAndGet(-increment);
366 }
367 }
368
369 public void increaseReadMessages() {
370 readMessages++;
371 }
372
373 public void increaseWrittenMessages() {
374 writtenMessages++;
375 scheduledWriteRequests.decrementAndGet();
376 }
377
378 public void increaseScheduledWriteBytes(int increment) {
379 scheduledWriteBytes.addAndGet(increment);
380 }
381
382 public void increaseScheduledWriteRequests() {
383 scheduledWriteRequests.incrementAndGet();
384 }
385
386 public long getCreationTime() {
387 return creationTime;
388 }
389
390 public long getLastIoTime() {
391 return Math.max(lastReadTime, lastWriteTime);
392 }
393
394 public long getLastReadTime() {
395 return lastReadTime;
396 }
397
398 public long getLastWriteTime() {
399 return lastWriteTime;
400 }
401
402 public boolean isIdle(IdleStatus status) {
403 if (status == IdleStatus.BOTH_IDLE)
404 return idleCountForBoth > 0;
405
406 if (status == IdleStatus.READER_IDLE)
407 return idleCountForRead > 0;
408
409 if (status == IdleStatus.WRITER_IDLE)
410 return idleCountForWrite > 0;
411
412 throw new IllegalArgumentException("Unknown idle status: " + status);
413 }
414
415 public int getIdleCount(IdleStatus status) {
416 if (status == IdleStatus.BOTH_IDLE)
417 return idleCountForBoth;
418
419 if (status == IdleStatus.READER_IDLE)
420 return idleCountForRead;
421
422 if (status == IdleStatus.WRITER_IDLE)
423 return idleCountForWrite;
424
425 throw new IllegalArgumentException("Unknown idle status: " + status);
426 }
427
428 public long getLastIdleTime(IdleStatus status) {
429 if (status == IdleStatus.BOTH_IDLE)
430 return lastIdleTimeForBoth;
431
432 if (status == IdleStatus.READER_IDLE)
433 return lastIdleTimeForRead;
434
435 if (status == IdleStatus.WRITER_IDLE)
436 return lastIdleTimeForWrite;
437
438 throw new IllegalArgumentException("Unknown idle status: " + status);
439 }
440
441 public void increaseIdleCount(IdleStatus status) {
442 if (status == IdleStatus.BOTH_IDLE) {
443 idleCountForBoth++;
444 lastIdleTimeForBoth = System.currentTimeMillis();
445 } else if (status == IdleStatus.READER_IDLE) {
446 idleCountForRead++;
447 lastIdleTimeForRead = System.currentTimeMillis();
448 } else if (status == IdleStatus.WRITER_IDLE) {
449 idleCountForWrite++;
450 lastIdleTimeForWrite = System.currentTimeMillis();
451 } else
452 throw new IllegalArgumentException("Unknown idle status: " + status);
453 }
454
455 public String toString() {
456 return "(" + getTransportType() + ", R: " + getRemoteAddress()
457 + ", L: " + getLocalAddress() + ", S: " + getServiceAddress()
458 + ')';
459 }
460 }