use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.
the class StandardRootGroupPort method transferFlowFiles.
@Override
public int transferFlowFiles(final Peer peer, final ServerProtocol serverProtocol) throws NotAuthorizedException, BadRequestException, RequestExpiredException {
if (getConnectableType() != ConnectableType.OUTPUT_PORT) {
throw new IllegalStateException("Cannot send FlowFiles because this port is not an Output Port");
}
if (!this.isRunning()) {
throw new IllegalStateException("Port not running");
}
try {
final FlowFileRequest request = new FlowFileRequest(peer, serverProtocol);
if (!this.requestQueue.offer(request)) {
throw new RequestExpiredException();
}
// Trigger this port to run
scheduler.registerEvent(this);
// Get a response from the response queue but don't wait forever if the port is stopped
ProcessingResult result = null;
// before the request expires
while (!request.isBeingServiced()) {
if (request.isExpired()) {
// Remove expired request, so that it won't block new request to be offered.
this.requestQueue.remove(request);
throw new SocketTimeoutException("Read timed out");
} else {
try {
Thread.sleep(100L);
} catch (final InterruptedException e) {
}
}
}
// we've started to service the request. Now just wait until it's finished
result = request.getResponseQueue().take();
final Exception problem = result.getProblem();
if (problem == null) {
return result.getFileCount();
} else {
throw problem;
}
} catch (final NotAuthorizedException | BadRequestException | RequestExpiredException e) {
throw e;
} catch (final ProtocolException e) {
throw new BadRequestException(e);
} catch (final Exception e) {
throw new ProcessException(e);
}
}
use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.
the class StandardRootGroupPort method receiveFlowFiles.
@Override
public int receiveFlowFiles(final Peer peer, final ServerProtocol serverProtocol) throws NotAuthorizedException, BadRequestException, RequestExpiredException {
if (getConnectableType() != ConnectableType.INPUT_PORT) {
throw new IllegalStateException("Cannot receive FlowFiles because this port is not an Input Port");
}
if (!this.isRunning()) {
throw new IllegalStateException("Port not running");
}
try {
final FlowFileRequest request = new FlowFileRequest(peer, serverProtocol);
if (!this.requestQueue.offer(request)) {
throw new RequestExpiredException();
}
// Trigger this port to run.
scheduler.registerEvent(this);
// Get a response from the response queue but don't wait forever if the port is stopped
ProcessingResult result = null;
// before the request expires
while (!request.isBeingServiced()) {
if (request.isExpired()) {
// Remove expired request, so that it won't block new request to be offered.
this.requestQueue.remove(request);
throw new SocketTimeoutException("Read timed out");
} else {
try {
Thread.sleep(100L);
} catch (final InterruptedException e) {
}
}
}
// we've started to service the request. Now just wait until it's finished
result = request.getResponseQueue().take();
final Exception problem = result.getProblem();
if (problem == null) {
return result.getFileCount();
} else {
throw problem;
}
} catch (final NotAuthorizedException | BadRequestException | RequestExpiredException e) {
throw e;
} catch (final ProtocolException e) {
throw new BadRequestException(e);
} catch (final Exception e) {
throw new ProcessException(e);
}
}
use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.
the class AbstractFlowFileServerProtocol method commitTransferTransaction.
protected int commitTransferTransaction(Peer peer, FlowFileTransaction transaction) throws IOException {
ProcessSession session = transaction.getSession();
Set<FlowFile> flowFilesSent = transaction.getFlowFilesSent();
// we've sent a FINISH_TRANSACTION. Now we'll wait for the peer to send a 'Confirm Transaction' response
CommunicationsSession commsSession = peer.getCommunicationsSession();
final Response transactionConfirmationResponse = readTransactionResponse(true, commsSession);
if (transactionConfirmationResponse.getCode() == ResponseCode.CONFIRM_TRANSACTION) {
// Confirm Checksum and echo back the confirmation.
logger.debug("{} Received {} from {}", this, transactionConfirmationResponse, peer);
final String receivedCRC = transactionConfirmationResponse.getMessage();
if (getVersionNegotiator().getVersion() > 3) {
String calculatedCRC = transaction.getCalculatedCRC();
if (!receivedCRC.equals(calculatedCRC)) {
writeTransactionResponse(true, ResponseCode.BAD_CHECKSUM, commsSession);
session.rollback();
throw new IOException(this + " Sent data to peer " + peer + " but calculated CRC32 Checksum as " + calculatedCRC + " while peer calculated CRC32 Checksum as " + receivedCRC + "; canceling transaction and rolling back session");
}
}
writeTransactionResponse(true, ResponseCode.CONFIRM_TRANSACTION, commsSession, "");
} else {
throw new ProtocolException("Expected to receive 'Confirm Transaction' response from peer " + peer + " but received " + transactionConfirmationResponse);
}
final String flowFileDescription = flowFilesSent.size() < 20 ? flowFilesSent.toString() : flowFilesSent.size() + " FlowFiles";
final Response transactionResponse;
try {
transactionResponse = readTransactionResponse(true, commsSession);
} catch (final IOException e) {
logger.error("{} Failed to receive a response from {} when expecting a TransactionFinished Indicator." + " It is unknown whether or not the peer successfully received/processed the data." + " Therefore, {} will be rolled back, possibly resulting in data duplication of {}", this, peer, session, flowFileDescription);
session.rollback();
throw e;
}
logger.debug("{} received {} from {}", new Object[] { this, transactionResponse, peer });
if (transactionResponse.getCode() == ResponseCode.TRANSACTION_FINISHED_BUT_DESTINATION_FULL) {
peer.penalize(port.getIdentifier(), port.getYieldPeriod(TimeUnit.MILLISECONDS));
} else if (transactionResponse.getCode() != ResponseCode.TRANSACTION_FINISHED) {
throw new ProtocolException("After sending data, expected TRANSACTION_FINISHED response but got " + transactionResponse);
}
session.commit();
StopWatch stopWatch = transaction.getStopWatch();
long bytesSent = transaction.getBytesSent();
stopWatch.stop();
final String uploadDataRate = stopWatch.calculateDataRate(bytesSent);
final long uploadMillis = stopWatch.getDuration(TimeUnit.MILLISECONDS);
final String dataSize = FormatUtils.formatDataSize(bytesSent);
logger.info("{} Successfully sent {} ({}) to {} in {} milliseconds at a rate of {}", new Object[] { this, flowFileDescription, dataSize, peer, uploadMillis, uploadDataRate });
return flowFilesSent.size();
}
use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.
the class AbstractFlowFileServerProtocol method commitReceiveTransaction.
protected int commitReceiveTransaction(Peer peer, FlowFileTransaction transaction) throws IOException {
CommunicationsSession commsSession = peer.getCommunicationsSession();
ProcessSession session = transaction.getSession();
final Response confirmTransactionResponse = readTransactionResponse(false, commsSession);
logger.debug("{} Received {} from {}", this, confirmTransactionResponse, peer);
switch(confirmTransactionResponse.getCode()) {
case CONFIRM_TRANSACTION:
break;
case BAD_CHECKSUM:
session.rollback();
throw new IOException(this + " Received a BadChecksum response from peer " + peer);
default:
throw new ProtocolException(this + " Received unexpected Response Code from peer " + peer + " : " + confirmTransactionResponse + "; expected 'Confirm Transaction' Response Code");
}
// Commit the session so that we have persisted the data
session.commit();
if (transaction.getContext().getAvailableRelationships().isEmpty()) {
// Confirm that we received the data and the peer can now discard it but that the peer should not
// send any more data for a bit
logger.debug("{} Sending TRANSACTION_FINISHED_BUT_DESTINATION_FULL to {}", this, peer);
writeTransactionResponse(false, ResponseCode.TRANSACTION_FINISHED_BUT_DESTINATION_FULL, commsSession);
} else {
// Confirm that we received the data and the peer can now discard it
logger.debug("{} Sending TRANSACTION_FINISHED to {}", this, peer);
writeTransactionResponse(false, ResponseCode.TRANSACTION_FINISHED, commsSession);
}
Set<FlowFile> flowFilesReceived = transaction.getFlowFilesSent();
long bytesReceived = transaction.getBytesSent();
StopWatch stopWatch = transaction.getStopWatch();
stopWatch.stop();
final String flowFileDescription = flowFilesReceived.size() < 20 ? flowFilesReceived.toString() : flowFilesReceived.size() + " FlowFiles";
final String uploadDataRate = stopWatch.calculateDataRate(bytesReceived);
final long uploadMillis = stopWatch.getDuration(TimeUnit.MILLISECONDS);
final String dataSize = FormatUtils.formatDataSize(bytesReceived);
logger.info("{} Successfully received {} ({}) from {} in {} milliseconds at a rate of {}", new Object[] { this, flowFileDescription, dataSize, peer, uploadMillis, uploadDataRate });
return flowFilesReceived.size();
}
use of org.apache.nifi.remote.exception.ProtocolException 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;
}
Aggregations