@GuardedBy("lock") private void setWriteOps() { // Make sure we are registered to get updated when writing is available again key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); // Refresh the selector to make sure it gets the new interestOps key.selector().wakeup(); }
/** Немедленно выключает интересуемое действие OP_READ */ protected void disableReadInterest() { try { _selectionKey.interestOps(_selectionKey.interestOps() & ~SelectionKey.OP_READ); } catch (CancelledKeyException e) { // ignore } }
private void processWritableKey(SelectionKey key) { CrawlURL url = (CrawlURL) key.attachment(); SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = (ByteBuffer) url.getHandlerAttr(_REQUEST_BUFFER); try { // 发送http请求,若发送完成,取消OP_WRITE。 int writtenBytes = 0; for (int i = WRITE_SPIN_COUNT; i > 0; i--) { writtenBytes = channel.write(buffer); // write success if (writtenBytes != 0) { url.setHandlerAttr(_LAST_SEND_REQUEST_MILLIS, System.currentTimeMillis()); url.setHandlerAttr( _REQUEST_ALREADY_SEND_SIZE, (Integer) url.getHandlerAttr(_REQUEST_ALREADY_SEND_SIZE) + writtenBytes); url.setHandlerAttr( _REQUEST_SEND_TIMES, (Integer) url.getHandlerAttr(_REQUEST_SEND_TIMES) + 1); break; } } boolean reqSendFinished = !buffer.hasRemaining(); url.setHandlerAttr(_REQUEST_SEND_FINISHED, reqSendFinished); url.setHandlerAttr(_REQUEST_SEND_FINISHED_MILLIS, reqSendFinished); if (reqSendFinished) { url.removeHandlerAttr(_REQUEST_BUFFER); key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); } } catch (IOException e) { logger.error("error send http request ! URL: " + url); cancelAndClose(key); url.setFetchStatus(FETCH_FAILED); url.getPipeline().resume(DefaultPipeline.EMPTY_MSG); } }
@Override protected void writeOP(SelectionKey key) throws IOException { RapidoidConnection conn = (RapidoidConnection) key.attachment(); SocketChannel socketChannel = (SocketChannel) key.channel(); checkOnSameThread(); try { int wrote = conn.output.writeTo(socketChannel); conn.output.deleteBefore(wrote); boolean complete = conn.output.size() == 0; if (conn.closeAfterWrite() && complete) { close(conn); } else { if (complete) { key.interestOps(SelectionKey.OP_READ); } else { key.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE); } conn.wrote(complete); } } catch (IOException e) { close(conn); } }
public static void chooseDispatcher(SocketChannel channel, int op) { if (channel.isRegistered()) { for (Dispatcher dispatcher : dispatchers) { SelectionKey key = channel.keyFor(dispatcher.getSelector()); if (key != null && key.isValid() && (key.interestOps() == op)) { return; } } for (Dispatcher dispatcher : dispatchers) { SelectionKey key = channel.keyFor(dispatcher.getSelector()); if (key != null && key.isValid() && (key.interestOps() == 0)) { if (op == SelectionKey.OP_READ) { dispatcher.addChannelForRead(channel); } else if (op == SelectionKey.OP_WRITE) { dispatcher.addChannelForWrite(channel); } return; } } } else { if (op == SelectionKey.OP_READ) { nextDispatcher().addChannelForRead(channel); } else if (op == SelectionKey.OP_WRITE) { nextDispatcher().addChannelForWrite(channel); } } }
/** Немедленно выключает интересуемое действие OP_WRITE */ protected void disableWriteInterest() { try { if (_isPengingWrite.compareAndSet(true, false)) _selectionKey.interestOps(_selectionKey.interestOps() & ~SelectionKey.OP_WRITE); } catch (CancelledKeyException e) { // ignore } }
private void removeInterest(int i) { if (selKey.isValid()) { selKey.interestOps(selKey.interestOps() & ~i); if (log.isDebugEnabled()) { log.debug("Interest now {}", selKey.interestOps()); } } }
private boolean resumeIfSuspended(final int ops) { final int interestOps = key.interestOps(); if ((interestOps & ops) == 0) { key.interestOps(interestOps | ops).selector().wakeup(); logger.debug("{} resumed {}", this, ops == SelectionKey.OP_READ ? "read" : "write"); return true; } else { return false; } }
private boolean suspendIfResumed(final int ops) { final int interestOps = key.interestOps(); if ((interestOps & ops) == ops) { key.interestOps(interestOps & ~ops); logger.debug("{} suspended {}", this, ops == SelectionKey.OP_READ ? "read" : "write"); return true; } else { return false; } }
void disableWrites() { if (writeChannel == null) return; try { final SelectionKey selectionKey = writeChannel.keyFor(this.selector); selectionKey.interestOps(selectionKey.interestOps() & ~OP_WRITE); } catch (Exception e) { LOG.error("", e); } }
// Remove connect interest from connected sockets // See: // http://stackoverflow.com/questions/204186/java-nio-select-returns-without-selected-keys-why private void processKey(SelectionKey key) { if ((key.readyOps() & SelectionKey.OP_CONNECT) != 0) { int interestOps = key.interestOps(); interestOps &= ~SelectionKey.OP_CONNECT; interestOps |= SelectionKey.OP_WRITE; key.interestOps(interestOps); } }
private void handleRemaining(int remaining) { if (remaining > 0) { // chunked channels should not fail assert !mChannel.isChunked(); // register for a write notification if a write fails mKey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); } else { mKey.interestOps(SelectionKey.OP_READ); } }
private void dispatch() throws IOException { SelectionKey key = null; for (SocketChannelOPSChangeRequest request : opsChangeRequstMap.values()) { key = request.getChannel().keyFor(selector); if (key != null) { // 写优先 if ((request.getOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) { key.interestOps(SelectionKey.OP_WRITE); request.clearOps(SelectionKey.OP_WRITE); } else if ((request.getOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) { key.interestOps(SelectionKey.OP_READ); request.clearOps(SelectionKey.OP_READ); } } } isWeakuped.set(false); if (selector.select(WaveriderConfig.WAVERIDER_DEFAULT_NETWORK_TIME_OUT) <= 0) { return; } Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { key = (SelectionKey) iterator.next(); iterator.remove(); try { if (!key.isValid()) { continue; } else if (key.isAcceptable()) { onAccept(key); } else if (key.isReadable()) { // readerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_READ)); onRead(key); } else if (key.isWritable()) { // writerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_WRITE)); onWrite(key); } } catch (IOException e) { // 客户端连接出问题 Session session = (Session) key.attachment(); if (session != null) { session.onException(); // 释放Session sessionManager.freeSession(session); } opsChangeRequstMap.remove((SocketChannel) key.channel()); key.cancel(); key.channel().close(); e.printStackTrace(); logger.error("OOPS:Exception:", e); } } }
private void enableWrites() { if (writeChannel == null) return; try { final SelectionKey selectionKey = writeChannel.keyFor(this.selector); if (selectionKey != null) selectionKey.interestOps(selectionKey.interestOps() | OP_WRITE); // we have just enabled it, so don't have to do this again. shouldEnableOpWrite = false; } catch (Exception e) { LOG.error("", e); } }
private void handleWritableChannel(SelectionKey key, SelectableChannel channel) { try { if (!key.isWritable()) return; ByteBuffer buffer = this.outputBuffers.get(channel); buffer.flip(); ((WritableByteChannel) channel).write(buffer); // If there aren't any bytes left to write from the buffer, tell the // selector that we no longer want to write to the channel (and-not // disables only that bit) if (0 == buffer.remaining()) key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); buffer.compact(); // The code below the catch blocks below is for error-handling only return; } catch (CancelledKeyException e) { // Error-handling code below to avoid code duplication } catch (ClosedChannelException e) { // Error-handling code below to avoid code duplication } catch (EOFException e) { // Error-handling code below to avoid code duplication } catch (IOException e) { reportIOException(e); // Continue with the error-handling code below } this.outputBuffers.remove(channel); // Close and remove any routes that point to this channel as an output Iterator<Map.Entry<SelectableChannel, SelectableChannel>> i = this.outputs.entrySet().iterator(); while (i.hasNext()) { Map.Entry<SelectableChannel, SelectableChannel> entry = i.next(); if (entry.getValue().equals(channel)) { closeChannelAndReportException(entry.getKey()); i.remove(); } } try { // No longer interested in handling this channel for write // operations key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); } catch (CancelledKeyException e) { // Do nothing } // The channel should already be closed, but just in case closeChannelAndReportException(channel); }
public void applyUpdates() { if (wasChanged.getAndSet(false)) { for (int i = changeOfOpWriteRequired.nextSetBit(0); i >= 0; i = changeOfOpWriteRequired.nextSetBit(i + 1)) { changeOfOpWriteRequired.clear(i); final SelectionKey key = selectionKeys[i]; try { key.interestOps(key.interestOps() | op); } catch (Exception e) { LOG.debug("", e); } } } }
/** * Handle OP_WRITE. * * @param key {@link SelectionKey} * @param ctx {@link Context} */ public boolean onWriteInterest(final SelectionKey key, final Context ctx) throws IOException { // disable OP_WRITE on key before doing anything else key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE)); if (asyncQueueWriter.isReady(key)) { invokeAsyncQueueWriter(pollContext(ctx, key, Context.OpType.OP_WRITE)); return false; } Object attach = SelectionKeyAttachment.getAttachment(key); if (attach instanceof CallbackHandler) { NIOContext context = pollContext(ctx, key, Context.OpType.OP_WRITE); invokeCallbackHandler((CallbackHandler) attach, context); return false; } return true; }
private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); synchronized (this.pendingData) { List queue = (List) this.pendingData.get(socketChannel); // Write until there's not more data ... while (!queue.isEmpty()) { ByteBuffer buf = (ByteBuffer) queue.get(0); socketChannel.write(buf); if (buf.remaining() > 0) { // ... or the socket's buffer fills up break; } queue.remove(0); } if (queue.isEmpty()) { // We wrote away all data, so we're no longer interested // in writing on this socket. Switch back to waiting for // data. key.interestOps(SelectionKey.OP_READ); } } }
/** Handle new OP_CONNECT ops. */ protected void onConnectOp(Context ctx, ConnectChannelOperation selectionKeyOp) throws IOException { SocketChannel socketChannel = (SocketChannel) selectionKeyOp.getChannel(); SocketAddress remoteAddress = selectionKeyOp.getRemoteAddress(); CallbackHandler callbackHandler = selectionKeyOp.getCallbackHandler(); CallbackHandlerSelectionKeyAttachment attachment = new CallbackHandlerSelectionKeyAttachment(callbackHandler); SelectionKey key = socketChannel.register(selector, 0, attachment); attachment.associateKey(key); boolean isConnected; try { isConnected = socketChannel.connect(remoteAddress); } catch (Exception e) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Exception occured when tried to connect socket", e); } // set isConnected to true to let callback handler to know about the problem happened isConnected = true; } // if channel was connected immediately or exception occured if (isConnected) { onConnectInterest(key, ctx); } else { key.interestOps(SelectionKey.OP_CONNECT); } }
private void queue_data(SelectionKey key, byte[] data) { SocketChannel channel = (SocketChannel) key.channel(); List<byte[]> pendingData = to_send.get(channel); key.interestOps(SelectionKey.OP_WRITE); pendingData.add(data); }
/** * Serves the incoming connections. * * @throws IOException * @throws DirectoryException */ private void serveIncomingConnections() throws IOException, DirectoryException { int selectorState = selector.select(); // We can't rely on return value of select to determine if any keys // are ready. // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4850373 for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext(); ) { SelectionKey key = iterator.next(); iterator.remove(); if (key.isAcceptable()) { // Accept the new client connection. ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel clientChannel = serverChannel.accept(); if (clientChannel != null) { acceptConnection(clientChannel); } } if (selectorState == 0 && enabled && !shutdownRequested && logger.isTraceEnabled()) { // Selected keys was non empty but select() returned 0. // Log warning and hope it blocks on the next select() call. logger.trace( "Selector.select() returned 0. " + "Selected Keys: %d, Interest Ops: %d, Ready Ops: %d ", selector.selectedKeys().size(), key.interestOps(), key.readyOps()); } } }
/** Writes data pending message into a specific socket defined by the key */ private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); synchronized (pendingWriteData) { List<ByteBuffer> queue = pendingWriteData.get(socketChannel); if (queue == null) { queue = new ArrayList<>(); pendingWriteData.put(socketChannel, queue); } // Write until there's no more data ... while (!queue.isEmpty()) { ByteBuffer buf = queue.get(0); socketChannel.write(buf); if (buf.remaining() > 0) { logger.finest("Write Buffer Full!"); break; } queue.remove(0); } if (queue.isEmpty()) { // All data written, change selector interest logger.finest("No more Data to write!"); key.interestOps(SelectionKey.OP_READ); } } }
private void doAsyncWrite(SelectionKey key) throws IOException { Call call = (Call) key.attachment(); if (call == null) { return; } if (key.channel() != call.connection.channel) { throw new IOException("doAsyncWrite: bad channel"); } synchronized (call.connection.responseQueue) { if (processResponse(call.connection.responseQueue, false)) { try { key.interestOps(0); } catch (CancelledKeyException e) { /* * The Listener/reader might have closed the socket. * We don't explicitly cancel the key, so not sure if this will * ever fire. * This warning could be removed. */ LOG.warn("Exception while changing ops : " + e); } } } }
@Override public void write(Multiplexer multiplexer, SelectionKey key) throws Exception { try { _socket.write(_command); if (_command.position() == _command.limit()) { if (_state == ReceiverState.SEND_BYE) { close(multiplexer, key, true); // TODO: Check true } else { key.interestOps(SelectionKey.OP_READ); } } } catch (ClosedChannelException e) { /* From GridFTP v2 spec: "...the sender may choose not * to wait for 'BYE' acknowledgement. The sender is * allowed to close data channels immediately after * sending EOD, and the receiver may get a socket * error trying to send 'BYE' message back to the * sender". */ if (_state == ReceiverState.SEND_BYE) { close(multiplexer, key, true); // TODO: Check true } else { throw e; } } }
private void write(SelectionKey key) throws IOException { SocketChannel ch = (SocketChannel) key.channel(); int count = 0; synchronized (pendingData) { List queue = (List) pendingData.get(ch); /** * Null exception alert: This can happen once a connection was established. Check send() for * more information. */ if (queue == null) return; while (!queue.isEmpty()) { ByteBuffer buf = (ByteBuffer) queue.get(0); ch.write(buf); count += buf.capacity() - buf.remaining(); if (buf.remaining() > 0) break; queue.remove(0); } if (queue.isEmpty()) key.interestOps(SelectionKey.OP_READ); } if (!listener.handleWrite(ch, count)) close(ch); }
public void run() { while (true) { try { synchronized (changeRequests) { Iterator changes = changeRequests.iterator(); while (changes.hasNext()) { ChangeRequest change = (ChangeRequest) changes.next(); switch (change.type) { case ChangeRequest.CHANGEOPS: SelectionKey key = change.socket.keyFor(selector); key.interestOps(change.ops); } } changeRequests.clear(); } selector.select(); Iterator selectedKeys = selector.selectedKeys().iterator(); while (selectedKeys.hasNext()) { SelectionKey key = (SelectionKey) selectedKeys.next(); selectedKeys.remove(); if (!key.isValid()) continue; if (key.isAcceptable()) accept(key); else if (key.isReadable()) read(key); else if (key.isWritable()) write(key); } } catch (IOException e) { e.printStackTrace(); } } }
@Override protected void write(SelectionKey selectionKey) throws IOException { if (!checkTimeout()) return; if (outputStream.getBuffer().hasRemaining()) { // If we have data, write what we can now... int count = socketChannel.write(outputStream.getBuffer()); if (logger.isTraceEnabled()) logger.trace( "Wrote " + count + " bytes, remaining: " + outputStream.getBuffer().remaining() + " for " + socketChannel.socket()); } else { if (logger.isTraceEnabled()) logger.trace("Wrote no bytes for " + socketChannel.socket()); } // If there's more to write but we didn't write it, we'll take that to // mean that we're done here. We don't clear or reset anything. We leave // our buffer state where it is and try our luck next time. if (outputStream.getBuffer().hasRemaining()) return; resetStreams(); // If we're not streaming writes, signal the Selector that we're // ready to read the next request. selectionKey.interestOps(SelectionKey.OP_READ); }
protected void writeBuffer(SocketChannel channel) throws IOException { synchronized (this.writeQueue) { ByteBuffer buffer = this.writeQueue.peek(); while (buffer != null) { writeSize += channel.write(buffer); if (buffer.hasRemaining()) { this.selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_WRITE); this.selectionKey.selector().wakeup(); break; } else { this.writeQueue.remove(); buffer = this.writeQueue.peek(); } } this.writeQueue.notifyAll(); } if (System.currentTimeMillis() - this.lastWriteTime > 1000) { writeSpeed = this.writeSize * 1.0 / (System.currentTimeMillis() - this.lastWriteTime); this.writeSize = 0; this.lastWriteTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { log.debug( String.format( "Write speed %1.3f Kb/s on %s.", this.writeSpeed, this.listener.toString())); if (this.writeQueue.size() > 0) { log.warn( String.format( "Write buffer queue size:%s, on %s", this.writeQueue.size(), this.listener.toString())); } } } }
public void write(ByteBuffer src, boolean sync) { if (this.selectionKey == null || !this.selectionKey.isValid()) return; // log.debug("wirte to DVR Video channel:" + src.remaining()); if (this.writeBusy()) { this.close(); // 写出错,设置网络超时错误。关闭连接。 try { this.listener.timeout(this); } catch (IOException e) { log.error(e.toString(), e); } } else if (this.writeQueue.offer(src)) { // 如果当前Socket没有注册写操作. if (this.writeQueue.size() == 1 && (this.selectionKey.interestOps() & SelectionKey.OP_WRITE) != SelectionKey.OP_WRITE) { this.selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_WRITE); this.selectionKey.selector().wakeup(); } } else { log.warn("Write buffer queue full, client:" + this.toString()); } while (sync && src.remaining() > 0) { synchronized (writeQueue) { try { writeQueue.wait(); } catch (InterruptedException e) { } } } }
/** * @throws IOException due to {@link SocketChannel#write(ByteBuffer)} call * @throws CancelledKeyException * @see * com.niffy.AndEngineLockStepEngine.threads.nio.BaseSelectorThread#write(java.nio.channels.SelectionKey) */ @Override protected void write(SelectionKey pKey) throws IOException, CancelledKeyException { DatagramChannel socketChannel; String connectionIP; socketChannel = (DatagramChannel) pKey.channel(); InetSocketAddress address = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); connectionIP = address.getAddress().getHostAddress(); InetSocketAddress target = (InetSocketAddress) pKey.attachment(); synchronized (this.mPendingData) { ArrayList<ByteBuffer> queue = this.mPendingData.get(target.getAddress()); // Write until there's not more data ... while (!queue.isEmpty()) { ByteBuffer buf = (ByteBuffer) queue.get(0); socketChannel.send(buf, target); if (buf.remaining() > 0) { // ... or the socket's buffer fills up break; } queue.remove(0); } if (queue.isEmpty()) { // We wrote away all data, so we're no longer interested // in writing on this socket. Switch back to waiting for // data. pKey.interestOps(SelectionKey.OP_READ); } } }