/**
     * 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);
      }
    }
Exemple #5
0
 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();
     }
   }
 }