예제 #1
0
  private void write0(SctpChannelImpl channel) {
    boolean open = true;
    boolean addOpWrite = false;
    boolean removeOpWrite = false;

    long writtenBytes = 0;

    final SctpSendBufferPool sendBufferPool = this.sendBufferPool;
    final com.sun.nio.sctp.SctpChannel ch = channel.channel;
    final Queue<MessageEvent> writeBuffer = channel.writeBuffer;
    final int writeSpinCount = channel.getConfig().getWriteSpinCount();
    synchronized (channel.writeLock) {
      channel.inWriteNowLoop = true;
      for (; ; ) {
        MessageEvent evt = channel.currentWriteEvent;
        SendBuffer buf;
        if (evt == null) {
          if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) {
            removeOpWrite = true;
            channel.writeSuspended = false;
            break;
          }

          channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage());
        } else {
          buf = channel.currentWriteBuffer;
        }

        ChannelFuture future = evt.getFuture();
        try {
          long localWrittenBytes = 0;
          for (int i = writeSpinCount; i > 0; i--) {
            localWrittenBytes = buf.transferTo(ch);
            if (localWrittenBytes != 0) {
              writtenBytes += localWrittenBytes;
              break;
            }
            if (buf.finished()) {
              break;
            }
          }

          if (buf.finished()) {
            // Successful write - proceed to the next message.
            buf.release();
            channel.currentWriteEvent = null;
            channel.currentWriteBuffer = null;
            evt = null;
            buf = null;
            future.setSuccess();
          } else {
            // Not written fully - perhaps the kernel buffer is full.
            addOpWrite = true;
            channel.writeSuspended = true;

            if (localWrittenBytes > 0) {
              // Notify progress listeners if necessary.
              future.setProgress(localWrittenBytes, buf.writtenBytes(), buf.totalBytes());
            }
            break;
          }
        } catch (AsynchronousCloseException e) {
          // Doesn't need a user attention - ignore.
        } catch (Throwable t) {
          buf.release();
          channel.currentWriteEvent = null;
          channel.currentWriteBuffer = null;
          buf = null;
          evt = null;
          future.setFailure(t);
          fireExceptionCaught(channel, t);
          if (t instanceof IOException) {
            open = false;
            close(channel, succeededFuture(channel));
          }
        }
      }
      channel.inWriteNowLoop = false;
    }

    if (open) {
      if (addOpWrite) {
        setOpWrite(channel);
      } else if (removeOpWrite) {
        clearOpWrite(channel);
      }
    }

    fireWriteComplete(channel, writtenBytes);
  }
예제 #2
0
 void writeFromSelectorLoop(final SelectionKey k) {
   SctpChannelImpl ch = (SctpChannelImpl) k.attachment();
   ch.writeSuspended = false;
   write0(ch);
 }