1 //******************************************************************************
2 //
3 // File: NetworkChannel.java
4 // Package: edu.rit.mp
5 // Unit: Class edu.rit.mp.NetworkChannel
6 //
7 // This Java source file is copyright (C) 2008 by Alan Kaminsky. All rights
8 // reserved. For further information, contact the author, Alan Kaminsky, at
9 // ark@cs.rit.edu.
10 //
11 // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12 // software; you can redistribute it and/or modify it under the terms of the GNU
13 // General Public License as published by the Free Software Foundation; either
14 // version 3 of the License, or (at your option) any later version.
15 //
16 // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 //
20 // Linking this library statically or dynamically with other modules is making a
21 // combined work based on this library. Thus, the terms and conditions of the GNU
22 // General Public License cover the whole combination.
23 //
24 // As a special exception, the copyright holders of this library give you
25 // permission to link this library with independent modules to produce an
26 // executable, regardless of the license terms of these independent modules, and
27 // to copy and distribute the resulting executable under terms of your choice,
28 // provided that you also meet, for each linked independent module, the terms
29 // and conditions of the license of that module. An independent module is a module
30 // which is not derived from or based on this library. If you modify this library,
31 // you may extend this exception to your version of the library, but you are not
32 // obligated to do so. If you do not wish to do so, delete this exception
33 // statement from your version.
34 //
35 // A copy of the GNU General Public License is provided in the file gpl.txt. You
36 // may also obtain a copy of the GNU General Public License on the World Wide
37 // Web at http://www.gnu.org/licenses/gpl.html.
38 //
39 //******************************************************************************
40 package edu.rit.mp;
41
42 import java.io.IOException;
43 import java.net.InetSocketAddress;
44 import java.nio.channels.SocketChannel;
45 import java.util.concurrent.LinkedBlockingQueue;
46
47 /**
48 * Class NetworkChannel provides a channel for sending and receiving messages
49 * over the network in the Message Protocol (MP).
50 *
51 * @author Alan Kaminsky
52 * @version 23-Apr-2008
53 */
54 class NetworkChannel
55 extends Channel {
56
57 // Hidden data members.
58 // Underlying socket channel.
59 private SocketChannel mySocketChannel;
60
61 // Far end channel group ID.
62 private int myFarChannelGroupId;
63
64 // Queue of outgoing I/O requests.
65 private LinkedBlockingQueue<IORequest> myOutgoingQueue;
66
67 // Network channel send and receive threads.
68 private NetworkChannelSendThread myNetworkChannelSendThread;
69 private NetworkChannelReceiveThread myNetworkChannelReceiveThread;
70
71 // Hidden constructors.
72 /**
73 * Construct a new network channel.
74 *
75 * @param theChannelGroup Enclosing channel group.
76 * @param theSocketChannel Underlying socket channel.
77 * @param theFarChannelGroupId Far end channel group ID.
78 */
79 NetworkChannel(ChannelGroup theChannelGroup,
80 SocketChannel theSocketChannel,
81 int theFarChannelGroupId) {
82 super(theChannelGroup);
83 mySocketChannel = theSocketChannel;
84 myFarChannelGroupId = theFarChannelGroupId;
85 myOutgoingQueue = new LinkedBlockingQueue<IORequest>();
86 }
87
88 // Exported operations.
89 /**
90 * Obtain the channel group ID of this channel's near end channel group.
91 *
92 * @return Near end channel group ID.
93 */
94 public int nearEndChannelGroupId() {
95 return myChannelGroup.myChannelGroupId;
96 }
97
98 /**
99 * Obtain the channel group ID of this channel's far end channel group.
100 *
101 * @return Far end channel group ID.
102 */
103 public int farEndChannelGroupId() {
104 return myFarChannelGroupId;
105 }
106
107 /**
108 * Obtain this channel's near end address. This is the host and port of the
109 * near end of this channel's connection.
110 *
111 * @return Near end address.
112 */
113 public InetSocketAddress nearEndAddress() {
114 return (InetSocketAddress) mySocketChannel.socket().getLocalSocketAddress();
115 }
116
117 /**
118 * Obtain this channel's far end address. This is the host and port of the
119 * far end of this channel's connection.
120 *
121 * @return Far end address.
122 */
123 public InetSocketAddress farEndAddress() {
124 return (InetSocketAddress) mySocketChannel.socket().getRemoteSocketAddress();
125 }
126
127 // Hidden operations.
128 /**
129 * Start sending and receiving messages via this channel.
130 */
131 void start() {
132 myNetworkChannelSendThread
133 = new NetworkChannelSendThread(this,
134 mySocketChannel,
135 myOutgoingQueue);
136 myNetworkChannelReceiveThread
137 = new NetworkChannelReceiveThread(this,
138 mySocketChannel);
139 }
140
141 /**
142 * Send a message via this channel. The I/O request object must be newly
143 * constructed with the message tag and source buffer fields filled in. This
144 * method is allowed to return immediately and let the message be sent in a
145 * separate thread. The calling thread should use the I/O request object to
146 * wait for the message send to complete.
147 *
148 * @param theIORequest I/O request object.
149 *
150 * @exception IOException Thrown if an I/O error occurred.
151 */
152 synchronized void send(IORequest theIORequest)
153 throws IOException {
154 // Check whether channel is closed.
155 if (myWriteState == WRITE_CLOSED) {
156 throw new IOException("NetworkChannel.send(): Channel closed");
157 }
158
159 // Put I/O request in outgoing queue. Send thread will actually send the
160 // message.
161 myOutgoingQueue.add(theIORequest);
162 }
163
164 /**
165 * Perform additional close actions in a subclass.
166 */
167 void subclassClose() {
168 // Close socket channel.
169 if (mySocketChannel != null) {
170 try {
171 mySocketChannel.close();
172 } catch (IOException ignored) {
173 }
174 }
175
176 // Interrupt the send and receive threads, which will cause them to
177 // terminate.
178 if (myNetworkChannelSendThread != null) {
179 myNetworkChannelSendThread.interrupt();
180 }
181 if (myNetworkChannelReceiveThread != null) {
182 myNetworkChannelReceiveThread.interrupt();
183 }
184
185 // Enable garbage collection of data members.
186 mySocketChannel = null;
187 myOutgoingQueue = null;
188 myNetworkChannelSendThread = null;
189 myNetworkChannelReceiveThread = null;
190 }
191
192 /**
193 * Shut down the input side of this network channel.
194 */
195 synchronized void shutdownInput() {
196 myReadState = READ_CLOSED;
197 myNetworkChannelReceiveThread = null;
198 }
199
200 }