/[classpath]/classpath/gnu/java/rmi/server/UnicastConnectionManager.java
ViewVC logotype

Diff of /classpath/gnu/java/rmi/server/UnicastConnectionManager.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by cbj, Thu Mar 21 05:40:11 2002 UTC revision 1.4 by mark, Thu Oct 31 18:35:21 2002 UTC
# Line 1  Line 1 
1  /*  /*
2    Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.    Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 41  import java.rmi.server.RMISocketFactory; Line 41  import java.rmi.server.RMISocketFactory;
41  import java.rmi.server.RMIServerSocketFactory;  import java.rmi.server.RMIServerSocketFactory;
42  import java.rmi.server.RMIClientSocketFactory;  import java.rmi.server.RMIClientSocketFactory;
43  import java.rmi.RemoteException;  import java.rmi.RemoteException;
 import gnu.java.rmi.server.UnicastConnection;  
 import java.util.Hashtable;  
 import java.net.Socket;  
 import java.net.ServerSocket;  
44  import java.io.IOException;  import java.io.IOException;
45  import java.io.ObjectOutput;  import java.io.ObjectOutput;
46  import java.io.ObjectInput;  import java.io.ObjectInput;
47    import java.io.DataInputStream;
48  import java.lang.Thread;  import java.lang.Thread;
49  import java.lang.Runnable;  import java.lang.Runnable;
50  import java.net.InetAddress;  import java.net.InetAddress;
51    import java.net.Socket;
52    import java.net.ServerSocket;
53  import java.net.UnknownHostException;  import java.net.UnknownHostException;
54    
55    import java.util.ArrayList;
56    import java.util.ConcurrentModificationException;
57    import java.util.Enumeration;
58    import java.util.Hashtable;
59    import java.util.Iterator;
60    
61    import gnu.java.rmi.server.UnicastConnection;
62    
63  public class UnicastConnectionManager  public class UnicastConnectionManager
64          implements Runnable, ProtocolConstants {          implements Runnable, ProtocolConstants {
65    
# Line 60  private static String localhost; Line 67  private static String localhost;
67  // use different maps for server/client type UnicastConnectionManager  // use different maps for server/client type UnicastConnectionManager
68  private static Hashtable servers = new Hashtable();  private static Hashtable servers = new Hashtable();
69  private static Hashtable clients = new Hashtable();  private static Hashtable clients = new Hashtable();
70    private ArrayList connections; //client connection pool
71    
72  // make serverThread volatile for poll  // make serverThread volatile for poll
73  private volatile Thread serverThread;  private volatile Thread serverThread;
74  private ServerSocket ssock;  private ServerSocket ssock;
75  String serverName;  String serverName;
76  int serverPort;  int serverPort;
77    
78    static private Thread scavenger;
79    
80    // If client and server are in the same VM, serverobj represents server
81    Object serverobj;
82    
83    private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
84  private RMIServerSocketFactory serverFactory;  private RMIServerSocketFactory serverFactory;
85  private RMIClientSocketFactory clientFactory;  private RMIClientSocketFactory clientFactory;
86    
87    // The following is for debug
88    private static int ncsock = 0;    //count of client socket
89    private static int nssock = 0;    //count of server socket
90    private static int ncmanager = 0; //count of client manager
91    private static int nsmanager = 0; //count of server manager
92    
93    private static final boolean debug = false;
94    
95    private static final Object GLOBAL_LOCK = new Object();
96    
97  static {  static {
98          try {          try {
99                  //Use host address instead of host name to avoid name resolving issues                  //Use host address instead of host name to avoid name resolving issues
# Line 78  static { Line 103  static {
103          catch (UnknownHostException _) {          catch (UnknownHostException _) {
104                  localhost = "localhost";                  localhost = "localhost";
105          }          }
106            
107            
108    }
109    
110    //Only one scavenger thread running globally
111    private static void startScavenger(){
112        scavenger = new Thread(new Runnable(){
113            public void run(){
114                if (debug) System.out.println("************* start scavenger.");
115                boolean liveon = true;
116                while (liveon){
117                    // Sleep for the expire timeout
118                    try{
119                        Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
120                    }catch(InterruptedException _ie){
121                        break;
122                    }
123                    liveon = false;
124                    // Scavenge all clients' connections that're expired
125                    Iterator iter = clients.values().iterator();
126                    long l = System.currentTimeMillis();
127                    try{
128                        while(iter.hasNext()){
129                            UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
130                            ArrayList conns = man.connections;
131                            synchronized(conns) { // is the lock a little coarser?
132                                for (int last = conns.size() - 1;
133                                     last >= 0;
134                                     --last)
135                                {
136                                    UnicastConnection conn = (UnicastConnection)conns.get(last);
137                                    if (UnicastConnection.isExpired(conn, l)){
138                                        conns.remove(last);
139                                        conn.disconnect();
140                                        conn = null;  
141                                    }else
142                                        liveon = true; //there're still live connections
143                                }
144                            }
145                        }
146                    }catch(ConcurrentModificationException cme) {
147                        // handle it lazily
148                        liveon = true;
149                    }
150                }
151                scavenger = null;
152                if (debug) System.out.println("************* exit scavenger.");
153            }
154        });
155        scavenger.start();
156  }  }
157    
158    /**
159      * Client UnicastConnectionManager constructor
160      */
161  private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {  private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
162          ssock = null;          ssock = null;
163          serverName = host;          serverName = host;
164          serverPort = port;          serverPort = port;
165          serverFactory = null;          serverFactory = null;
166          clientFactory = csf;          clientFactory = csf;
167        connections = new ArrayList();
168  }  }
169    
170    /**
171      * Server UnicastConnectionManager constructor
172      */
173  private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {  private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
174          try {          try {
175                  ssock = ssf.createServerSocket(port);                  ssock = ssf.createServerSocket(port);
# Line 115  private UnicastConnectionManager(int por Line 197  private UnicastConnectionManager(int por
197  public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {  public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
198  //System.out.println("getInstance: " + host + "," + port + "," + csf);  //System.out.println("getInstance: " + host + "," + port + "," + csf);
199          if (csf == null) {          if (csf == null) {
200                  csf = RMISocketFactory.getSocketFactory();          csf = defaultSocketFactory;
201          }          }
202          // change host name to host address to avoid name resolving issues          // change host name to host address to avoid name resolving issues
203          try{          try{
# Line 126  public static synchronized UnicastConnec Line 208  public static synchronized UnicastConnec
208          UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);          UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
209          if (man == null) {          if (man == null) {
210                  man = new UnicastConnectionManager(host, port, csf);                  man = new UnicastConnectionManager(host, port, csf);
211            if (debug) {
212                ncmanager++;
213                System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
214            }
215                  clients.put(key, man);                  clients.put(key, man);
216            
217            // Detect if client and server are in the same VM, i.e., their keys are equal
218            UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
219            if(svrman != null){ // server and client are in the same VM
220                man.serverobj = svrman.serverobj;
221            }
222          }          }
223          return (man);          return (man);
224  }  }
# Line 138  public static synchronized UnicastConnec Line 230  public static synchronized UnicastConnec
230  public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {  public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {
231  //System.out.println("getInstance: " + port + "," + ssf);  //System.out.println("getInstance: " + port + "," + ssf);
232          if (ssf == null) {          if (ssf == null) {
233                  ssf = RMISocketFactory.getSocketFactory();          ssf = defaultSocketFactory;
234          }          }
235          TripleKey key = new TripleKey(localhost, port, ssf);          TripleKey key = new TripleKey(localhost, port, ssf);
236          UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);          UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
237          if (man == null) {          if (man == null) {
238                  man = new UnicastConnectionManager(port, ssf);                  man = new UnicastConnectionManager(port, ssf);
239            if (debug) {
240                nsmanager++;
241                System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
242            }
243                  // The provided port might not be the set port.                  // The provided port might not be the set port.
244                  key.port = man.serverPort;                  key.port = man.serverPort;
245                  servers.put(key, man);                  servers.put(key, man);
# Line 168  public UnicastConnection getConnection() Line 264  public UnicastConnection getConnection()
264   */   */
265  private UnicastConnection getServerConnection() throws IOException {  private UnicastConnection getServerConnection() throws IOException {
266          Socket sock = ssock.accept();          Socket sock = ssock.accept();
267        sock.setTcpNoDelay(true); //??
268          UnicastConnection conn = new UnicastConnection(this, sock);          UnicastConnection conn = new UnicastConnection(this, sock);
269          conn.acceptConnection();          conn.acceptConnection();
270  //System.out.println("Server connection " + conn);      if (debug){
271            nssock++;
272            System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
273        }
274        //System.out.println("Server connection " + sock);
275          return (conn);          return (conn);
276  }  }
277    
# Line 178  private UnicastConnection getServerConne Line 279  private UnicastConnection getServerConne
279   * Make a conection from this client to the server.   * Make a conection from this client to the server.
280   */   */
281  private UnicastConnection getClientConnection() throws IOException {  private UnicastConnection getClientConnection() throws IOException {
282        ArrayList conns = connections;
283        UnicastConnection conn;
284        
285        synchronized(conns) {
286            int nconn = conns.size() - 1;
287        
288            // if there're free connections in connection pool
289            if(nconn >= 0) {
290                conn = (UnicastConnection)conns.get(nconn);
291                //Should we check if conn is alive using Ping??
292                conns.remove(nconn);
293                
294                // Check if the connection is already expired
295                long l = System.currentTimeMillis();
296                if (!UnicastConnection.isExpired(conn, l)){
297                    return conn;
298                }else {
299                    conn.disconnect();
300                    conn = null;  
301                }
302            }
303        }
304        
305          Socket sock = clientFactory.createSocket(serverName, serverPort);          Socket sock = clientFactory.createSocket(serverName, serverPort);
306          UnicastConnection conn = new UnicastConnection(this, sock);      conn = new UnicastConnection(this, sock);
307          conn.makeConnection(DEFAULT_PROTOCOL);          conn.makeConnection(DEFAULT_PROTOCOL);
308  //System.out.println("Client connection " + conn);      
309        if (debug) {
310            ncsock++;
311            System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
312        }
313    
314          return (conn);          return (conn);
315  }  }
316    
# Line 191  private UnicastConnection getClientConne Line 320  private UnicastConnection getClientConne
320   */   */
321  public void discardConnection(UnicastConnection conn) {  public void discardConnection(UnicastConnection conn) {
322  //System.out.println("Discarding connection " + conn);  //System.out.println("Discarding connection " + conn);
323        //conn.disconnect();
324        if (ssock != null) //server connection
325          conn.disconnect();          conn.disconnect();
326        else {
327            // To client connection, we'd like to return back to pool
328            UnicastConnection.resetTime(conn);
329            //Ensure there're only one scavenger globally
330            synchronized(GLOBAL_LOCK) {
331                connections.add(conn); //borrow this lock to garantee thread safety
332                if (scavenger == null)
333                    startScavenger();
334            }
335        }
336  }  }
337    
338  /**  /**
# Line 204  public void startServer() { Line 345  public void startServer() {
345                          return;                          return;
346                  }                  }
347                  serverThread = new Thread(this);                  serverThread = new Thread(this);
348            // The following is not necessary when java.lang.Thread's constructor do this.
349            // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
350          }          }
351          serverThread.start();          serverThread.start();
352  }  }
# Line 231  public void run() { Line 374  public void run() {
374  //System.out.println("Waiting for connection on " + serverPort);  //System.out.println("Waiting for connection on " + serverPort);
375                          UnicastConnection conn = getServerConnection();                          UnicastConnection conn = getServerConnection();
376                          // use a thread pool to improve performance                          // use a thread pool to improve performance
377                          // (new Thread(conn)).start();              //ConnectionRunnerPool.dispatchConnection(conn);
378                          ConnectionRunnerPool.dispatchConnection(conn);              (new Thread(conn)).start();
379                  }                  }
380                  catch (Exception e) {                  catch (Exception e) {
381                          // e.printStackTrace();              e.printStackTrace();
382                  }                  }
383          }          }
384  }  }
# Line 254  void write(ObjectOutput out) throws IOEx Line 397  void write(ObjectOutput out) throws IOEx
397  static UnicastConnectionManager read(ObjectInput in) throws IOException {  static UnicastConnectionManager read(ObjectInput in) throws IOException {
398          String host = in.readUTF();          String host = in.readUTF();
399          int port = in.readInt();          int port = in.readInt();
400          RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;          //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
401          return (getInstance(host, port, csf));          //return (getInstance(host, port, csf));
402            return (getInstance(host, port, null));
403  }  }
404    
405  }  }
# Line 288  public boolean equals(Object obj) { Line 432  public boolean equals(Object obj) {
432                  TripleKey other = (TripleKey)obj;                  TripleKey other = (TripleKey)obj;
433                  if (this.host.equals(other.host) &&                  if (this.host.equals(other.host) &&
434                      this.other == other.other &&                      this.other == other.other &&
435                      (this.port == other.port || this.port == 0 || other.port == 0)) {              (this.port == other.port /* || this.port == 0 || other.port == 0*/)) {
436                          return (true);                          return (true);
437                  }                  }
438          }          }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26