001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.common;
021:
022: import java.net.SocketAddress;
023: import java.util.Set;
024:
025: /**
026: * A handle which represents connection between two end-points regardless of
027: * transport types.
028: * <p/>
029: * {@link IoSession} provides user-defined attributes. User-defined attributes
030: * are application-specific data which is associated with a session.
031: * It often contains objects that represents the state of a higher-level protocol
032: * and becomes a way to exchange data between filters and handlers.
033: * <p/>
034: * <h3>Adjusting Transport Type Specific Properties</h3>
035: * <p/>
036: * You can simply downcast the session to an appropriate subclass.
037: * </p>
038: * <p/>
039: * <h3>Thread Safety</h3>
040: * <p/>
041: * {@link IoSession} is thread-safe. But please note that performing
042: * more than one {@link #write(Object)} calls at the same time will
043: * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)}
044: * is executed simultaneously, and therefore you have to make sure the
045: * {@link IoFilter} implementations you're using are thread-safe, too.
046: * </p>
047: * <p/>
048: * <h3>Equality of Sessions</h3>
049: * {@link #equals(Object)} and {@link #hashCode()} shall not be overriden
050: * to the default behavior that is defined in {@link Object}.
051: *
052: * @author The Apache MINA Project (dev@mina.apache.org)
053: * @version $Rev: 601679 $, $Date: 2007-12-06 03:13:21 -0700 (Thu, 06 Dec 2007) $
054: */
055: public interface IoSession {
056:
057: /**
058: * Returns a unique identifier of this session. Every session has its own
059: * ID which is different from each other.
060: */
061: long getId();
062:
063: /**
064: * Returns the {@link IoService} which provides I/O service to this session.
065: */
066: IoService getService();
067:
068: /**
069: * Returns the {@link IoHandler} which handles this session.
070: */
071: IoHandler getHandler();
072:
073: /**
074: * Returns the configuration of this session.
075: */
076: IoSessionConfig getConfig();
077:
078: /**
079: * Returns the filter chain that only affects this session.
080: */
081: IoFilterChain getFilterChain();
082:
083: /**
084: * Returns the {@link TransportMetadata} that this session runs on.
085: */
086: TransportMetadata getTransportMetadata();
087:
088: /**
089: * Returns a {@link ReadFuture} which is notified when a new message is
090: * received, the connection is closed or an exception is caught. This
091: * operation is especially useful when you implement a client application.
092: * However, please note that this operation is disabled by default and
093: * throw {@link IllegalStateException} because all received events must be
094: * queued somewhere to support this operation, possibly leading to memory
095: * leak. This means you have to keep calling {@link #read()} once you
096: * enabled this operation. To enable this operation, please call
097: * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>.
098: *
099: * @throws IllegalStateException if
100: * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation}
101: * option has not been enabled.
102: */
103: ReadFuture read();
104:
105: /**
106: * Writes the specified <code>message</code> to remote peer. This
107: * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)}
108: * will be invoked when the message is actually sent to remote peer.
109: * You can also wait for the returned {@link WriteFuture} if you want
110: * to wait for the message actually written.
111: */
112: WriteFuture write(Object message);
113:
114: /**
115: * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>.
116: * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)}
117: * will be invoked when the message is actually sent to remote peer. You can
118: * also wait for the returned {@link WriteFuture} if you want to wait for
119: * the message actually written.
120: * <p>
121: * When you implement a client that receives a broadcast message from a server
122: * such as DHCP server, the client might need to send a response message for the
123: * broadcast message the server sent. Because the remote address of the session
124: * is not the address of the server in case of broadcasting, there should be a
125: * way to specify the destination when you write the response message.
126: * This interface provides {@link #write(Object, SocketAddress)} method so you
127: * can specify the destination.
128: *
129: * @param destination <tt>null</tt> if you want the message sent to the
130: * default remote address
131: *
132: * @throws UnsupportedOperationException if this operation is not supported
133: */
134: WriteFuture write(Object message, SocketAddress destination);
135:
136: /**
137: * Closes this session immediately. This operation is asynchronous.
138: * Wait for the returned {@link CloseFuture} if you want to wait for
139: * the session actually closed.
140: */
141: CloseFuture close();
142:
143: /**
144: * Closes this session after all queued write requests are flushed.
145: * This operation is asynchronous. Wait for the returned {@link CloseFuture}
146: * if you want to wait for the session actually closed.
147: */
148: CloseFuture closeOnFlush();
149:
150: /**
151: * Closes this session immediately or after all queued write requests
152: * are flushed. This operation is asynchronous. Wait for the returned
153: * {@link CloseFuture} if you want to wait for the session actually closed.
154: *
155: * @param immediately {@code true} to close this session immediately
156: * (i.e. {@link #close()}).
157: * {@code false} to close this session after all queued
158: * write requests are flushed (i.e. {@link #closeOnFlush()}).
159: */
160: CloseFuture close(boolean immediately);
161:
162: /**
163: * Returns an attachment of this session.
164: * This method is identical with <tt>getAttribute( "" )</tt>.
165: *
166: * @deprecated Use {@link #getAttribute(Object)} instead.
167: */
168: @Deprecated
169: Object getAttachment();
170:
171: /**
172: * Sets an attachment of this session.
173: * This method is identical with <tt>setAttribute( "", attachment )</tt>.
174: *
175: * @return Old attachment. <tt>null</tt> if it is new.
176: * @deprecated Use {@link #setAttribute(Object, Object)} instead.
177: */
178: @Deprecated
179: Object setAttachment(Object attachment);
180:
181: /**
182: * Returns the value of the user-defined attribute of this session.
183: *
184: * @param key the key of the attribute
185: * @return <tt>null</tt> if there is no attribute with the specified key
186: */
187: Object getAttribute(Object key);
188:
189: /**
190: * Returns the value of user defined attribute associated with the
191: * specified key. If there's no such attribute, the specified default
192: * value is associated with the specified key, and the default value is
193: * returned. This method is same with the following code except that the
194: * operation is performed atomically.
195: * <pre>
196: * if (containsAttribute(key)) {
197: * return getAttribute(key);
198: * } else {
199: * setAttribute(key, defaultValue);
200: * return defaultValue;
201: * }
202: * </pre>
203: */
204: Object getAttribute(Object key, Object defaultValue);
205:
206: /**
207: * Sets a user-defined attribute.
208: *
209: * @param key the key of the attribute
210: * @param value the value of the attribute
211: * @return The old value of the attribute. <tt>null</tt> if it is new.
212: */
213: Object setAttribute(Object key, Object value);
214:
215: /**
216: * Sets a user defined attribute without a value. This is useful when
217: * you just want to put a 'mark' attribute. Its value is set to
218: * {@link Boolean#TRUE}.
219: *
220: * @param key the key of the attribute
221: * @return The old value of the attribute. <tt>null</tt> if it is new.
222: */
223: Object setAttribute(Object key);
224:
225: /**
226: * Sets a user defined attribute if the attribute with the specified key
227: * is not set yet. This method is same with the following code except
228: * that the operation is performed atomically.
229: * <pre>
230: * if (containsAttribute(key)) {
231: * return getAttribute(key);
232: * } else {
233: * return setAttribute(key, value);
234: * }
235: * </pre>
236: */
237: Object setAttributeIfAbsent(Object key, Object value);
238:
239: /**
240: * Sets a user defined attribute without a value if the attribute with
241: * the specified key is not set yet. This is useful when you just want to
242: * put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}.
243: * This method is same with the following code except that the operation
244: * is performed atomically.
245: * <pre>
246: * if (containsAttribute(key)) {
247: * return getAttribute(key); // might not always be Boolean.TRUE.
248: * } else {
249: * return setAttribute(key);
250: * }
251: * </pre>
252: */
253: Object setAttributeIfAbsent(Object key);
254:
255: /**
256: * Removes a user-defined attribute with the specified key.
257: *
258: * @return The old value of the attribute. <tt>null</tt> if not found.
259: */
260: Object removeAttribute(Object key);
261:
262: /**
263: * Removes a user defined attribute with the specified key if the current
264: * attribute value is equal to the specified value. This method is same
265: * with the following code except that the operation is performed
266: * atomically.
267: * <pre>
268: * if (containsAttribute(key) && getAttribute(key).equals(value)) {
269: * removeAttribute(key);
270: * return true;
271: * } else {
272: * return false;
273: * }
274: * </pre>
275: */
276: boolean removeAttribute(Object key, Object value);
277:
278: /**
279: * Replaces a user defined attribute with the specified key if the
280: * value of the attribute is equals to the specified old value.
281: * This method is same with the following code except that the operation
282: * is performed atomically.
283: * <pre>
284: * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
285: * setAttribute(key, newValue);
286: * return true;
287: * } else {
288: * return false;
289: * }
290: * </pre>
291: */
292: boolean replaceAttribute(Object key, Object oldValue,
293: Object newValue);
294:
295: /**
296: * Returns <tt>true</tt> if this session contains the attribute with
297: * the specified <tt>key</tt>.
298: */
299: boolean containsAttribute(Object key);
300:
301: /**
302: * Returns the set of keys of all user-defined attributes.
303: */
304: Set<Object> getAttributeKeys();
305:
306: /**
307: * Returns <code>true</code> if this session is connected with remote peer.
308: */
309: boolean isConnected();
310:
311: /**
312: * Returns <code>true</tt> if and only if this session is being closed
313: * (but not disconnected yet) or is closed.
314: */
315: boolean isClosing();
316:
317: /**
318: * Returns the {@link CloseFuture} of this session. This method returns
319: * the same instance whenever user calls it.
320: */
321: CloseFuture getCloseFuture();
322:
323: /**
324: * Returns the socket address of remote peer.
325: */
326: SocketAddress getRemoteAddress();
327:
328: /**
329: * Returns the socket address of local machine which is associated with this
330: * session.
331: */
332: SocketAddress getLocalAddress();
333:
334: /**
335: * Returns the socket address of the {@link IoService} listens to to manage
336: * this session. If this session is managed by {@link IoAcceptor}, it
337: * returns the {@link SocketAddress} which is specified as a parameter of
338: * {@link IoAcceptor#bind()}. If this session is managed by
339: * {@link IoConnector}, this method returns the same address with
340: * that of {@link #getRemoteAddress()}.
341: */
342: SocketAddress getServiceAddress();
343:
344: /**
345: * Returns the current {@link TrafficMask} of this session.
346: */
347: TrafficMask getTrafficMask();
348:
349: /**
350: * Sets the {@link TrafficMask} of this session which will result
351: * the parent {@link IoService} to start to control the traffic
352: * of this session immediately.
353: */
354: void setTrafficMask(TrafficMask trafficMask);
355:
356: /**
357: * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
358: * suspends read operations for this session.
359: */
360: void suspendRead();
361:
362: /**
363: * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
364: * suspends write operations for this session.
365: */
366: void suspendWrite();
367:
368: /**
369: * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
370: * resumes read operations for this session.
371: */
372: void resumeRead();
373:
374: /**
375: * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
376: * resumes write operations for this session.
377: */
378: void resumeWrite();
379:
380: /**
381: * Returns the total number of bytes which were read from this session.
382: */
383: long getReadBytes();
384:
385: /**
386: * Returns the total number of bytes which were written to this session.
387: */
388: long getWrittenBytes();
389:
390: /**
391: * Returns the total number of messages which were read and decoded from this session.
392: */
393: long getReadMessages();
394:
395: /**
396: * Returns the total number of messages which were written and encoded by this session.
397: */
398: long getWrittenMessages();
399:
400: /**
401: * Returns the number of read bytes per second.
402: */
403: double getReadBytesThroughput();
404:
405: /**
406: * Returns the number of written bytes per second.
407: */
408: double getWrittenBytesThroughput();
409:
410: /**
411: * Returns the number of read messages per second.
412: */
413: double getReadMessagesThroughput();
414:
415: /**
416: * Returns the number of written messages per second.
417: */
418: double getWrittenMessagesThroughput();
419:
420: /**
421: * Returns the number of messages which are scheduled to be written to this session.
422: */
423: int getScheduledWriteMessages();
424:
425: /**
426: * Returns the number of bytes which are scheduled to be written to this
427: * session.
428: */
429: long getScheduledWriteBytes();
430:
431: /**
432: * Returns the time in millis when this session is created.
433: */
434: long getCreationTime();
435:
436: /**
437: * Returns the time in millis when I/O occurred lastly.
438: */
439: long getLastIoTime();
440:
441: /**
442: * Returns the time in millis when read operation occurred lastly.
443: */
444: long getLastReadTime();
445:
446: /**
447: * Returns the time in millis when write operation occurred lastly.
448: */
449: long getLastWriteTime();
450:
451: /**
452: * Returns <code>true</code> if this session is idle for the specified
453: * {@link IdleStatus}.
454: */
455: boolean isIdle(IdleStatus status);
456:
457: /**
458: * Returns the number of the fired continuous <tt>sessionIdle</tt> events
459: * for the specified {@link IdleStatus}.
460: * <p/>
461: * If <tt>sessionIdle</tt> event is fired first after some time after I/O,
462: * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to
463: * <tt>0</tt> if any I/O occurs again, otherwise it increases to
464: * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
465: * any I/O between two (or more) <tt>sessionIdle</tt> events.
466: */
467: int getIdleCount(IdleStatus status);
468:
469: /**
470: * Returns the number of the fired continuous <tt>sessionIdle</tt> events
471: * for {@link IdleStatus#READER_IDLE}.
472: * @see #getIdleCount(IdleStatus)
473: */
474: int getReaderIdleCount();
475:
476: /**
477: * Returns the number of the fired continuous <tt>sessionIdle</tt> events
478: * for {@link IdleStatus#WRITER_IDLE}.
479: * @see #getIdleCount(IdleStatus)
480: */
481: int getWriterIdleCount();
482:
483: /**
484: * Returns the number of the fired continuous <tt>sessionIdle</tt> events
485: * for {@link IdleStatus#BOTH_IDLE}.
486: * @see #getIdleCount(IdleStatus)
487: */
488: int getBothIdleCount();
489:
490: /**
491: * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
492: * is fired for the specified {@link IdleStatus}.
493: */
494: long getLastIdleTime(IdleStatus status);
495:
496: /**
497: * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
498: * is fired for {@link IdleStatus#READER_IDLE}.
499: * @see #getLastIdleTime(IdleStatus)
500: */
501: long getLastReaderIdleTime();
502:
503: /**
504: * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
505: * is fired for {@link IdleStatus#WRITER_IDLE}.
506: * @see #getLastIdleTime(IdleStatus)
507: */
508: long getLastWriterIdleTime();
509:
510: /**
511: * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
512: * is fired for {@link IdleStatus#BOTH_IDLE}.
513: * @see #getLastIdleTime(IdleStatus)
514: */
515: long getLastBothIdleTime();
516: }
|