/** * writes the contents of the buffer to the socket * * @param socketChannel the socket to publish the buffer to * @param approxTime an approximation of the current time in millis * @throws IOException */ private int writeBufferToSocket( @NotNull final SocketChannel socketChannel, final long approxTime) throws IOException { if (in.position() == 0) return 0; // if we still have some unwritten writer from last time lastSentTime = approxTime; out.limit((int) in.position()); final int len = socketChannel.write(out); if (LOG.isDebugEnabled()) LOG.debug("bytes-written=" + len); if (out.remaining() == 0) { out.clear(); in.clear(); } else { out.compact(); in.position(out.position()); in.limit(in.capacity()); out.clear(); } return len; }
/** blocks until connected */ @Override SelectableChannel doConnect() throws IOException, InterruptedException { boolean success = false; final SocketChannel socketChannel = SocketChannel.open(); try { socketChannel.configureBlocking(false); socketChannel.socket().setReuseAddress(true); socketChannel.socket().setSoLinger(false, 0); socketChannel.socket().setSoTimeout(0); socketChannel.socket().setTcpNoDelay(true); try { socketChannel.connect(details.address()); } catch (UnresolvedAddressException e) { this.connectLater(); } // Under experiment, the concoction was found to be more successful if we // paused before registering the OP_CONNECT Thread.sleep(10); // the registration has be be run on the same thread as the selector addPendingRegistration( new Runnable() { @Override public void run() { final Attached attached = new Attached(); attached.connector = ClientConnector.this; try { socketChannel.register(selector, OP_CONNECT, attached); } catch (ClosedChannelException e) { if (socketChannel.isOpen()) LOG.error("", e); } } }); selector.wakeup(); success = true; return socketChannel; } finally { if (!success) { try { try { socketChannel.socket().close(); } catch (Exception e) { LOG.error("", e); } socketChannel.close(); } catch (IOException e) { LOG.error("", e); } } } }
SelectableChannel doConnect() throws IOException, InterruptedException { final DatagramChannel server = DatagramChannel.open(); server.configureBlocking(false); // Kick off connection establishment try { // Create a non-blocking socket channel server.socket().setBroadcast(true); server.connect(socketAddress); } catch (IOException e) { if (LOG.isDebugEnabled()) LOG.debug("details=" + new Details(socketAddress, localIdentifier), e); connectLater(); return null; } server .setOption(SO_REUSEADDR, true) .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false) .setOption(StandardSocketOptions.SO_BROADCAST, true) .setOption(SO_REUSEADDR, true); if (networkInterface != null) server.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface); // the registration has be be run on the same thread as the selector addPendingRegistration( new Runnable() { @Override public void run() { try { server.register(selector, OP_WRITE); writeChannel = server; throttle(server); } catch (ClosedChannelException e) { LOG.error("", e); } } }); return server; }
/** * removes back in the OP_WRITE from the selector, otherwise it'll spin loop. The OP_WRITE will * get added back in as soon as we have data to write * * @param socketChannel the socketChannel we wish to stop writing to * @param attached data associated with the socketChannels key */ public synchronized void disableWrite( @NotNull final SocketChannel socketChannel, @NotNull final Attached attached) { try { SelectionKey key = socketChannel.keyFor(selector); if (key != null) { if (attached.isHandShakingComplete() && selector.isOpen()) { if (LOG.isDebugEnabled()) LOG.debug( "Disabling OP_WRITE to remoteIdentifier=" + attached.remoteIdentifier + ", localIdentifier=" + localIdentifier); key.interestOps(key.interestOps() & ~OP_WRITE); } } } catch (Exception e) { LOG.error("", e); } }
public void run() { while (shouldRun) { JobInProgress job = null; synchronized (jobInitQueue) { if (jobInitQueue.size() > 0) { job = (JobInProgress) jobInitQueue.elementAt(0); jobInitQueue.remove(job); } else { try { jobInitQueue.wait(JOBINIT_SLEEP_INTERVAL); } catch (InterruptedException iex) { } } } try { if (job != null) { job.initTasks(); } } catch (Exception e) { LOG.log(Level.WARNING, "job init failed", e); job.kill(); } } }