@Override public void close() throws IOException { closed = true; pool.shutdown(); }
@Override public Transaction createTransaction(final TransferDirection direction) throws IOException { if (closed) { throw new IllegalStateException("Client is closed"); } final String portId = getPortIdentifier(direction); if (portId == null) { throw new IOException( "Could not find Port with name '" + portName + "' for remote NiFi instance"); } final EndpointConnection connectionState = pool.getEndpointConnection(direction, getConfig()); if (connectionState == null) { return null; } final Transaction transaction; try { transaction = connectionState .getSocketClientProtocol() .startTransaction(connectionState.getPeer(), connectionState.getCodec(), direction); } catch (final Throwable t) { pool.terminate(connectionState); throw new IOException( "Unable to create Transaction to communicate with " + connectionState.getPeer(), t); } // Wrap the transaction in a new one that will return the EndpointConnectionState back to the // pool whenever // the transaction is either completed or canceled. final AtomicReference<EndpointConnection> connectionStateRef = new AtomicReference<>(connectionState); return new Transaction() { @Override public void confirm() throws IOException { transaction.confirm(); } @Override public TransactionCompletion complete() throws IOException { try { return transaction.complete(); } finally { final EndpointConnection state = connectionStateRef.get(); if (state != null) { pool.offer(connectionState); connectionStateRef.set(null); } } } @Override public void cancel(final String explanation) throws IOException { try { transaction.cancel(explanation); } finally { final EndpointConnection state = connectionStateRef.get(); if (state != null) { pool.terminate(connectionState); connectionStateRef.set(null); } } } @Override public void error() { try { transaction.error(); } finally { final EndpointConnection state = connectionStateRef.get(); if (state != null) { pool.terminate(connectionState); connectionStateRef.set(null); } } } @Override public void send(final DataPacket dataPacket) throws IOException { transaction.send(dataPacket); } @Override public void send(final byte[] content, final Map<String, String> attributes) throws IOException { transaction.send(content, attributes); } @Override public DataPacket receive() throws IOException { return transaction.receive(); } @Override public TransactionState getState() throws IOException { return transaction.getState(); } @Override public Communicant getCommunicant() { return transaction.getCommunicant(); } }; }