Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.flink.runtime.io.network.partition.consumer;
import org.apache.flink.runtime.metrics.groups.IOMetricGroup;
import org.apache.flink.runtime.event.TaskEvent;
import org.apache.flink.runtime.io.network.ConnectionID;
import org.apache.flink.runtime.io.network.ConnectionManager;
import org.apache.flink.runtime.io.network.buffer.Buffer;
import org.apache.flink.runtime.io.network.buffer.BufferProvider;
import org.apache.flink.runtime.io.network.netty.PartitionRequestClient;
import org.apache.flink.runtime.io.network.partition.PartitionNotFoundException;
import org.apache.flink.runtime.io.network.partition.ResultPartitionID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Tuple2;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.flink.util.Preconditions.checkNotNull;
import static org.apache.flink.util.Preconditions.checkState;
/**
* An input channel, which requests a remote partition queue.
*/
public class RemoteInputChannel extends InputChannel {
private static final Logger LOG = LoggerFactory.getLogger(RemoteInputChannel.class);
/** ID to distinguish this channel from other channels sharing the same TCP connection. */
private final InputChannelID id = new InputChannelID();
/** The connection to use to request the remote partition. */
private final ConnectionID connectionId;
/** The connection manager to use connect to the remote partition provider. */
private final ConnectionManager connectionManager;
/**
* The received buffers. Received buffers are enqueued by the network I/O thread and the queue
* is consumed by the receiving task thread.
*/
private final Queue receivedBuffers = new ArrayDeque();
/**
* Flag indicating whether this channel has been released. Either called by the receiving task
* thread or the task manager actor.
*/
private final AtomicBoolean isReleased = new AtomicBoolean();
/** Client to establish a (possibly shared) TCP connection and request the partition. */
private volatile PartitionRequestClient partitionRequestClient;
/**
* The next expected sequence number for the next buffer. This is modified by the network
* I/O thread only.
*/
private int expectedSequenceNumber = 0;
public RemoteInputChannel(
SingleInputGate inputGate,
int channelIndex,
ResultPartitionID partitionId,
ConnectionID connectionId,
ConnectionManager connectionManager,
IOMetricGroup metrics) {
this(inputGate, channelIndex, partitionId, connectionId, connectionManager,
new Tuple2(0, 0), metrics);
}
public RemoteInputChannel(
SingleInputGate inputGate,
int channelIndex,
ResultPartitionID partitionId,
ConnectionID connectionId,
ConnectionManager connectionManager,
Tuple2 initialAndMaxBackoff,
IOMetricGroup metrics) {
super(inputGate, channelIndex, partitionId, initialAndMaxBackoff, metrics.getNumBytesInRemoteCounter());
this.connectionId = checkNotNull(connectionId);
this.connectionManager = checkNotNull(connectionManager);
}
// ------------------------------------------------------------------------
// Consume
// ------------------------------------------------------------------------
/**
* Requests a remote subpartition.
*/
@Override
void requestSubpartition(int subpartitionIndex) throws IOException, InterruptedException {
if (partitionRequestClient == null) {
// Create a client and request the partition
partitionRequestClient = connectionManager
.createPartitionRequestClient(connectionId);
partitionRequestClient.requestSubpartition(partitionId, subpartitionIndex, this, 0);
}
}
/**
* Retriggers a remote subpartition request.
*/
void retriggerSubpartitionRequest(int subpartitionIndex) throws IOException, InterruptedException {
checkState(partitionRequestClient != null, "Missing initial subpartition request.");
if (increaseBackoff()) {
partitionRequestClient.requestSubpartition(
partitionId, subpartitionIndex, this, getCurrentBackoff());
}
else {
failPartitionRequest();
}
}
@Override
Buffer getNextBuffer() throws IOException {
checkState(!isReleased.get(), "Queried for a buffer after channel has been closed.");
checkState(partitionRequestClient != null, "Queried for a buffer before requesting a queue.");
checkError();
synchronized (receivedBuffers) {
Buffer buffer = receivedBuffers.poll();
// Sanity check that channel is only queried after a notification
if (buffer == null) {
throw new IOException("Queried input channel for data although non is available.");
}
numBytesIn.inc(buffer.getSize());
return buffer;
}
}
// ------------------------------------------------------------------------
// Task events
// ------------------------------------------------------------------------
@Override
void sendTaskEvent(TaskEvent event) throws IOException {
checkState(!isReleased.get(), "Tried to send task event to producer after channel has been released.");
checkState(partitionRequestClient != null, "Tried to send task event to producer before requesting a queue.");
checkError();
partitionRequestClient.sendTaskEvent(partitionId, event, this);
}
// ------------------------------------------------------------------------
// Life cycle
// ------------------------------------------------------------------------
@Override
boolean isReleased() {
return isReleased.get();
}
@Override
void notifySubpartitionConsumed() {
// Nothing to do
}
/**
* Releases all received buffers and closes the partition request client.
*/
@Override
void releaseAllResources() throws IOException {
if (isReleased.compareAndSet(false, true)) {
synchronized (receivedBuffers) {
Buffer buffer;
while ((buffer = receivedBuffers.poll()) != null) {
buffer.recycle();
}
}
// The released flag has to be set before closing the connection to ensure that
// buffers received concurrently with closing are properly recycled.
if (partitionRequestClient != null) {
partitionRequestClient.close(this);
}
else {
connectionManager.closeOpenChannelConnections(connectionId);
}
}
}
public void failPartitionRequest() {
setError(new PartitionNotFoundException(partitionId));
}
@Override
public String toString() {
return "RemoteInputChannel [" + partitionId + " at " + connectionId + "]";
}
// ------------------------------------------------------------------------
// Network I/O notifications (called by network I/O thread)
// ------------------------------------------------------------------------
public int getNumberOfQueuedBuffers() {
synchronized (receivedBuffers) {
return receivedBuffers.size();
}
}
public InputChannelID getInputChannelId() {
return id;
}
public BufferProvider getBufferProvider() throws IOException {
if (isReleased.get()) {
return null;
}
return inputGate.getBufferProvider();
}
public void onBuffer(Buffer buffer, int sequenceNumber) {
boolean success = false;
try {
synchronized (receivedBuffers) {
if (!isReleased.get()) {
if (expectedSequenceNumber == sequenceNumber) {
receivedBuffers.add(buffer);
expectedSequenceNumber++;
notifyAvailableBuffer();
success = true;
}
else {
onError(new BufferReorderingException(expectedSequenceNumber, sequenceNumber));
}
}
}
}
finally {
if (!success) {
buffer.recycle();
}
}
}
public void onEmptyBuffer(int sequenceNumber) {
synchronized (receivedBuffers) {
if (!isReleased.get()) {
if (expectedSequenceNumber == sequenceNumber) {
expectedSequenceNumber++;
}
else {
onError(new BufferReorderingException(expectedSequenceNumber, sequenceNumber));
}
}
}
}
public void onFailedPartitionRequest() {
inputGate.triggerPartitionStateCheck(partitionId);
}
public void onError(Throwable cause) {
setError(cause);
}
public static class BufferReorderingException extends IOException {
private static final long serialVersionUID = -888282210356266816L;
private final int expectedSequenceNumber;
private final int actualSequenceNumber;
public BufferReorderingException(int expectedSequenceNumber, int actualSequenceNumber) {
this.expectedSequenceNumber = expectedSequenceNumber;
this.actualSequenceNumber = actualSequenceNumber;
}
@Override
public String getMessage() {
return String.format("Buffer re-ordering: expected buffer with sequence number %d, but received %d.",
expectedSequenceNumber, actualSequenceNumber);
}
}
}