public SocketChannel detachChannel(long sig) { EventableSocketChannel ec = (EventableSocketChannel) Connections.get(sig); if (ec != null) { UnboundConnections.add(sig); return ec.getChannel(); } else { return null; } }
void isConnectable(SelectionKey k) { EventableSocketChannel ec = (EventableSocketChannel) k.attachment(); long b = ec.getBinding(); try { if (ec.finishConnecting()) eventCallback(b, EM_CONNECTION_COMPLETED, null); else UnboundConnections.add(b); } catch (IOException e) { UnboundConnections.add(b); } }
public long attachChannel(SocketChannel sc, boolean watch_mode) { long b = createBinding(); EventableSocketChannel ec = new EventableSocketChannel(sc, b, mySelector); ec.setAttached(); if (watch_mode) ec.setWatchOnly(); Connections.put(b, ec); NewConnections.add(b); return b; }
void close() { try { if (mySelector != null) mySelector.close(); } catch (IOException e) { } mySelector = null; // run down open connections and sockets. Iterator<ServerSocketChannel> i = Acceptors.values().iterator(); while (i.hasNext()) { try { i.next().close(); } catch (IOException e) { } } // 29Sep09: We create an ArrayList of the existing connections, then iterate over // that to call unbind on them. This is because an unbind can trigger a reconnect, // which will add to the Connections HashMap, causing a ConcurrentModificationException. // XXX: The correct behavior here would be to latch the various reactor methods to return // immediately if the reactor is shutting down. ArrayList<EventableChannel> conns = new ArrayList<EventableChannel>(); Iterator<EventableChannel> i2 = Connections.values().iterator(); while (i2.hasNext()) { EventableChannel ec = i2.next(); if (ec != null) { conns.add(ec); } } Connections.clear(); ListIterator<EventableChannel> i3 = conns.listIterator(0); while (i3.hasNext()) { EventableChannel ec = i3.next(); eventCallback(ec.getBinding(), EM_CONNECTION_UNBOUND, null); ec.close(); EventableSocketChannel sc = (EventableSocketChannel) ec; if (sc != null && sc.isAttached()) DetachedConnections.add(sc); } ListIterator<EventableSocketChannel> i4 = DetachedConnections.listIterator(0); while (i4.hasNext()) { EventableSocketChannel ec = i4.next(); ec.cleanup(); } DetachedConnections.clear(); }
void removeUnboundConnections() { ListIterator<Long> iter = UnboundConnections.listIterator(0); while (iter.hasNext()) { long b = iter.next(); EventableChannel ec = Connections.remove(b); if (ec != null) { eventCallback(b, EM_CONNECTION_UNBOUND, null); ec.close(); EventableSocketChannel sc = (EventableSocketChannel) ec; if (sc != null && sc.isAttached()) DetachedConnections.add(sc); } } UnboundConnections.clear(); }
void removeUnboundConnections() { if (UnboundConnections.size() == 0) { return; } ArrayList<Long> currentUnboundConnections = UnboundConnections; // fix concurrent modification exception UnboundConnections = new ArrayList<Long>(); for (long b : currentUnboundConnections) { EventableChannel ec = Connections.remove(b); if (ec != null) { if (ProxyConnections != null) { ProxyConnections.remove(b); } eventCallback(b, EM_CONNECTION_UNBOUND, null); ec.close(); EventableSocketChannel sc = (EventableSocketChannel) ec; if (sc != null && sc.isAttached()) DetachedConnections.add(sc); } } }
void addNewConnections() { ListIterator<EventableSocketChannel> iter = DetachedConnections.listIterator(0); while (iter.hasNext()) { EventableSocketChannel ec = iter.next(); ec.cleanup(); } DetachedConnections.clear(); ListIterator<Long> iter2 = NewConnections.listIterator(0); while (iter2.hasNext()) { long b = iter2.next(); EventableChannel ec = Connections.get(b); if (ec != null) { try { ec.register(); } catch (ClosedChannelException e) { UnboundConnections.add(ec.getBinding()); } } } NewConnections.clear(); }
public long connectTcpServer(String bindAddr, int bindPort, String address, int port) { long b = createBinding(); try { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); if (bindAddr != null) sc.socket().bind(new InetSocketAddress(bindAddr, bindPort)); EventableSocketChannel ec = new EventableSocketChannel(sc, b, mySelector); if (sc.connect(new InetSocketAddress(address, port))) { // Connection returned immediately. Can happen with localhost connections. // WARNING, this code is untested due to lack of available test conditions. // Ought to be be able to come here from a localhost connection, but that // doesn't happen on Linux. (Maybe on FreeBSD?) // The reason for not handling this until we can test it is that we // really need to return from this function WITHOUT triggering any EM events. // That's because until the user code has seen the signature we generated here, // it won't be able to properly dispatch them. The C++ EM deals with this // by setting pending mode as a flag in ALL eventable descriptors and making // the descriptor select for writable. Then, it can send UNBOUND and // CONNECTION_COMPLETED on the next pass through the loop, because writable will // fire. throw new RuntimeException("immediate-connect unimplemented"); } else { ec.setConnectPending(); Connections.put(b, ec); NewConnections.add(b); } } catch (IOException e) { // Can theoretically come here if a connect failure can be determined immediately. // I don't know how to make that happen for testing purposes. throw new RuntimeException("immediate-connect unimplemented: " + e.toString()); } return b; }