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 lastReadTime = System.currentTimeMillis();
372 }
373
374 public void increaseWrittenMessages() {
375 writtenMessages++;
376 lastWriteTime = System.currentTimeMillis();
377 scheduledWriteRequests.decrementAndGet();
378 }
379
380 public void increaseScheduledWriteBytes(int increment) {
381 scheduledWriteBytes.addAndGet(increment);
382 }
383
384 public void increaseScheduledWriteRequests() {
385 scheduledWriteRequests.incrementAndGet();
386 }
387
388 public long getCreationTime() {
389 return creationTime;
390 }
391
392 public long getLastIoTime() {
393 return Math.max(lastReadTime, lastWriteTime);
394 }
395
396 public long getLastReadTime() {
397 return lastReadTime;
398 }
399
400 public long getLastWriteTime() {
401 return lastWriteTime;
402 }
403
404 public boolean isIdle(IdleStatus status) {
405 if (status == IdleStatus.BOTH_IDLE)
406 return idleCountForBoth > 0;
407
408 if (status == IdleStatus.READER_IDLE)
409 return idleCountForRead > 0;
410
411 if (status == IdleStatus.WRITER_IDLE)
412 return idleCountForWrite > 0;
413
414 throw new IllegalArgumentException("Unknown idle status: " + status);
415 }
416
417 public int getIdleCount(IdleStatus status) {
418 if (status == IdleStatus.BOTH_IDLE)
419 return idleCountForBoth;
420
421 if (status == IdleStatus.READER_IDLE)
422 return idleCountForRead;
423
424 if (status == IdleStatus.WRITER_IDLE)
425 return idleCountForWrite;
426
427 throw new IllegalArgumentException("Unknown idle status: " + status);
428 }
429
430 public long getLastIdleTime(IdleStatus status) {
431 if (status == IdleStatus.BOTH_IDLE)
432 return lastIdleTimeForBoth;
433
434 if (status == IdleStatus.READER_IDLE)
435 return lastIdleTimeForRead;
436
437 if (status == IdleStatus.WRITER_IDLE)
438 return lastIdleTimeForWrite;
439
440 throw new IllegalArgumentException("Unknown idle status: " + status);
441 }
442
443 public void increaseIdleCount(IdleStatus status) {
444 if (status == IdleStatus.BOTH_IDLE) {
445 idleCountForBoth++;
446 lastIdleTimeForBoth = System.currentTimeMillis();
447 } else if (status == IdleStatus.READER_IDLE) {
448 idleCountForRead++;
449 lastIdleTimeForRead = System.currentTimeMillis();
450 } else if (status == IdleStatus.WRITER_IDLE) {
451 idleCountForWrite++;
452 lastIdleTimeForWrite = System.currentTimeMillis();
453 } else
454 throw new IllegalArgumentException("Unknown idle status: " + status);
455 }
456
457 public String toString() {
458 return "(" + getTransportType() + ", R: " + getRemoteAddress()
459 + ", L: " + getLocalAddress() + ", S: " + getServiceAddress()
460 + ')';
461 }
462 }