/*
 * Copyright 2015 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.UncheckedBooleanSupplier;

Default implementation of MaxMessagesRecvByteBufAllocator which respects ChannelConfig.isAutoRead() and also prevents overflow.
/** * Default implementation of {@link MaxMessagesRecvByteBufAllocator} which respects {@link ChannelConfig#isAutoRead()} * and also prevents overflow. */
public abstract class DefaultMaxMessagesRecvByteBufAllocator implements MaxMessagesRecvByteBufAllocator { private volatile int maxMessagesPerRead; private volatile boolean respectMaybeMoreData = true; public DefaultMaxMessagesRecvByteBufAllocator() { this(1); } public DefaultMaxMessagesRecvByteBufAllocator(int maxMessagesPerRead) { maxMessagesPerRead(maxMessagesPerRead); } @Override public int maxMessagesPerRead() { return maxMessagesPerRead; } @Override public MaxMessagesRecvByteBufAllocator maxMessagesPerRead(int maxMessagesPerRead) { if (maxMessagesPerRead <= 0) { throw new IllegalArgumentException("maxMessagesPerRead: " + maxMessagesPerRead + " (expected: > 0)"); } this.maxMessagesPerRead = maxMessagesPerRead; return this; }
Determine if future instances of RecvByteBufAllocator.newHandle() will stop reading if we think there is no more data.
Params:
  • respectMaybeMoreData –
    • true to stop reading if we think there is no more data. This may save a system call to read from the socket, but if data has arrived in a racy fashion we may give up our maxMessagesPerRead() quantum and have to wait for the selector to notify us of more data.
    • false to keep reading (up to maxMessagesPerRead()) or until there is no data when we attempt to read.
Returns:this.
/** * Determine if future instances of {@link #newHandle()} will stop reading if we think there is no more data. * @param respectMaybeMoreData * <ul> * <li>{@code true} to stop reading if we think there is no more data. This may save a system call to read from * the socket, but if data has arrived in a racy fashion we may give up our {@link #maxMessagesPerRead()} * quantum and have to wait for the selector to notify us of more data.</li> * <li>{@code false} to keep reading (up to {@link #maxMessagesPerRead()}) or until there is no data when we * attempt to read.</li> * </ul> * @return {@code this}. */
public DefaultMaxMessagesRecvByteBufAllocator respectMaybeMoreData(boolean respectMaybeMoreData) { this.respectMaybeMoreData = respectMaybeMoreData; return this; }
Get if future instances of RecvByteBufAllocator.newHandle() will stop reading if we think there is no more data.
Returns:
  • true to stop reading if we think there is no more data. This may save a system call to read from the socket, but if data has arrived in a racy fashion we may give up our maxMessagesPerRead() quantum and have to wait for the selector to notify us of more data.
  • false to keep reading (up to maxMessagesPerRead()) or until there is no data when we attempt to read.
/** * Get if future instances of {@link #newHandle()} will stop reading if we think there is no more data. * @return * <ul> * <li>{@code true} to stop reading if we think there is no more data. This may save a system call to read from * the socket, but if data has arrived in a racy fashion we may give up our {@link #maxMessagesPerRead()} * quantum and have to wait for the selector to notify us of more data.</li> * <li>{@code false} to keep reading (up to {@link #maxMessagesPerRead()}) or until there is no data when we * attempt to read.</li> * </ul> */
public final boolean respectMaybeMoreData() { return respectMaybeMoreData; }
Focuses on enforcing the maximum messages per read condition for continueReading().
/** * Focuses on enforcing the maximum messages per read condition for {@link #continueReading()}. */
public abstract class MaxMessageHandle implements ExtendedHandle { private ChannelConfig config; private int maxMessagePerRead; private int totalMessages; private int totalBytesRead; private int attemptedBytesRead; private int lastBytesRead; private final boolean respectMaybeMoreData = DefaultMaxMessagesRecvByteBufAllocator.this.respectMaybeMoreData; private final UncheckedBooleanSupplier defaultMaybeMoreSupplier = new UncheckedBooleanSupplier() { @Override public boolean get() { return attemptedBytesRead == lastBytesRead; } }; /** * Only {@link ChannelConfig#getMaxMessagesPerRead()} is used. */ @Override public void reset(ChannelConfig config) { this.config = config; maxMessagePerRead = maxMessagesPerRead(); totalMessages = totalBytesRead = 0; } @Override public ByteBuf allocate(ByteBufAllocator alloc) { return alloc.ioBuffer(guess()); } @Override public final void incMessagesRead(int amt) { totalMessages += amt; } @Override public void lastBytesRead(int bytes) { lastBytesRead = bytes; if (bytes > 0) { totalBytesRead += bytes; } } @Override public final int lastBytesRead() { return lastBytesRead; } @Override public boolean continueReading() { return continueReading(defaultMaybeMoreSupplier); } @Override public boolean continueReading(UncheckedBooleanSupplier maybeMoreDataSupplier) { return config.isAutoRead() && (!respectMaybeMoreData || maybeMoreDataSupplier.get()) && totalMessages < maxMessagePerRead && totalBytesRead > 0; } @Override public void readComplete() { } @Override public int attemptedBytesRead() { return attemptedBytesRead; } @Override public void attemptedBytesRead(int bytes) { attemptedBytesRead = bytes; } protected final int totalBytesRead() { return totalBytesRead < 0 ? Integer.MAX_VALUE : totalBytesRead; } } }