OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [rmi/] [server/] [UnicastConnectionManager.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* UnicastConnectionManager.java --
2
   Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004
3
   Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package gnu.java.rmi.server;
41
 
42
import java.io.IOException;
43
import java.io.ObjectInput;
44
import java.io.ObjectOutput;
45
import java.net.InetAddress;
46
import java.net.ServerSocket;
47
import java.net.Socket;
48
import java.net.UnknownHostException;
49
import java.rmi.RemoteException;
50
import java.rmi.server.RMIClientSocketFactory;
51
import java.rmi.server.RMIServerSocketFactory;
52
import java.rmi.server.RMISocketFactory;
53
import java.util.ArrayList;
54
import java.util.ConcurrentModificationException;
55
import java.util.Hashtable;
56
import java.util.Iterator;
57
 
58
public class UnicastConnectionManager
59
        implements Runnable, ProtocolConstants {
60
 
61
private static String localhost;
62
// use different maps for server/client type UnicastConnectionManager
63
private static Hashtable servers = new Hashtable();
64
// Package-private to avoid trampolines.
65
static Hashtable clients = new Hashtable();
66
ArrayList connections; //client connection pool
67
 
68
// make serverThread volatile for poll
69
private volatile Thread serverThread;
70
private ServerSocket ssock;
71
String serverName;
72
int serverPort;
73
 
74
// Package-private to avoid a trampoline.
75
static Thread scavenger;
76
 
77
// If client and server are in the same VM, serverobj represents server
78
Object serverobj;
79
 
80
private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
81
private RMIServerSocketFactory serverFactory;
82
private RMIClientSocketFactory clientFactory;
83
 
84
// The following is for debug
85
private static int ncsock = 0;    //count of client socket
86
private static int nssock = 0;    //count of server socket
87
private static int ncmanager = 0; //count of client manager
88
private static int nsmanager = 0; //count of server manager
89
 
90
private static final boolean debug = false;
91
 
92
private static final Object GLOBAL_LOCK = new Object();
93
 
94
static {
95
        try {
96
                //Use host address instead of host name to avoid name resolving issues
97
                //localhost = InetAddress.getLocalHost().getHostName();
98
                localhost = InetAddress.getLocalHost().getHostAddress();
99
        }
100
        catch (UnknownHostException _) {
101
                localhost = "localhost";
102
        }
103
 
104
 
105
}
106
 
107
//Only one scavenger thread running globally
108
private static void startScavenger(){
109
    scavenger = new Thread(new Runnable(){
110
        public void run(){
111
            if (debug) System.out.println("************* start scavenger.");
112
            boolean liveon = true;
113
            while (liveon){
114
                // Sleep for the expire timeout
115
                try{
116
                    Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
117
                }catch(InterruptedException _ie){
118
                    break;
119
                }
120
                liveon = false;
121
                // Scavenge all clients' connections that're expired
122
                Iterator iter = clients.values().iterator();
123
                long l = System.currentTimeMillis();
124
                try{
125
                    while(iter.hasNext()){
126
                        UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
127
                        ArrayList conns = man.connections;
128
                        synchronized(conns) { // is the lock a little coarser?
129
                            for (int last = conns.size() - 1;
130
                                 last >= 0;
131
                                 --last)
132
                            {
133
                                UnicastConnection conn = (UnicastConnection)conns.get(last);
134
                                if (UnicastConnection.isExpired(conn, l)){
135
                                    conns.remove(last);
136
                                    conn.disconnect();
137
                                    conn = null;
138
                                }else
139
                                    liveon = true; //there're still live connections
140
                            }
141
                        }
142
                    }
143
                }catch(ConcurrentModificationException cme) {
144
                    // handle it lazily
145
                    liveon = true;
146
                }
147
            }
148
            scavenger = null;
149
            if (debug) System.out.println("************* exit scavenger.");
150
        }
151
    });
152
    // As it is used for client connection, we may put this thread
153
    // in daemon state to prevent the VM from blocking when exiting.
154
    scavenger.setDaemon(true);
155
    scavenger.start();
156
}
157
 
158
/**
159
  * Client UnicastConnectionManager constructor
160
  */
161
private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
162
        ssock = null;
163
        serverName = host;
164
        serverPort = port;
165
        serverFactory = null;
166
        clientFactory = csf;
167
    connections = new ArrayList();
168
}
169
 
170
/**
171
  * Server UnicastConnectionManager constructor
172
  */
173
private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) throws RemoteException {
174
 
175
        try {
176
                ssock = ssf.createServerSocket(port);
177
                serverPort = ssock.getLocalPort();
178
        }
179
        catch (IOException ioex) {
180
                ssock = null;
181
                serverPort = 0;
182
                throw new java.rmi.server.ExportException("can not create Server Socket on port " + port,ioex);
183
        }
184
        // Note that for compatibility the serverName is "localhost",
185
        // not UnicastConnectionManager.localhost, which is the name
186
        // of the local box.  A server listening on localhost:port is
187
        // listening on the loopback interface, 127.0.0.1, but
188
        // UnicastConnectionManager.localhost is an externally
189
        // accessible IP address.
190
        serverName = "localhost";
191
        serverFactory = ssf;
192
        clientFactory = null;
193
}
194
 
195
/**
196
 * Return a client connection manager which will connect to the given
197
 * host/port.
198
 */
199
public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
200
//System.out.println("getInstance: " + host + "," + port + "," + csf);
201
        if (csf == null) {
202
        csf = defaultSocketFactory;
203
        }
204
        // change host name to host address to avoid name resolving issues
205
        try{
206
        host = InetAddress.getByName(host).getHostAddress();
207
    }catch(Exception _){}
208
 
209
        TripleKey key = new TripleKey(host, port, csf);
210
        UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
211
        if (man == null) {
212
                man = new UnicastConnectionManager(host, port, csf);
213
        if (debug) {
214
            ncmanager++;
215
            System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
216
        }
217
                clients.put(key, man);
218
 
219
        // Detect if client and server are in the same VM, i.e., their keys are equal
220
        UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
221
        if(svrman != null){ // server and client are in the same VM
222
            man.serverobj = svrman.serverobj;
223
        }
224
        }
225
        return (man);
226
}
227
 
228
/**
229
 * Return a server connection manager which will accept connection on the
230
 * given port.
231
 */
232
public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException {
233
//System.out.println("getInstance: " + port + "," + ssf);
234
        if (ssf == null) {
235
        ssf = defaultSocketFactory;
236
        }
237
        TripleKey key = new TripleKey(localhost, port, ssf);
238
        UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
239
        if (man == null) {
240
                man = new UnicastConnectionManager(port, ssf);
241
        if (debug) {
242
            nsmanager++;
243
            System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
244
        }
245
                // The provided port might not be the set port.
246
                key.port = man.serverPort;
247
                servers.put(key, man);
248
        }
249
        return (man);
250
}
251
 
252
/**
253
 * Get a connection from this manager.
254
 */
255
public UnicastConnection getConnection() throws IOException {
256
        if (ssock == null) {
257
                return (getClientConnection());
258
        }
259
        else {
260
                return (getServerConnection());
261
        }
262
}
263
 
264
/**
265
 * Accept a connection to this server.
266
 */
267
private UnicastConnection getServerConnection() throws IOException {
268
        Socket sock = ssock.accept();
269
    sock.setTcpNoDelay(true); //??
270
        UnicastConnection conn = new UnicastConnection(this, sock);
271
        conn.acceptConnection();
272
    if (debug){
273
        nssock++;
274
        System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
275
    }
276
    //System.out.println("Server connection " + sock);
277
        return (conn);
278
}
279
 
280
/**
281
 * Make a conection from this client to the server.
282
 */
283
private UnicastConnection getClientConnection() throws IOException {
284
    ArrayList conns = connections;
285
    UnicastConnection conn;
286
 
287
    synchronized(conns) {
288
        int nconn = conns.size() - 1;
289
 
290
        // if there're free connections in connection pool
291
        if(nconn >= 0) {
292
            conn = (UnicastConnection)conns.get(nconn);
293
            //Should we check if conn is alive using Ping??
294
            conns.remove(nconn);
295
 
296
            // Check if the connection is already expired
297
            long l = System.currentTimeMillis();
298
            if (!UnicastConnection.isExpired(conn, l)){
299
                return conn;
300
            }else {
301
                conn.disconnect();
302
                conn = null;
303
            }
304
        }
305
    }
306
 
307
        Socket sock = clientFactory.createSocket(serverName, serverPort);
308
    conn = new UnicastConnection(this, sock);
309
        conn.makeConnection(DEFAULT_PROTOCOL);
310
 
311
    if (debug) {
312
        ncsock++;
313
        System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
314
    }
315
 
316
        return (conn);
317
}
318
 
319
/**
320
 * Get the string representation, describing the connection.
321
 */
322
public String toString()
323
{
324
  return serverName+":"+serverPort+" ("+serverobj+")";
325
}
326
 
327
/**
328
 * Discard a connection when we're done with it - maybe it can be
329
 * recycled.
330
 */
331
public void discardConnection(UnicastConnection conn) {
332
//System.out.println("Discarding connection " + conn);
333
    //conn.disconnect();
334
    if (ssock != null) //server connection
335
        conn.disconnect();
336
    else {
337
        // To client connection, we'd like to return back to pool
338
        UnicastConnection.resetTime(conn);
339
        //Ensure there're only one scavenger globally
340
        synchronized(GLOBAL_LOCK) {
341
            connections.add(conn); //borrow this lock to garantee thread safety
342
            if (scavenger == null)
343
                startScavenger();
344
        }
345
    }
346
}
347
 
348
/**
349
 * Start a server on this manager if it's a server socket and we've not
350
 * already got one running.
351
 */
352
public void startServer() {
353
        synchronized(this) {
354
                if (ssock == null || serverThread != null) {
355
                        return;
356
                }
357
                serverThread = new Thread(this);
358
        // The following is not necessary when java.lang.Thread's constructor do this.
359
        // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
360
        }
361
        serverThread.start();
362
}
363
 
364
/**
365
 * Stop a server on this manager
366
 */
367
public void stopServer() {
368
    synchronized(this) {
369
        if(serverThread != null){
370
            serverThread = null;
371
            try{
372
                ssock.close();
373
            }catch(Exception _){}
374
        }
375
    }
376
}
377
 
378
/**
379
 * Server thread for connection manager.
380
 */
381
public void run() {
382
        for (;serverThread != null;) { // if serverThread==null, then exit thread
383
                try {
384
//System.out.println("Waiting for connection on " + serverPort);
385
                        UnicastConnection conn = getServerConnection();
386
 
387
                        // get address of remote host for the RMIIncomingThread object
388
                        String remoteHost = null;
389
                        if (conn.sock != null) {
390
                                remoteHost = conn.sock.getInetAddress().getHostAddress();
391
                        }
392
 
393
                        // use a thread pool to improve performance
394
            //ConnectionRunnerPool.dispatchConnection(conn);
395
            (new RMIIncomingThread(conn, remoteHost)).start();
396
//         (new Thread(conn)).start();
397
                }
398
                catch (Exception e) {
399
            e.printStackTrace();
400
                }
401
        }
402
}
403
 
404
/**
405
 * Serialization routine.
406
 */
407
void write(ObjectOutput out) throws IOException {
408
        out.writeUTF(serverName);
409
        out.writeInt(serverPort);
410
}
411
 
412
/**
413
 * Serialization routine.
414
 */
415
static UnicastConnectionManager read(ObjectInput in) throws IOException {
416
        String host = in.readUTF();
417
        int port = in.readInt();
418
        //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
419
        //return (getInstance(host, port, csf));
420
        return (getInstance(host, port, null));
421
}
422
 
423
}
424
 
425
/**
426
 * This is use as the hashkey for the client/server connections.
427
 */
428
class TripleKey {
429
 
430
String host;
431
int port;
432
Object other;
433
 
434
TripleKey(String host, int port, Object other) {
435
        this.host = host;
436
        this.port = port;
437
        this.other = other;
438
}
439
 
440
/**
441
 * Hash code just include the host and other - we ignore the port since
442
 * this has unusual matching behaviour.
443
 */
444
public int hashCode() {
445
        return (host.hashCode() ^ other.hashCode());
446
}
447
 
448
public boolean equals(Object obj) {
449
        if (obj instanceof TripleKey) {
450
                TripleKey other = (TripleKey)obj;
451
                if (this.host.equals(other.host) &&
452
                    this.other == other.other &&
453
            (this.port == other.port /* || this.port == 0 || other.port == 0*/)) {
454
                        return (true);
455
                }
456
        }
457
        return (false);
458
}
459
 
460
  /**
461
   * Get the string representation, describing the connection.
462
   */
463
  public String toString()
464
  {
465
    return host+":"+port+" ("+other+")";
466
  }
467
 
468
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.