public int ready() throws IOException { if (descriptor.getChannel() instanceof SelectableChannel) { int ready_stat = 0; java.nio.channels.Selector sel = SelectorFactory.openWithRetryFrom( null, ((SelectableChannel) descriptor.getChannel()).provider()); SelectableChannel selchan = (SelectableChannel) descriptor.getChannel(); synchronized (selchan.blockingLock()) { boolean is_block = selchan.isBlocking(); try { selchan.configureBlocking(false); selchan.register(sel, java.nio.channels.SelectionKey.OP_READ); ready_stat = sel.selectNow(); sel.close(); } catch (Throwable ex) { } finally { if (sel != null) { try { sel.close(); } catch (Exception e) { } } selchan.configureBlocking(is_block); } } return ready_stat; } else { return newInputStream().available(); } }
public static void main(String[] argv) throws Exception { Pipe[] pipes = new Pipe[PIPES_COUNT]; Pipe pipe = Pipe.open(); Pipe.SinkChannel sink = pipe.sink(); Pipe.SourceChannel source = pipe.source(); Selector sel = Selector.open(); source.configureBlocking(false); source.register(sel, SelectionKey.OP_READ); for (int i = 0; i < PIPES_COUNT; i++) { pipes[i] = Pipe.open(); Pipe.SourceChannel sc = pipes[i].source(); sc.configureBlocking(false); sc.register(sel, SelectionKey.OP_READ); Pipe.SinkChannel sc2 = pipes[i].sink(); sc2.configureBlocking(false); sc2.register(sel, SelectionKey.OP_WRITE); } for (int i = 0; i < LOOPS; i++) { sink.write(ByteBuffer.allocate(BUF_SIZE)); int x = sel.selectNow(); sel.selectedKeys().clear(); source.read(ByteBuffer.allocate(BUF_SIZE)); } for (int i = 0; i < PIPES_COUNT; i++) { pipes[i].sink().close(); pipes[i].source().close(); } pipe.sink().close(); pipe.source().close(); sel.close(); }
private void driveClientIO() throws IOException, GearmanException { for (GearmanJobServerSession sess : sessionsMap.values()) { int interestOps = SelectionKey.OP_READ; if (sess.sessionHasDataToWrite()) { interestOps |= SelectionKey.OP_WRITE; } try { sess.getSelectionKey().interestOps(interestOps); } catch (IllegalStateException ise) { LOG.warn("Unable to drive IO for session " + sess + "," + " skipping.", ise); continue; } } ioAvailable.selectNow(); Set<SelectionKey> keys = ioAvailable.selectedKeys(); LOG.trace( "Driving IO for client " + this + ". " + keys.size() + " session(s) currently available for IO"); Iterator<SelectionKey> iter = keys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); GearmanJobServerSession s = sessionsMap.get(key); s.driveSessionIO(); } }
/** * The background thread that adds sockets to the Poller, checks the poller for triggered events * and hands the associated socket off to an appropriate processor as events occur. */ @Override public void run() { // Loop until destroy() is called while (true) { boolean hasEvents = false; try { if (!close) { hasEvents = events(); if (wakeupCounter.getAndSet(-1) > 0) { // if we are here, means we have other stuff to do // do a non blocking select keyCount = selector.selectNow(); } else { keyCount = selector.select(selectorTimeout); } wakeupCounter.set(0); } if (close) { events(); timeout(0, false); try { selector.close(); } catch (IOException ioe) { log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe); } break; } } catch (Throwable x) { ExceptionUtils.handleThrowable(x); log.error("", x); continue; } // either we timed out or we woke up, process events first if (keyCount == 0) hasEvents = (hasEvents | events()); Iterator<SelectionKey> iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null; // Walk through the collection of ready keys and dispatch // any active event. while (iterator != null && iterator.hasNext()) { SelectionKey sk = iterator.next(); NioSocketWrapper attachment = (NioSocketWrapper) sk.attachment(); // Attachment may be null if another thread has called // cancelledKey() if (attachment == null) { iterator.remove(); } else { iterator.remove(); processKey(sk, attachment); } } // while // process timeouts timeout(keyCount, hasEvents); } // while stopLatch.countDown(); }
/** * Execute the Selector.select(...) operations. * * @param ctx {@link Context} * @return {@link Set} of {@link SelectionKey} */ public Set<SelectionKey> select(Context ctx) throws IOException { if (postponedTasks.isEmpty()) { selector.select(selectTimeout); } else { selector.selectNow(); } return selector.selectedKeys(); }
private boolean cleanUpCancelledKeys() throws IOException { if (cancelledKeys >= CLEANUP_INTERVAL) { cancelledKeys = 0; selector.selectNow(); return true; } return false; }
public boolean processNow() throws IOException { int numKeys = selector.selectNow(); if (selector.keys().isEmpty()) return false; if (numKeys > 0) dispatchMessages(); return true; }
/** * Release the selection key, working around for bug #6403933. * * @param selector The associated selector. * @param selectionKey The used selection key. * @throws IOException */ public static void release(Selector selector, SelectionKey selectionKey) throws IOException { if (selectionKey != null) { // The key you registered on the temporary selector selectionKey.cancel(); if (selector != null) { // Flush the canceled key selector.selectNow(); SelectorFactory.returnSelector(selector); } } }
protected final boolean cleanUpCancelledKeys() { try { if (cancelledKeys >= CLEANUP_INTERVAL) { cancelledKeys = 0; nioSelector.selectNow(); return true; } } catch (IOException e) { // select exception } return false; }
/** * Loops through all of the selected network events and determines which ones are ready to be * handled, and executes them if so. */ public void sequence() { try { selector.selectNow(); Iterator<SelectionKey> $it = selector.selectedKeys().iterator(); while ($it.hasNext()) { ServerSelectionKey key = new ServerSelectionKey($it.next(), selector, channel); Optional<ServerSelectionEvent> event = key.determineEvent(); event.ifPresent(e -> e.execute(key)); $it.remove(); } } catch (Exception e) { logger.log(Level.SEVERE, "An error has occured while selecting network events!", e); } }
@Override public boolean keepalive() throws RemoteException { try { boolean result = false; for (Iterator< Entry<Member, org.apache.catalina.tribes.transport.nio.NioSenderRemoteInterface>> i = nioSenders.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Member, org.apache.catalina.tribes.transport.nio.NioSenderRemoteInterface> entry = i.next(); org.apache.catalina.tribes.transport.nio.NioSenderRemoteInterface sender = entry.getValue(); if (sender.keepalive()) { // nioSenders.remove(entry.getKey()); i.remove(); result = true; } else { try { sender.read(null); } catch (IOException x) { sender.disconnect(); sender.reset(); // nioSenders.remove(entry.getKey()); i.remove(); result = true; } catch (Exception x) { log.warn("Error during keepalive test for sender:" + sender, x); } } } // clean up any cancelled keys if (result) try { selector.selectNow(); } catch (Exception e) { /* Ignore */ } return result; } catch (Exception excp) { excp.printStackTrace(); } return true; }
void processConnections() { synchronized (this.pendingStateChanges) { Iterator<ChangeRequest> changes = this.pendingStateChanges.iterator(); while (changes.hasNext()) { ChangeRequest change = (ChangeRequest) changes.next(); SelectionKey key = change.getSocket().keyFor(this.selector); key.interestOps(change.getOps()); } this.pendingStateChanges.clear(); } try { selector.selectNow(); } catch (IOException e) { LOG.severe("Couldn't select channels."); } processSelectedKeys(); selector.selectedKeys().clear(); }
void checkIO() { long timeout; if (NewConnections.size() > 0) { timeout = -1; } else if (!Timers.isEmpty()) { long now = new Date().getTime(); long k = Timers.firstKey(); long diff = k - now; if (diff <= 0) timeout = -1; // don't wait, just poll once else timeout = diff; } else { timeout = 0; // wait indefinitely } try { if (timeout == -1) mySelector.selectNow(); else mySelector.select(timeout); } catch (IOException e) { e.printStackTrace(); } }
public static void checkClients(List<SocketChannel> anonymousClients) { try { if (selector.selectNow() == 0) { return; } Set<SelectionKey> keys = selector.selectedKeys(); for (SelectionKey key : keys) { if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) { SocketChannel clientSocket = serverSocket.accept(); if (clientSocket == null) { System.err.println("Error: can not accept"); continue; } anonymousClients.add(clientSocket); clientSocket.configureBlocking(false); clientSocket.register(selector, SelectionKey.OP_READ); } else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) { SocketChannel clientSocket = (SocketChannel) key.channel(); ByteBuffer bytes = ByteBuffer.allocate(4096); if (clientSocket.read(bytes) != -1) { byte[] message = bytes.array(); switch (message[0]) { case 1: { String nick = MessageUtils.parseMessage(message).first; if (!checkMessage(nick, "", clientSocket)) { continue; } if (clients.containsKey(nick) || nick.length() > 32) { if (nick.length() > 32) { sendMessage( clientSocket, MessageUtils.error("<server>: your nick is too long")); } else { sendMessage( clientSocket, MessageUtils.error("<server>: another user is using this nick")); } sendMessage(clientSocket, MessageUtils.bye()); anonymousClients.remove(clientSocket); Utils.tryClose(clientSocket); } else { System.out.println(nick + " enter this chatroom"); notifyAllClients(nick + " enter this chatroom"); sendMessage( clientSocket, MessageUtils.message("<server>", "Wellcome, your nick is " + nick)); anonymousClients.remove(clientSocket); clients.put(nick, clientSocket); } break; } case 2: { String nick = getNickFromSocket(clientSocket); if (nick == null) { Utils.printErrorAndExit("Error: it could not happen"); } Utils.Pair<String, String> pair = MessageUtils.parseMessage(message); if (!checkMessage(pair.first, pair.second, clientSocket)) { continue; } if (!pair.first.equals(nick)) { System.out.println("Cheater: " + nick); sendMessage(clientSocket, MessageUtils.message("<server>", "do not cheat")); } for (Entry<String, SocketChannel> client : clients.entrySet()) { if (!clientSocket.equals(client.getValue())) { sendMessage(client.getValue(), MessageUtils.message(nick, pair.second)); } } break; } case 3: disconnectClient(clientSocket); break; case 127: { String nick = getNickFromSocket(clientSocket); Utils.Pair<String, String> pair = MessageUtils.parseMessage(message); if (!checkMessage(pair.first, pair.second, clientSocket)) { continue; } if (!pair.first.equals(nick)) { System.out.println("Cheater: " + nick); sendMessage(clientSocket, MessageUtils.message("<server>", "do not cheat")); } System.out.println(nick + ": " + pair.second); break; } default: System.out.println("Bad message from " + getNickFromSocket(clientSocket)); sendMessage(clientSocket, MessageUtils.message("<server>", "bad message")); break; } } else { disconnectClient(clientSocket); } } } keys.clear(); } catch (Exception expt) { expt.printStackTrace(); Utils.printErrorAndExit(expt.getMessage()); } }
@Test public void testSelector() throws Exception { ServerSocket acceptor = new ServerSocket(0); Selector selector = Selector.open(); // Create client server socket pair SocketChannel client = SocketChannel.open(acceptor.getLocalSocketAddress()); Socket server = acceptor.accept(); server.setTcpNoDelay(true); // Make the client non blocking and register it with selector for reads client.configureBlocking(false); SelectionKey key = client.register(selector, SelectionKey.OP_READ); // assert it is not selected assertTrue(key.isValid()); assertFalse(key.isReadable()); assertEquals(0, key.readyOps()); // try selecting and assert nothing selected int selected = selector.selectNow(); assertEquals(0, selected); assertEquals(0, selector.selectedKeys().size()); assertTrue(key.isValid()); assertFalse(key.isReadable()); assertEquals(0, key.readyOps()); // Write a byte from server to client server.getOutputStream().write(42); server.getOutputStream().flush(); // select again and assert selection found for read selected = selector.select(1000); assertEquals(1, selected); assertEquals(1, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // select again and see that it is not reselect, but stays selected selected = selector.select(100); assertEquals(0, selected); assertEquals(1, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // read the byte ByteBuffer buf = ByteBuffer.allocate(1024); int len = client.read(buf); assertEquals(1, len); buf.flip(); assertEquals(42, buf.get()); buf.clear(); // But this does not change the key assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // Even if we select again ? selected = selector.select(100); assertEquals(0, selected); assertEquals(1, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // Unless we remove the key from the select set // and then it is still flagged as isReadable() selector.selectedKeys().clear(); assertEquals(0, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // Now if we select again - it is still flagged as readable!!! selected = selector.select(100); assertEquals(0, selected); assertEquals(0, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1, key.readyOps()); // Only when it is selected for something else does that state change. key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); selected = selector.select(1000); assertEquals(1, selected); assertEquals(1, selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isWritable()); assertFalse(key.isReadable()); assertEquals(SelectionKey.OP_WRITE, key.readyOps()); }
/** Check for incoming messages */ private void readIncomingMessages() { Client client = null; try { // non-blocking select, returns immediately regardless of // how many keys are ready readSelector.selectNow(); // fetch the keys Set<SelectionKey> readyKeys = readSelector.selectedKeys(); // run through the keys and process each one while (!readyKeys.isEmpty()) { SelectionKey key = readyKeys.iterator().next(); readyKeys.remove(key); SocketChannel channel = (SocketChannel) key.channel(); client = (Client) key.attachment(); if (client.isHalfDead()) { continue; } readBuffer.clear(); client.setTimeOfLastReceive(System.currentTimeMillis()); // read from the channel into our buffer long nBytes = channel.read(readBuffer); client.addReceived(nBytes); // basic anti-flood protection FloodProtectionService floodProtection = getContext().getService(FloodProtectionService.class); if ((floodProtection != null) && floodProtection.isFlooding(client)) { continue; } // check for end-of-stream if (nBytes == -1) { LOG.debug("Socket disconnected - killing client"); channel.close(); // this will also close the socket channel getContext().getClients().killClient(client); } else { // use a CharsetDecoder to turn those bytes into a string // and append it to the client's StringBuilder readBuffer.flip(); String str = getContext().getServer().getAsciiDecoder().decode(readBuffer).toString(); readBuffer.clear(); client.appendToRecvBuf(str); // TODO move this to Client#appendToRecvBuf(String) // check for a full line String line = client.readLine(); while (line != null) { executeCommandWrapper(line, client); if (!client.isAlive()) { // in case the client was killed within the // executeCommand() method break; } line = client.readLine(); } } } } catch (IOException ioex) { LOG.info( "exception during select(): possibly due to force disconnect. Killing the client ..."); if (client != null) { getContext().getClients().killClient(client, "Quit: connection lost"); } LOG.debug("... the exception was:", ioex); } }
private boolean sendPacket(Packet packet, InetSocketAddress address, SelectionKey selectedKey) { boolean result = false; try { lock.lock(); if (selectedKey == unicastKey) { LifxNetworkThrottler.lock(macAsHex); } else { LifxNetworkThrottler.lock(); } boolean sent = false; while (!sent && selector.isOpen()) { try { selector.selectNow(); } catch (IOException e) { logger.error("An exception occurred while selecting: {}", e.getMessage()); } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isValid() && key.isWritable() && key.equals(selectedKey)) { SelectableChannel channel = key.channel(); try { if (channel instanceof DatagramChannel) { logger.trace( "{} : Sending packet type '{}' from '{}' to '{}' for '{}' with sequence '{}' and source '{}'", new Object[] { macAsHex, packet.getClass().getSimpleName(), ((InetSocketAddress) ((DatagramChannel) channel).getLocalAddress()) .toString(), address.toString(), packet.getTarget().getHex(), packet.getSequence(), Long.toString(packet.getSource(), 16) }); ((DatagramChannel) channel).send(packet.bytes(), address); sent = true; result = true; } else if (channel instanceof SocketChannel) { ((SocketChannel) channel).write(packet.bytes()); } } catch (Exception e) { logger.error("An exception occurred while writing data : '{}'", e.getMessage()); break; } } } } } catch (Exception e) { logger.error( "An exception occurred while sending a packet to the bulb : '{}'", e.getMessage()); } finally { if (selectedKey == unicastKey) { LifxNetworkThrottler.unlock(macAsHex); } else { LifxNetworkThrottler.unlock(); } lock.unlock(); } return result; }
@Override public void run() { try { lock.lock(); if (selector != null) { try { selector.selectNow(); } catch (IOException e) { logger.error("An exception occurred while selecting: {}", e.getMessage()); } Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); while (keyIterator.hasNext()) { SelectionKey key; try { key = keyIterator.next(); } catch (ConcurrentModificationException e) { // when a StateServiceResponse packet is handled a new unicastChannel may be // registered // in the selector which causes this exception, recover from it by restarting the // iteration logger.debug( "{} : Restarting iteration after ConcurrentModificationException", macAsHex); keyIterator = selector.selectedKeys().iterator(); continue; } if (key.isValid() && key.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. // block of code only for completeness purposes } else if (key.isValid() && key.isConnectable()) { // a connection was established with a remote server. // block of code only for completeness purposes } else if (key.isValid() && key.isReadable()) { // a channel is ready for reading SelectableChannel channel = key.channel(); InetSocketAddress address = null; int messageLength = 0; ByteBuffer readBuffer = ByteBuffer.allocate(bufferSize); try { if (channel instanceof DatagramChannel) { address = (InetSocketAddress) ((DatagramChannel) channel).receive(readBuffer); } else if (channel instanceof SocketChannel) { address = (InetSocketAddress) ((SocketChannel) channel).getRemoteAddress(); ((SocketChannel) channel).read(readBuffer); } messageLength = readBuffer.position(); } catch (Exception e) { logger.warn("An exception occurred while reading data : '{}'", e.getMessage()); } if (address != null) { if (!interfaceAddresses.contains(address.getAddress())) { readBuffer.rewind(); ByteBuffer packetSize = readBuffer.slice(); packetSize.position(0); packetSize.limit(2); int size = Packet.FIELD_SIZE.value(packetSize); if (messageLength == size) { ByteBuffer packetType = readBuffer.slice(); packetType.position(32); packetType.limit(34); int type = Packet.FIELD_PACKET_TYPE.value(packetType); PacketHandler<?> handler = PacketFactory.createHandler(type); if (handler == null) { logger.trace( "Unknown packet type: {} (source: {})", String.format("0x%02X", type), address.toString()); continue; } Packet packet = handler.handle(readBuffer); if (packet == null) { logger.warn( "Handler {} was unable to handle packet", handler.getClass().getName()); } else { handlePacket(packet, address); } } } } } else if (key.isValid() && key.isWritable()) { // a channel is ready for writing // block of code only for completeness purposes } } } } catch (Exception e) { logger.error( "An exception occurred while receiving a packet from the bulb : '{}'", e.getMessage()); } finally { lock.unlock(); } }
static void releaseTemporarySelector(Selector sel) throws IOException { // Selector should be empty sel.selectNow(); // Flush cancelled keys assert sel.keys().isEmpty() : "Temporary selector not empty"; localSelectorWrapper.set(null); }
/** Performs a server cycle. */ private void cycle() { int loggedIn = 0; Benchmark b = Benchmarks.getBenchmark("loginQueue"); b.start(); while (!loginQueue.isEmpty() && loggedIn++ < 50) { Player player = loginQueue.poll(); try { player.finishLogin(); player.setLoginStage(LoginStages.LOGGED_IN); } catch (Exception ex) { // ex.printStackTrace(); System.out.println("Error, infinite DC loop for this player"); player.disconnect(); } } b.stop(); b = Benchmarks.getBenchmark("handleNetworkPackets"); b.start(); // Handle all network events. try { selector.selectNow(); for (SelectionKey selectionKey : selector.selectedKeys()) { if (selectionKey.isValid()) { if (selectionKey.isReadable()) { // Tell the client to handle the packet. PacketManager.handleIncomingData((Player) selectionKey.attachment()); } } } } catch (Exception ex) { ex.printStackTrace(); } b.stop(); // Next, perform game processing. try { PluginManager.tick(); World.process(); } catch (Exception ex) { ex.printStackTrace(); } b = Benchmarks.getBenchmark("disconnectingPlayers"); b.start(); synchronized (disconnectedPlayers) { for (Iterator<Player> players = disconnectedPlayers.iterator(); players.hasNext(); ) { Player player = players.next(); if (player.logoutDisabled()) continue; player.logout(); players.remove(); } } b.stop(); if (infoDisplayCounter == 0) { System.out.println( "[ENGINE]: Server load: " + cycle + "% with " + World.playerAmount() + " players"); infoDisplayCounter = 300; } else { infoDisplayCounter--; } }
final void selectNow() throws IOException { final Selector selector = this.selector; if (selector != null) { selector.selectNow(); } }
public boolean select(Channel channel, RubyIO io, int ops, long timeout) { if (channel instanceof SelectableChannel) { SelectableChannel selectable = (SelectableChannel) channel; synchronized (selectable.blockingLock()) { boolean oldBlocking = selectable.isBlocking(); SelectionKey key = null; try { selectable.configureBlocking(false); if (io != null) io.addBlockingThread(this); currentSelector = getRuntime().getSelectorPool().get(selectable.provider()); key = selectable.register(currentSelector, ops); beforeBlockingCall(); int result; if (timeout < 0) { result = currentSelector.select(); } else if (timeout == 0) { result = currentSelector.selectNow(); } else { result = currentSelector.select(timeout); } // check for thread events, in case we've been woken up to die pollThreadEvents(); if (result == 1) { Set<SelectionKey> keySet = currentSelector.selectedKeys(); if (keySet.iterator().next() == key) { return true; } } return false; } catch (IOException ioe) { throw getRuntime().newIOErrorFromException(ioe); } finally { // Note: I don't like ignoring these exceptions, but it's // unclear how likely they are to happen or what damage we // might do by ignoring them. Note that the pieces are separate // so that we can ensure one failing does not affect the others // running. // clean up the key in the selector try { if (key != null) key.cancel(); if (currentSelector != null) currentSelector.selectNow(); } catch (Exception e) { // ignore } // shut down and null out the selector try { if (currentSelector != null) { getRuntime().getSelectorPool().put(currentSelector); } } catch (Exception e) { // ignore } finally { currentSelector = null; } // remove this thread as a blocker against the given IO if (io != null) io.removeBlockingThread(this); // go back to previous blocking state on the selectable try { selectable.configureBlocking(oldBlocking); } catch (Exception e) { // ignore } // clear thread state from blocking call afterBlockingCall(); } } } else { // can't select, just have to do a blocking call return true; } }