use of org.apache.nifi.remote.exception.UnknownPortException in project nifi by apache.
the class StandardRemoteGroupPort method onTrigger.
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) {
if (!remoteGroup.isTransmitting()) {
logger.debug("{} {} is not transmitting; will not send/receive", this, remoteGroup);
return;
}
if (getConnectableType() == ConnectableType.REMOTE_INPUT_PORT && session.getQueueSize().getObjectCount() == 0) {
logger.debug("{} No data to send", this);
return;
}
final String url = getRemoteProcessGroup().getTargetUri();
// If we are sending data, we need to ensure that we have at least 1 FlowFile to send. Otherwise,
// we don't want to create a transaction at all.
final FlowFile firstFlowFile;
if (getConnectableType() == ConnectableType.REMOTE_INPUT_PORT) {
firstFlowFile = session.get();
if (firstFlowFile == null) {
return;
}
} else {
firstFlowFile = null;
}
final SiteToSiteClient client = getSiteToSiteClient();
final Transaction transaction;
try {
transaction = client.createTransaction(transferDirection);
} catch (final PortNotRunningException e) {
context.yield();
this.targetRunning.set(false);
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port is not in a valid state", this, url);
logger.error(message);
session.rollback();
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
return;
} catch (final UnknownPortException e) {
context.yield();
this.targetExists.set(false);
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port no longer exists", this, url);
logger.error(message);
session.rollback();
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
return;
} catch (final UnreachableClusterException e) {
context.yield();
final String message = String.format("%s failed to communicate with %s due to %s", this, url, e.toString());
logger.error(message);
session.rollback();
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
return;
} catch (final IOException e) {
// we do not yield here because the 'peer' will be penalized, and we won't communicate with that particular nifi instance
// for a while due to penalization, but we can continue to talk to other nifi instances
final String message = String.format("%s failed to communicate with %s due to %s", this, url, e.toString());
logger.error(message);
if (logger.isDebugEnabled()) {
logger.error("", e);
}
session.rollback();
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
return;
}
if (transaction == null) {
logger.debug("{} Unable to create transaction to communicate with; all peers must be penalized, so yielding context", this);
session.rollback();
context.yield();
return;
}
try {
if (getConnectableType() == ConnectableType.REMOTE_INPUT_PORT) {
transferFlowFiles(transaction, context, session, firstFlowFile);
} else {
final int numReceived = receiveFlowFiles(transaction, context, session);
if (numReceived == 0) {
context.yield();
}
}
session.commit();
} catch (final Throwable t) {
final String message = String.format("%s failed to communicate with remote NiFi instance due to %s", this, t.toString());
logger.error("{} failed to communicate with remote NiFi instance due to {}", this, t.toString());
if (logger.isDebugEnabled()) {
logger.error("", t);
}
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
transaction.error();
session.rollback();
}
}
use of org.apache.nifi.remote.exception.UnknownPortException in project nifi by apache.
the class HttpClient method createTransaction.
@Override
public Transaction createTransaction(final TransferDirection direction) throws HandshakeException, PortNotRunningException, ProtocolException, UnknownPortException, IOException {
final int timeoutMillis = (int) config.getTimeout(TimeUnit.MILLISECONDS);
PeerStatus peerStatus;
while ((peerStatus = peerSelector.getNextPeerStatus(direction)) != null) {
logger.debug("peerStatus={}", peerStatus);
final CommunicationsSession commSession = new HttpCommunicationsSession();
final String nodeApiUrl = resolveNodeApiUrl(peerStatus.getPeerDescription());
final StringBuilder clusterUrls = new StringBuilder();
config.getUrls().forEach(url -> {
if (clusterUrls.length() > 0) {
clusterUrls.append(",");
clusterUrls.append(url);
}
});
final Peer peer = new Peer(peerStatus.getPeerDescription(), commSession, nodeApiUrl, clusterUrls.toString());
final int penaltyMillis = (int) config.getPenalizationPeriod(TimeUnit.MILLISECONDS);
String portId = config.getPortIdentifier();
if (StringUtils.isEmpty(portId)) {
portId = siteInfoProvider.getPortIdentifier(config.getPortName(), direction);
if (StringUtils.isEmpty(portId)) {
peer.close();
throw new IOException("Failed to determine the identifier of port " + config.getPortName());
}
}
final SiteToSiteRestApiClient apiClient = new SiteToSiteRestApiClient(config.getSslContext(), config.getHttpProxy(), config.getEventReporter());
apiClient.setBaseUrl(peer.getUrl());
apiClient.setConnectTimeoutMillis(timeoutMillis);
apiClient.setReadTimeoutMillis(timeoutMillis);
apiClient.setCacheExpirationMillis(config.getCacheExpiration(TimeUnit.MILLISECONDS));
apiClient.setLocalAddress(config.getLocalAddress());
apiClient.setCompress(config.isUseCompression());
apiClient.setRequestExpirationMillis(config.getIdleConnectionExpiration(TimeUnit.MILLISECONDS));
apiClient.setBatchCount(config.getPreferredBatchCount());
apiClient.setBatchSize(config.getPreferredBatchSize());
apiClient.setBatchDurationMillis(config.getPreferredBatchDuration(TimeUnit.MILLISECONDS));
final String transactionUrl;
try {
transactionUrl = apiClient.initiateTransaction(direction, portId);
commSession.setUserDn(apiClient.getTrustedPeerDn());
} catch (final Exception e) {
apiClient.close();
logger.warn("Penalizing a peer {} due to {}", peer, e.toString());
peerSelector.penalize(peer, penaltyMillis);
// Following exceptions will be thrown even if we tried other peers, so throw it.
if (e instanceof UnknownPortException || e instanceof PortNotRunningException || e instanceof HandshakeException) {
throw e;
}
logger.debug("Continue trying other peers...");
continue;
}
// We found a valid peer to communicate with.
final Integer transactionProtocolVersion = apiClient.getTransactionProtocolVersion();
final HttpClientTransaction transaction = new HttpClientTransaction(transactionProtocolVersion, peer, direction, config.isUseCompression(), portId, penaltyMillis, config.getEventReporter()) {
@Override
protected void close() throws IOException {
try {
super.close();
} finally {
activeTransactions.remove(this);
}
}
};
try {
transaction.initialize(apiClient, transactionUrl);
} catch (final Exception e) {
transaction.error();
throw e;
}
activeTransactions.add(transaction);
return transaction;
}
logger.info("Couldn't find a valid peer to communicate with.");
return null;
}
use of org.apache.nifi.remote.exception.UnknownPortException in project nifi by apache.
the class SiteToSiteRestApiClient method handleErrResponse.
private IOException handleErrResponse(final int responseCode, final InputStream in) throws IOException {
if (in == null) {
return new IOException("Unexpected response code: " + responseCode);
}
final TransactionResultEntity errEntity = readResponse(in);
final ResponseCode errCode = ResponseCode.fromCode(errEntity.getResponseCode());
switch(errCode) {
case UNKNOWN_PORT:
return new UnknownPortException(errEntity.getMessage());
case PORT_NOT_IN_VALID_STATE:
return new PortNotRunningException(errEntity.getMessage());
default:
switch(responseCode) {
case RESPONSE_CODE_FORBIDDEN:
return new HandshakeException(errEntity.getMessage());
default:
return new IOException("Unexpected response code: " + responseCode + " errCode:" + errCode + " errMessage:" + errEntity.getMessage());
}
}
}
use of org.apache.nifi.remote.exception.UnknownPortException in project nifi by apache.
the class EndpointConnectionPool method getEndpointConnection.
public EndpointConnection getEndpointConnection(final TransferDirection direction, final SiteToSiteClientConfig config) throws IOException {
//
// Attempt to get a connection state that already exists for this URL.
//
FlowFileCodec codec = null;
CommunicationsSession commsSession = null;
SocketClientProtocol protocol = null;
EndpointConnection connection;
Peer peer = null;
final URI clusterUrl;
try {
clusterUrl = siteInfoProvider.getActiveClusterUrl();
} catch (final IOException ioe) {
throw new UnreachableClusterException("Unable to refresh details from any of the configured remote instances.", ioe);
}
do {
final List<EndpointConnection> addBack = new ArrayList<>();
logger.debug("{} getting next peer status", this);
final PeerStatus peerStatus = peerSelector.getNextPeerStatus(direction);
logger.debug("{} next peer status = {}", this, peerStatus);
if (peerStatus == null) {
return null;
}
final PeerDescription peerDescription = peerStatus.getPeerDescription();
BlockingQueue<EndpointConnection> connectionQueue = connectionQueueMap.get(peerDescription);
if (connectionQueue == null) {
connectionQueue = new LinkedBlockingQueue<>();
BlockingQueue<EndpointConnection> existing = connectionQueueMap.putIfAbsent(peerDescription, connectionQueue);
if (existing != null) {
connectionQueue = existing;
}
}
try {
connection = connectionQueue.poll();
logger.debug("{} Connection State for {} = {}", this, clusterUrl, connection);
final String portId = getPortIdentifier(direction);
if (connection == null && !addBack.isEmpty()) {
// all available connections have been penalized.
logger.debug("{} all Connections for {} are penalized; returning no Connection", this, portId);
return null;
}
if (connection != null && connection.getPeer().isPenalized(portId)) {
// we have a connection, but it's penalized. We want to add it back to the queue
// when we've found one to use.
addBack.add(connection);
continue;
}
// if we can't get an existing Connection, create one
if (connection == null) {
logger.debug("{} No Connection available for Port {}; creating new Connection", this, portId);
protocol = new SocketClientProtocol();
protocol.setDestination(new IdEnrichedRemoteDestination(remoteDestination, portId));
protocol.setEventReporter(eventReporter);
final long penalizationMillis = remoteDestination.getYieldPeriod(TimeUnit.MILLISECONDS);
try {
logger.debug("{} Establishing site-to-site connection with {}", this, peerStatus);
commsSession = establishSiteToSiteConnection(peerStatus);
} catch (final IOException ioe) {
peerSelector.penalize(peerStatus.getPeerDescription(), penalizationMillis);
throw ioe;
}
final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
try {
logger.debug("{} Negotiating protocol", this);
RemoteResourceInitiator.initiateResourceNegotiation(protocol, dis, dos);
} catch (final HandshakeException e) {
try {
commsSession.close();
} catch (final IOException ioe) {
throw e;
}
}
final String peerUrl = "nifi://" + peerDescription.getHostname() + ":" + peerDescription.getPort();
peer = new Peer(peerDescription, commsSession, peerUrl, clusterUrl.toString());
// set properties based on config
if (config != null) {
protocol.setTimeout((int) config.getTimeout(TimeUnit.MILLISECONDS));
protocol.setPreferredBatchCount(config.getPreferredBatchCount());
protocol.setPreferredBatchSize(config.getPreferredBatchSize());
protocol.setPreferredBatchDuration(config.getPreferredBatchDuration(TimeUnit.MILLISECONDS));
}
// perform handshake
try {
logger.debug("{} performing handshake", this);
protocol.handshake(peer);
// handle error cases
if (protocol.isDestinationFull()) {
logger.warn("{} {} indicates that port {}'s destination is full; penalizing peer", this, peer, config.getPortName() == null ? config.getPortIdentifier() : config.getPortName());
peerSelector.penalize(peer, penalizationMillis);
try {
peer.close();
} catch (final IOException ioe) {
}
continue;
} else if (protocol.isPortInvalid()) {
peerSelector.penalize(peer, penalizationMillis);
cleanup(protocol, peer);
throw new PortNotRunningException(peer.toString() + " indicates that port " + portId + " is not running");
} else if (protocol.isPortUnknown()) {
peerSelector.penalize(peer, penalizationMillis);
cleanup(protocol, peer);
throw new UnknownPortException(peer.toString() + " indicates that port " + portId + " is not known");
}
// negotiate the FlowFileCodec to use
logger.debug("{} negotiating codec", this);
codec = protocol.negotiateCodec(peer);
logger.debug("{} negotiated codec is {}", this, codec);
} catch (final PortNotRunningException | UnknownPortException e) {
throw e;
} catch (final Exception e) {
peerSelector.penalize(peer, penalizationMillis);
cleanup(protocol, peer);
final String message = String.format("%s failed to communicate with %s due to %s", this, peer == null ? clusterUrl : peer, e.toString());
error(logger, eventReporter, message);
if (logger.isDebugEnabled()) {
logger.error("", e);
}
throw e;
}
connection = new EndpointConnection(peer, protocol, codec);
} else {
final long lastTimeUsed = connection.getLastTimeUsed();
final long millisSinceLastUse = System.currentTimeMillis() - lastTimeUsed;
if (commsTimeout > 0L && millisSinceLastUse >= commsTimeout) {
cleanup(connection.getSocketClientProtocol(), connection.getPeer());
connection = null;
} else {
codec = connection.getCodec();
peer = connection.getPeer();
commsSession = peer.getCommunicationsSession();
protocol = connection.getSocketClientProtocol();
}
}
} catch (final Throwable t) {
if (commsSession != null) {
try {
commsSession.close();
} catch (final IOException ioe) {
}
}
throw t;
} finally {
if (!addBack.isEmpty()) {
connectionQueue.addAll(addBack);
addBack.clear();
}
}
} while (connection == null || codec == null || commsSession == null || protocol == null);
activeConnections.add(connection);
return connection;
}
Aggregations