1 //****************************************************************************** 2 // 3 // File: Channel.java 4 // Package: edu.rit.mp 5 // Unit: Class edu.rit.mp.Channel 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.io.PrintStream; 44 import java.net.InetSocketAddress; 45 46 /** 47 * Class Channel provides a channel for sending and receiving messages in the 48 * Message Protocol (MP). 49 * <P> 50 * A channel object is not constructed directly. Rather, a channel group object 51 * is used to connect a channel to another computer, accept a channel connection 52 * from another computer, or obtain a "loopback" channel within the same 53 * computer. See class {@linkplain ChannelGroup} for further information. 54 * <P> 55 * An information object may be associated with a channel. An application using 56 * MP can use the information object to hold additional data about the channel. 57 * 58 * @author Alan Kaminsky 59 * @version 13-May-2008 60 */ 61 public abstract class Channel { 62 63 // Hidden data members. 64 ChannelGroup myChannelGroup; 65 IORequestList myIORequestList; 66 Object myInfo; 67 68 int myWriteState = WRITE_OPEN; 69 static final int WRITE_OPEN = 0; 70 static final int WRITE_CLOSED = 1; 71 72 int myReadState = READ_OPEN; 73 static final int READ_OPEN = 0; 74 static final int READ_CLOSED = 1; 75 76 // Hidden constructors. 77 /** 78 * Construct a new channel. 79 * 80 * @param theChannelGroup Enclosing channel group. 81 */ 82 Channel(ChannelGroup theChannelGroup) { 83 myChannelGroup = theChannelGroup; 84 myIORequestList = theChannelGroup.myIORequestList; 85 } 86 87 // Exported operations. 88 /** 89 * Obtain the channel group that created this channel. 90 * 91 * @return Channel group. 92 */ 93 public ChannelGroup getChannelGroup() { 94 return myChannelGroup; 95 } 96 97 /** 98 * Obtain the channel group ID of this channel's near end channel group. 99 * 100 * @return Near end channel group ID. 101 */ 102 public abstract int nearEndChannelGroupId(); 103 104 /** 105 * Obtain the channel group ID of this channel's far end channel group. 106 * 107 * @return Far end channel group ID. 108 */ 109 public abstract int farEndChannelGroupId(); 110 111 /** 112 * Obtain this channel's near end address. This is the host and port of the 113 * near end of this channel's connection. 114 * 115 * @return Near end address. 116 */ 117 public abstract InetSocketAddress nearEndAddress(); 118 119 /** 120 * Obtain this channel's far end address. This is the host and port of the 121 * far end of this channel's connection. 122 * 123 * @return Far end address. 124 */ 125 public abstract InetSocketAddress farEndAddress(); 126 127 /** 128 * Obtain this channel's information object. 129 * 130 * @return Information object, or null if none. 131 */ 132 public Object info() { 133 return myInfo; 134 } 135 136 /** 137 * Set this channel's information object. 138 * 139 * @param theInfo Information object, or null if none. 140 */ 141 public void info(Object theInfo) { 142 myInfo = theInfo; 143 } 144 145 /** 146 * Close this channel. Any pending send requests will fail with a 147 * {@linkplain ChannelClosedException}. 148 */ 149 public void close() { 150 // To avoid deadlock, synchronize first on the channel group, then on 151 // this channel. 152 synchronized (myChannelGroup) { 153 synchronized (this) { 154 myChannelGroup.removeChannel(this); 155 myWriteState = WRITE_CLOSED; 156 myReadState = READ_CLOSED; 157 subclassClose(); 158 } 159 } 160 } 161 162 /** 163 * Returns a string version of this channel. 164 * 165 * @return a {@link java.lang.String} object. 166 */ 167 public String toString() { 168 return getClass().getName() 169 + "(near=" + nearEndAddress() 170 + ",far=" + farEndAddress() + ")"; 171 } 172 173 /** 174 * Dump the state of this channel on the given print stream. For debugging. 175 * 176 * @param out Print stream. 177 * @param prefix String to print at the beginning of each line. 178 */ 179 public void dump(PrintStream out, 180 String prefix) { 181 out.println(prefix + getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(this))); 182 out.println(prefix + "myChannelGroup = " + myChannelGroup); 183 out.println(prefix + "myIORequestList = " + myIORequestList); 184 out.println(prefix + "myInfo = " + myInfo); 185 out.println(prefix + "myWriteState = " + (myWriteState == WRITE_OPEN ? "WRITE_OPEN" : "WRITE_CLOSED")); 186 out.println(prefix + "myReadState = " + (myReadState == READ_OPEN ? "READ_OPEN" : "READ_CLOSED")); 187 out.println(prefix + "nearEndChannelGroupId() = " + nearEndChannelGroupId()); 188 out.println(prefix + "farEndChannelGroupId() = " + farEndChannelGroupId()); 189 out.println(prefix + "nearEndAddress() = " + nearEndAddress()); 190 out.println(prefix + "farEndAddress() = " + farEndAddress()); 191 } 192 193 // Hidden operations. 194 /** 195 * Start sending and receiving messages via this channel. 196 */ 197 void start() { 198 } 199 200 /** 201 * Send a message via this channel. The I/O request object must be newly 202 * constructed with the message tag and source buffer fields filled in. This 203 * method is allowed to return immediately and let the message be sent in a 204 * separate thread. The calling thread should use the I/O request object to 205 * wait for the message send to complete. 206 * 207 * @param theIORequest I/O request object. 208 * 209 * @exception IOException Thrown if an I/O error occurred. 210 */ 211 abstract void send(IORequest theIORequest) 212 throws IOException; 213 214 /** 215 * Perform additional close actions in a subclass. 216 */ 217 void subclassClose() { 218 } 219 220 }