text:
package org.apache.ignite.internal.jdbc.thin;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.sql.Array;
import java.sql.BatchUpdateException;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLPermission;
import java.sql.SQLTimeoutException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.query.QueryCancelledException;
import org.apache.ignite.internal.jdbc2.JdbcUtils;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheUtils;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
import org.apache.ignite.internal.processors.odbc.SqlStateCode;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBulkLoadBatchRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcCachePartitionsRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcCachePartitionsResult;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcOrderedBatchExecuteRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcOrderedBatchExecuteResult;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCancelRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResultWithIo;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
import org.apache.ignite.internal.sql.command.SqlCommand;
import org.apache.ignite.internal.sql.command.SqlSetStreamingCommand;
import org.apache.ignite.internal.sql.optimizer.affinity.PartitionClientContext;
import org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult;
import org.apache.ignite.internal.util.HostAndPortRange;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.lang.IgniteProductVersion;
import org.jetbrains.annotations.Nullable;

import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
import static java.sql.ResultSet.CONCUR_READ_ONLY;
import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
import static org.apache.ignite.internal.processors.odbc.SqlStateCode.CLIENT_CONNECTION_FAILED;
import static org.apache.ignite.internal.processors.odbc.SqlStateCode.CONNECTION_CLOSED;
import static org.apache.ignite.internal.processors.odbc.SqlStateCode.CONNECTION_FAILURE;
import static org.apache.ignite.internal.processors.odbc.SqlStateCode.INTERNAL_ERROR;

/**
 * JDBC connection implementation.
 *
 * See documentation of {@link org.apache.ignite.IgniteJdbcThinDriver} for details.
 */
public class JdbcThinConnection implements Connection {
    /** Logger. */
    private static final Logger LOG = Logger.getLogger(JdbcThinConnection.class.getName());

    /** Request timeout period. */
    private static final int REQUEST_TIMEOUT_PERIOD = 1_000;

    /** Reconnection period. */
    public static final int RECONNECTION_DELAY = 200;

    /** Reconnection maximum period. */
    private static final int RECONNECTION_MAX_DELAY = 300_000;

    /** Network timeout permission */
    private static final String SET_NETWORK_TIMEOUT_PERM = "setNetworkTimeout";

    /** Zero timeout as query timeout means no timeout. */
    static final int NO_TIMEOUT = 0;

    /** Index generator. */
    private static final AtomicLong IDX_GEN = new AtomicLong();

    /** Default retires count. */
    public static final int DFLT_RETRIES_CNT = 4;

    /** No retries. */
    public static final int NO_RETRIES = 0;

    /** Partition awareness enabled flag. */
    private final boolean partitionAwareness;

    /** Statements modification mutex. */
    private final Object stmtsMux = new Object();

    /** Schema name. */
    private String schema;

    /** Closed flag. */
    private volatile boolean closed;

    /** Current transaction isolation. */
    private int txIsolation;

    /** Auto-commit flag. */
    private boolean autoCommit;

    /** Read-only flag. */
    private boolean readOnly;

    /** Streaming flag. */
    private volatile StreamState streamState;

    /** Current transaction holdability. */
    private int holdability;

    /** Jdbc metadata. Cache the JDBC object on the first access */
    private JdbcThinDatabaseMetadata metadata;

    /** Connection properties. */
    private final ConnectionProperties connProps;

    /** The amount of potentially alive {@code JdbcThinTcpIo} instances - connections to server nodes. */
    private final AtomicInteger connCnt = new AtomicInteger();

    /** Tracked statements to close on disconnect. */
    private final Set<JdbcThinStatement> stmts = Collections.newSetFromMap(new IdentityHashMap<>());

    /** Affinity cache. */
    private AffinityCache affinityCache;

    /** Ignite endpoint. */
    private volatile JdbcThinTcpIo singleIo;

    /** Node Ids tp ignite endpoints. */
    private final ConcurrentSkipListMap<UUID, JdbcThinTcpIo> ios = new ConcurrentSkipListMap<>();

    /** Server index. */
    private int srvIdx;

    /** Ignite server version. */
    private Thread ownThread;

    /** Mutex. */
    private final Object mux = new Object();

    /** Ignite endpoint to use within transactional context. */
    private volatile JdbcThinTcpIo txIo;

    /** Random generator. */
    private static final Random RND = new Random(System.currentTimeMillis());

    /** Network timeout. */
    private int netTimeout;

    /** Query timeout. */
    private int qryTimeout;

    /** Background periodical maintenance: query timeouts and reconnection handler. */
    private final ScheduledExecutorService maintenanceExecutor = Executors.newScheduledThreadPool(2);

    /** Cancelable future for query timeout task. */
    private ScheduledFuture<?> qryTimeoutScheduledFut;

    /** Cancelable future for connections handler task. */
    private ScheduledFuture<?> connectionsHndScheduledFut;

    /** Connections handler timer. */
    private final IgniteProductVersion baseEndpointVer;

    /**
     * Creates new connection.
     *
     * @param connProps Connection properties.
     * @throws SQLException In case Ignite client failed to start.
     */
    public JdbcThinConnection(ConnectionProperties connProps) throws SQLException {
        this.connProps = connProps;

        holdability = HOLD_CURSORS_OVER_COMMIT;
        autoCommit = true;
        txIsolation = Connection.TRANSACTION_NONE;
        netTimeout = connProps.getConnectionTimeout();
        qryTimeout = connProps.getQueryTimeout();

        schema = JdbcUtils.normalizeSchema(connProps.getSchema());

        partitionAwareness = connProps.isPartitionAwareness();

        if (partitionAwareness) {
            baseEndpointVer = connectInBestEffortAffinityMode(null);

            connectionsHndScheduledFut = maintenanceExecutor.scheduleWithFixedDelay(new ConnectionHandlerTask(),
                0, RECONNECTION_DELAY, TimeUnit.MILLISECONDS);
        }
        else {
            connectInCommonMode();

            baseEndpointVer = null;
        }
    }

    /**
     * @throws SQLException On connection error.
     */
    private void ensureConnected() throws SQLException {
        if (connCnt.get() > 0)
            return;

        assert !closed;

        assert ios.isEmpty();

        if (partitionAwareness)
            connectInBestEffortAffinityMode(baseEndpointVer);
        else
            connectInCommonMode();
    }

    /**
     * @return Whether this connection is streamed or not.
     */
    boolean isStream() {
        return streamState != null;
    }

    /**
     * @param sql Statement.
     * @param cmd Parsed form of {@code sql}.
     * @param stmt Jdbc thin statement.
     * @throws SQLException if failed.
     */
    void executeNative(String sql, SqlCommand cmd, JdbcThinStatement stmt) throws SQLException {
        if (cmd instanceof SqlSetStreamingCommand) {
            SqlSetStreamingCommand cmd0 = (SqlSetStreamingCommand)cmd;

            // If streaming is already on, we have to close it first.
            if (streamState != null) {
                streamState.close();

                streamState = null;
            }

            boolean newVal = ((SqlSetStreamingCommand)cmd).isTurnOn();

            ensureConnected();

            JdbcThinTcpIo cliIo = cliIo(null);

            // Actual ON, if needed.
            if (newVal) {
                if (!cmd0.isOrdered() && !cliIo.isUnorderedStreamSupported()) {
                    throw new SQLException("Streaming without order doesn't supported by server [remoteNodeVer="
                        + cliIo.igniteVersion() + ']', INTERNAL_ERROR);
                }

                streamState = new StreamState((SqlSetStreamingCommand)cmd, cliIo);

                sendRequest(new JdbcQueryExecuteRequest(JdbcStatementType.ANY_STATEMENT_TYPE,
                    schema, 1, 1, autoCommit, sql, null), stmt, cliIo);

                streamState.start();
            }
        }
        else
            throw IgniteQueryErrorCode.createJdbcSqlException("Unsupported native statement: " + sql,
                IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }

    /**
     * Add another query for batched execution.
     *
     * @param sql Query.
     * @param args Arguments.
     * @throws SQLException On error.
     */
    void addBatch(String sql, List<Object> args) throws SQLException {
        assert isStream();

        streamState.addBatch(sql, args);
    }

    /** {@inheritDoc} */
    @Override public Statement createStatement() throws SQLException {
        return createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
    }

    /** {@inheritDoc} */
    @Override public Statement createStatement(int resSetType, int resSetConcurrency) throws SQLException {
        return createStatement(resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
    }

    /** {@inheritDoc} */
    @Override public Statement createStatement(int resSetType, int resSetConcurrency,
        int resSetHoldability) throws SQLException {
        ensureNotClosed();

        checkCursorOptions(resSetType, resSetConcurrency);

        JdbcThinStatement stmt = new JdbcThinStatement(this, resSetHoldability, schema);

        stmt.setQueryTimeout(qryTimeout);

        synchronized (stmtsMux) {
            stmts.add(stmt);
        }

        return stmt;
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql) throws SQLException {
        return prepareStatement(sql, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql, int resSetType,
        int resSetConcurrency) throws SQLException {
        return prepareStatement(sql, resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql, int resSetType, int resSetConcurrency,
        int resSetHoldability) throws SQLException {
        ensureNotClosed();

        checkCursorOptions(resSetType, resSetConcurrency);

        if (sql == null)
            throw new SQLException("SQL string cannot be null.");

        JdbcThinPreparedStatement stmt = new JdbcThinPreparedStatement(this, sql, resSetHoldability, schema);

        synchronized (stmtsMux) {
            stmts.add(stmt);
        }

        return stmt;
    }

    /**
     * @param resSetType Cursor option.
     * @param resSetConcurrency Cursor option.
     * @throws SQLException If options unsupported.
     */
    private void checkCursorOptions(int resSetType, int resSetConcurrency) throws SQLException {
        if (resSetType != TYPE_FORWARD_ONLY)
            throw new SQLFeatureNotSupportedException("Invalid result set type (only forward is supported).");

        if (resSetConcurrency != CONCUR_READ_ONLY)
            throw new SQLFeatureNotSupportedException("Invalid concurrency (updates are not supported).");
    }

    /** {@inheritDoc} */
    @Override public CallableStatement prepareCall(String sql) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
    }

    /** {@inheritDoc} */
    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency)
        throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
    }

    /** {@inheritDoc} */
    @Override public String nativeSQL(String sql) throws SQLException {
        ensureNotClosed();

        if (sql == null)
            throw new SQLException("SQL string cannot be null.");

        return sql;
    }

    /** {@inheritDoc} */
    @Override public void setAutoCommit(boolean autoCommit) throws SQLException {
        ensureNotClosed();

        // Do nothing if resulting value doesn't actually change.
        if (autoCommit != this.autoCommit) {
            doCommit();

            this.autoCommit = autoCommit;
        }
    }

    /** {@inheritDoc} */
    @Override public boolean getAutoCommit() throws SQLException {
        ensureNotClosed();

        return autoCommit;
    }

    /** {@inheritDoc} */
    @Override public void commit() throws SQLException {
        ensureNotClosed();

        if (autoCommit)
            throw new SQLException("Transaction cannot be committed explicitly in auto-commit mode.");

        doCommit();
    }

    /** {@inheritDoc} */
    @Override public void rollback() throws SQLException {
        ensureNotClosed();

        if (autoCommit)
            throw new SQLException("Transaction cannot be rolled back explicitly in auto-commit mode.");

        try (Statement s = createStatement()) {
            s.execute("ROLLBACK");
        }
    }

    /**
     * Send to the server {@code COMMIT} command.
     *
     * @throws SQLException if failed.
     */
    private void doCommit() throws SQLException {
        try (Statement s = createStatement()) {
            s.execute("COMMIT");
        }
    }

    /** {@inheritDoc} */
    @Override public void close() throws SQLException {
        if (isClosed())
            return;

        closed = true;

        maintenanceExecutor.shutdown();

        if (streamState != null) {
            streamState.close();

            streamState = null;
        }

        synchronized (stmtsMux) {
            stmts.clear();
        }

        SQLException err = null;

        if (partitionAwareness) {
            for (JdbcThinTcpIo clioIo : ios.values())
                clioIo.close();

            ios.clear();
        }
        else {
            if (singleIo != null)
                singleIo.close();
        }

        if (err != null)
            throw err;
    }

    /** {@inheritDoc} */
    @Override public boolean isClosed() {
        return closed;
    }

    /** {@inheritDoc} */
    @Override public DatabaseMetaData getMetaData() throws SQLException {
        ensureNotClosed();

        if (metadata == null)
            metadata = new JdbcThinDatabaseMetadata(this);

        return metadata;
    }

    /** {@inheritDoc} */
    @Override public void setReadOnly(boolean readOnly) throws SQLException {
        ensureNotClosed();

        this.readOnly = readOnly;
    }

    /** {@inheritDoc} */
    @Override public boolean isReadOnly() throws SQLException {
        ensureNotClosed();

        return readOnly;
    }

    /** {@inheritDoc} */
    @Override public void setCatalog(String catalog) throws SQLException {
        ensureNotClosed();
    }

    /** {@inheritDoc} */
    @Override public String getCatalog() throws SQLException {
        ensureNotClosed();

        return null;
    }

    /** {@inheritDoc} */
    @Override public void setTransactionIsolation(int level) throws SQLException {
        ensureNotClosed();

        switch (level) {
            case Connection.TRANSACTION_READ_UNCOMMITTED:
            case Connection.TRANSACTION_READ_COMMITTED:
            case Connection.TRANSACTION_REPEATABLE_READ:
            case Connection.TRANSACTION_SERIALIZABLE:
            case Connection.TRANSACTION_NONE:
                break;

            default:
                throw new SQLException("Invalid transaction isolation level.", SqlStateCode.INVALID_TRANSACTION_LEVEL);
        }

        txIsolation = level;
    }

    /** {@inheritDoc} */
    @Override public int getTransactionIsolation() throws SQLException {
        ensureNotClosed();

        return txIsolation;
    }

    /** {@inheritDoc} */
    @Override public SQLWarning getWarnings() throws SQLException {
        ensureNotClosed();

        return null;
    }

    /** {@inheritDoc} */
    @Override public void clearWarnings() throws SQLException {
        ensureNotClosed();
    }

    /** {@inheritDoc} */
    @Override public Map<String, Class<?>> getTypeMap() throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
    }

    /** {@inheritDoc} */
    @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
    }

    /** {@inheritDoc} */
    @Override public void setHoldability(int holdability) throws SQLException {
        ensureNotClosed();

        if (holdability != HOLD_CURSORS_OVER_COMMIT && holdability != CLOSE_CURSORS_AT_COMMIT)
            throw new SQLException("Invalid result set holdability value.");

        this.holdability = holdability;
    }

    /** {@inheritDoc} */
    @Override public int getHoldability() throws SQLException {
        ensureNotClosed();

        return holdability;
    }

    /** {@inheritDoc} */
    @Override public Savepoint setSavepoint() throws SQLException {
        ensureNotClosed();

        if (autoCommit)
            throw new SQLException("Savepoint cannot be set in auto-commit mode.");

        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
    }

    /** {@inheritDoc} */
    @Override public Savepoint setSavepoint(String name) throws SQLException {
        ensureNotClosed();

        if (name == null)
            throw new SQLException("Savepoint name cannot be null.");

        if (autoCommit)
            throw new SQLException("Savepoint cannot be set in auto-commit mode.");

        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
    }

    /** {@inheritDoc} */
    @Override public void rollback(Savepoint savepoint) throws SQLException {
        ensureNotClosed();

        if (savepoint == null)
            throw new SQLException("Invalid savepoint.");

        if (autoCommit)
            throw new SQLException("Auto-commit mode.");

        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
    }

    /** {@inheritDoc} */
    @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        ensureNotClosed();

        if (savepoint == null)
            throw new SQLException("Savepoint cannot be null.");

        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
    }

    /** {@inheritDoc} */
    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency,
        int resSetHoldability) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql, int[] colIndexes) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
    }

    /** {@inheritDoc} */
    @Override public PreparedStatement prepareStatement(String sql, String[] colNames) throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
    }

    /** {@inheritDoc} */
    @Override public Clob createClob() throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public Blob createBlob() throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public NClob createNClob() throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public SQLXML createSQLXML() throws SQLException {
        ensureNotClosed();

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public boolean isValid(int timeout) throws SQLException {
        if (timeout < 0)
            throw new SQLException("Invalid timeout: " + timeout);

        return !closed;
    }

    /** {@inheritDoc} */
    @Override public void setClientInfo(String name, String val) throws SQLClientInfoException {
        if (closed)
            throw new SQLClientInfoException("Connection is closed.", null);
    }

    /** {@inheritDoc} */
    @Override public void setClientInfo(Properties props) throws SQLClientInfoException {
        if (closed)
            throw new SQLClientInfoException("Connection is closed.", null);
    }

    /** {@inheritDoc} */
    @Override public String getClientInfo(String name) throws SQLException {
        ensureNotClosed();

        return null;
    }

    /** {@inheritDoc} */
    @Override public Properties getClientInfo() throws SQLException {
        ensureNotClosed();

        return new Properties();
    }

    /** {@inheritDoc} */
    @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        ensureNotClosed();

        if (typeName == null)
            throw new SQLException("Type name cannot be null.");

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public Struct createStruct(String typeName, Object[] attrs) throws SQLException {
        ensureNotClosed();

        if (typeName == null)
            throw new SQLException("Type name cannot be null.");

        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
    }

    /** {@inheritDoc} */
    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
        if (!isWrapperFor(iface))
            throw new SQLException("Connection is not a wrapper for " + iface.getName());

        return (T)this;
    }

    /** {@inheritDoc} */
    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return iface != null && iface.isAssignableFrom(JdbcThinConnection.class);
    }

    /** {@inheritDoc} */
    @Override public void setSchema(String schema) throws SQLException {
        ensureNotClosed();

        this.schema = JdbcUtils.normalizeSchema(schema);
    }

    /** {@inheritDoc} */
    @Override public String getSchema() throws SQLException {
        ensureNotClosed();

        return schema;
    }

    /** {@inheritDoc} */
    @Override public void abort(Executor executor) throws SQLException {
        if (executor == null)
            throw new SQLException("Executor cannot be null.");

        close();
    }

    /** {@inheritDoc} */
    @Override public void setNetworkTimeout(Executor executor, int ms) throws SQLException {
        ensureNotClosed();

        if (ms < 0)
            throw new SQLException("Network timeout cannot be negative.");

        SecurityManager secMgr = System.getSecurityManager();

        if (secMgr != null)
            secMgr.checkPermission(new SQLPermission(SET_NETWORK_TIMEOUT_PERM));

        netTimeout = ms;

        if (partitionAwareness) {
            for (JdbcThinTcpIo clioIo : ios.values())
                clioIo.timeout(ms);
        }
        else
            singleIo.timeout(ms);
    }

    /** {@inheritDoc} */
    @Override public int getNetworkTimeout() throws SQLException {
        ensureNotClosed();

        return netTimeout;
    }

    /**
     * Ensures that connection is not closed.
     *
     * @throws SQLException If connection is closed.
     */
    public void ensureNotClosed() throws SQLException {
        if (closed)
            throw new SQLException("Connection is closed.", CONNECTION_CLOSED);
    }

    /**
     * @return Ignite server version.
     */
    IgniteProductVersion igniteVersion() {
        if (partitionAwareness) {
            return ios.values().stream().map(JdbcThinTcpIo::igniteVersion).min(IgniteProductVersion::compareTo).
                orElse(baseEndpointVer);
        }
        else
            return singleIo.igniteVersion();
    }

    /**
     * @return Auto close server cursors flag.
     */
    boolean autoCloseServerCursor() {
        return connProps.isAutoCloseServerCursor();
    }

    /**
     * Send request for execution via corresponding singleIo from {@link #ios}.
     *
     * @param req Request.
     * @return Server response.
     * @throws SQLException On any error.
     */
    JdbcResultWithIo sendRequest(JdbcRequest req) throws SQLException {
        return sendRequest(req, null, null);
    }

    /**
     * Send request for execution via corresponding singleIo from {@link #ios} or sticky singleIo.
     *
     * @param req Request.
     * @param stmt Jdbc thin statement.
     * @param stickyIo Sticky ignite endpoint.
     * @return Server response.
     * @throws SQLException On any error.
     */
    JdbcResultWithIo sendRequest(JdbcRequest req, JdbcThinStatement stmt, @Nullable JdbcThinTcpIo stickyIo)
        throws SQLException {

        RequestTimeoutTask reqTimeoutTask = null;

        synchronized (mux) {
            if (ownThread != null) {
                throw new SQLException("Concurrent access to JDBC connection is not allowed"
                    + " [ownThread=" + ownThread.getName()
                    + ", curThread=" + Thread.currentThread().getName(), CONNECTION_FAILURE);
            }

            ownThread = Thread.currentThread();
        }
        try {
            try {
                int retryAttemptsLeft = 1;

                Exception lastE = null;

                while (retryAttemptsLeft > 0) {
                    JdbcThinTcpIo cliIo = null;

                    ensureConnected();

                    try {
                        cliIo = (stickyIo == null || !stickyIo.connected()) ? cliIo(calculateNodeIds(req)) : stickyIo;

                        if (stmt != null && stmt.requestTimeout() != NO_TIMEOUT) {
                            reqTimeoutTask = new RequestTimeoutTask(
                                req instanceof JdbcBulkLoadBatchRequest ? stmt.currentRequestId() : req.requestId(),
                                cliIo,
                                stmt.requestTimeout());

                            qryTimeoutScheduledFut = maintenanceExecutor.scheduleAtFixedRate(reqTimeoutTask, 0,
                                REQUEST_TIMEOUT_PERIOD, TimeUnit.MILLISECONDS);
                        }

                        JdbcQueryExecuteRequest qryReq = null;

                        if (req instanceof JdbcQueryExecuteRequest)
                            qryReq = (JdbcQueryExecuteRequest)req;

                        JdbcResponse res = cliIo.sendRequest(req, stmt);

                        txIo = res.activeTransaction() ? cliIo : null;

                        if (res.status() == IgniteQueryErrorCode.QUERY_CANCELED && stmt != null &&
                            stmt.requestTimeout() != NO_TIMEOUT && reqTimeoutTask != null &&
                            reqTimeoutTask.expired.get()) {

                            throw new SQLTimeoutException(QueryCancelledException.ERR_MSG, SqlStateCode.QUERY_CANCELLED,
                                IgniteQueryErrorCode.QUERY_CANCELED);
                        }
                        else if (res.status() != ClientListenerResponse.STATUS_SUCCESS)
                            throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status()),
                                res.status());

                        updateAffinityCache(qryReq, res);

                        return new JdbcResultWithIo(res.response(), cliIo);
                    }
                    catch (SQLException e) {
                        if (LOG.isLoggable(Level.FINE))
                            LOG.log(Level.FINE, "Exception during sending an sql request.", e);

                        throw e;
                    }
                    catch (Exception e) {
                        if (LOG.isLoggable(Level.FINE))
                            LOG.log(Level.FINE, "Exception during sending an sql request.", e);

                        onDisconnect(cliIo);

                        if (e instanceof SocketTimeoutException)
                            throw new SQLException("Connection timed out.", CONNECTION_FAILURE, e);
                        else {
                            if (lastE == null) {
                                retryAttemptsLeft = calculateRetryAttemptsCount(stickyIo, req);
                                lastE = e;
                            }
                            else
                                retryAttemptsLeft--;
                        }
                    }
                }

                throw new SQLException("Failed to communicate with Ignite cluster.", CONNECTION_FAILURE, lastE);
            }
            finally {
                if (stmt != null && stmt.requestTimeout() != NO_TIMEOUT && reqTimeoutTask != null)
                    qryTimeoutScheduledFut.cancel(false);
            }
        }
        finally {
            synchronized (mux) {
                ownThread = null;
            }
        }
    }

    /**
     * Calculate node UUIDs.
     *
     * @param req Jdbc request for which we'll try to calculate node id.
     * @return node UUID or null if failed to calculate.
     * @throws IOException If Exception occurred during the network partition distribution retrieval.
     * @throws SQLException If Failed to calculate derived partitions.
     */
    @Nullable private List<UUID> calculateNodeIds(JdbcRequest req) throws IOException, SQLException {
        if (!partitionAwareness || !(req instanceof JdbcQueryExecuteRequest))
            return null;

        JdbcQueryExecuteRequest qry = (JdbcQueryExecuteRequest)req;

        if (affinityCache == null) {
            qry.partitionResponseRequest(true);

            return null;
        }

        JdbcThinPartitionResultDescriptor partResDesc = affinityCache.partitionResult(
            new QualifiedSQLQuery(qry.schemaName(), qry.sqlQuery()));

        // Value is empty.
        if (partResDesc == JdbcThinPartitionResultDescriptor.EMPTY_DESCRIPTOR)
            return null;

        // Key is missing.
        if (partResDesc == null) {
            qry.partitionResponseRequest(true);

            return null;
        }

        Collection<Integer> parts = calculatePartitions(partResDesc, qry.arguments());

        if (parts == null || parts.isEmpty())
            return null;

        UUID[] cacheDistr = retrieveCacheDistribution(partResDesc.cacheId(),
            partResDesc.partitionResult().partitionsCount());

        if (parts.size() == 1)
            return Collections.singletonList(cacheDistr[parts.iterator().next()]);
        else {
            List<UUID> partitionAwarenessNodeIds = new ArrayList<>();

            for (int part : parts)
                partitionAwarenessNodeIds.add(cacheDistr[part]);

            return partitionAwarenessNodeIds;
        }
    }

    /**
     * Retrieve cache distribution for specified cache Id.
     *
     * @param cacheId Cache Id.
     * @param partCnt Partitions count.
     * @return Partitions cache distribution.
     * @throws IOException If Exception occurred during the network partition distribution retrieval.
     */
    private UUID[] retrieveCacheDistribution(int cacheId, int partCnt) throws IOException {
        UUID[] cacheDistr = affinityCache.cacheDistribution(cacheId);

        if (cacheDistr != null)
            return cacheDistr;

        JdbcResponse res;

        res = cliIo(null).sendRequest(new JdbcCachePartitionsRequest(Collections.singleton(cacheId)),
            null);

        assert res.status() == ClientListenerResponse.STATUS_SUCCESS;

        AffinityTopologyVersion resAffinityVer = res.affinityVersion();

        if (affinityCache.version().compareTo(resAffinityVer) < 0) {
            affinityCache = new AffinityCache(
                resAffinityVer,
                connProps.getPartitionAwarenessPartitionDistributionsCacheSize(),
                connProps.getPartitionAwarenessSqlCacheSize());
        }
        else if (affinityCache.version().compareTo(resAffinityVer) > 0) {
            // Jdbc thin affinity cache is binded to the newer affinity topology version, so we should ignore retrieved
            // partition distribution. Given situation might occur in case of concurrent race and is not
            // possible in single-threaded jdbc thin client, so it's a reserve for the future.
            return null;
        }

        List<JdbcThinPartitionAwarenessMappingGroup> mappings =
            ((JdbcCachePartitionsResult)res.response()).getMappings();

        // Despite the fact that, at this moment, we request partition distribution only for one cache,
        // we might retrieve multiple caches but exactly with same distribution.
        assert mappings.size() == 1;

        JdbcThinPartitionAwarenessMappingGroup mappingGrp = mappings.get(0);

        cacheDistr = mappingGrp.revertMappings(partCnt);

        for (int mpCacheId : mappingGrp.cacheIds())
            affinityCache.addCacheDistribution(mpCacheId, cacheDistr);

        return cacheDistr;
    }

    /**
     * Calculate partitions for the query.
     *
     * @param partResDesc Partition result descriptor.
     * @param args Arguments.
     * @return Calculated partitions or {@code null} if failed to calculate and there should be a broadcast.
     * @throws SQLException If Failed to calculate derived partitions.
     */
    public static Collection<Integer> calculatePartitions(JdbcThinPartitionResultDescriptor partResDesc, Object[] args)
        throws SQLException {
        PartitionResult derivedParts = partResDesc.partitionResult();

        if (derivedParts != null) {
            try {
                return derivedParts.tree().apply(partResDesc.partitionClientContext(), args);
            }
            catch (IgniteCheckedException e) {
                throw new SQLException("Failed to calculate derived partitions for query.",
                    INTERNAL_ERROR);
            }
        }

        return null;
    }

    /**
     * Send request for execution via corresponding singleIo from {@link #ios} or sticky singleIo.
     * Response is waited at the separate thread (see {@link StreamState#asyncRespReaderThread}).
     *
     * @param req Request.
     * @throws SQLException On any error.
     */
    void sendQueryCancelRequest(JdbcQueryCancelRequest req, JdbcThinTcpIo cliIo) throws SQLException {
        if (connCnt.get() == 0)
            throw new SQLException("Failed to communicate with Ignite cluster.", CONNECTION_FAILURE);

        assert cliIo != null;

        try {
            cliIo.sendCancelRequest(req);
        }
        catch (Exception e) {
            throw new SQLException("Failed to communicate with Ignite cluster.", CONNECTION_FAILURE, e);
        }
    }

    /**
     * Send request for execution via corresponding singleIo from {@link #ios} or sticky singleIo.
     * Response is waited at the separate thread (see {@link StreamState#asyncRespReaderThread}).
     *
     * @param req Request.
     * @param stickyIO Sticky ignite endpoint.
     * @throws SQLException On any error.
     */
    private void sendRequestNotWaitResponse(JdbcOrderedBatchExecuteRequest req, JdbcThinTcpIo stickyIO)
        throws SQLException {
        ensureConnected();

        synchronized (mux) {
            if (ownThread != null) {
                throw new SQLException("Concurrent access to JDBC connection is not allowed"
                    + " [ownThread=" + ownThread.getName()
                    + ", curThread=" + Thread.currentThread().getName(), CONNECTION_FAILURE);
            }

            ownThread = Thread.currentThread();
        }

        try {
            stickyIO.sendBatchRequestNoWaitResponse(req);
        }
        catch (SQLException e) {
            throw e;
        }
        catch (Exception e) {
            onDisconnect(stickyIO);

            if (e instanceof SocketTimeoutException)
                throw new SQLException("Connection timed out.", CONNECTION_FAILURE, e);
            else
                throw new SQLException("Failed to communicate with Ignite cluster.",
                    CONNECTION_FAILURE, e);
        }
        finally {
            synchronized (mux) {
                ownThread = null;
            }
        }
    }

    /**
     * @return Connection URL.
     */
    public String url() {
        return connProps.getUrl();
    }

    /**
     * Called on IO disconnect: close the client IO and opened statements.
     */
    private void onDisconnect(JdbcThinTcpIo cliIo) {
        assert connCnt.get() > 0;

        if (partitionAwareness) {
            cliIo.close();

            ios.remove(cliIo.nodeId());
        }
        else {
            if (singleIo != null)
                singleIo.close();
        }

        connCnt.decrementAndGet();

        if (streamState != null) {
            streamState.close0();

            streamState = null;
        }

        synchronized (stmtsMux) {
            for (JdbcThinStatement s : stmts)
                s.closeOnDisconnect();

            stmts.clear();
        }
    }

    /**
     * @param stmt Statement to close.
     */
    void closeStatement(JdbcThinStatement stmt) {
        synchronized (stmtsMux) {
            stmts.remove(stmt);
        }
    }

    /**
     * Streamer state and
     */
    private class StreamState {
        /** Maximum requests count that may be sent before any responses. */
        private static final int MAX_REQUESTS_BEFORE_RESPONSE = 10;

        /** Batch size for streaming. */
        private int streamBatchSize;

        /** Batch for streaming. */
        private List<JdbcQuery> streamBatch;

        /** Last added query to recognize batches. */
        private String lastStreamQry;

        /** Keep request order on execution. */
        private long order;

        /** Async response reader thread. */
        private Thread asyncRespReaderThread;

        /** Async response error. */
        private volatile Exception err;

        /** The order of the last batch request at the stream. */
        private long lastRespOrder = -1;

        /** Last response future. */
        private final GridFutureAdapter<Void> lastRespFut = new GridFutureAdapter<>();

        /** Response semaphore sem. */
        private Semaphore respSem = new Semaphore(MAX_REQUESTS_BEFORE_RESPONSE);

        /** Streaming sticky ignite endpoint. */
        private final JdbcThinTcpIo streamingStickyIo;

        /**
         * @param cmd Stream cmd.
         * @param stickyIo Sticky ignite endpoint.
         */
        StreamState(SqlSetStreamingCommand cmd, JdbcThinTcpIo stickyIo) {
            streamBatchSize = cmd.batchSize();

            asyncRespReaderThread = new Thread(this::readResponses);

            streamingStickyIo = stickyIo;
        }

        /**
         * Start reader.
         */
        void start() {
            asyncRespReaderThread.start();
        }

        /**
         * Add another query for batched execution.
         *
         * @param sql Query.
         * @param args Arguments.
         * @throws SQLException On error.
         */
        void addBatch(String sql, List<Object> args) throws SQLException {
            checkError();

            boolean newQry = (args == null || !F.eq(lastStreamQry, sql));

            // Providing null as SQL here allows for recognizing subbatches on server and handling them more efficiently.
            JdbcQuery q = new JdbcQuery(newQry ? sql : null, args != null ? args.toArray() : null);

            if (streamBatch == null)
                streamBatch = new ArrayList<>(streamBatchSize);

            streamBatch.add(q);

            // Null args means "addBatch(String)" was called on non-prepared Statement,
            // we don't want to remember its query string.
            lastStreamQry = (args != null ? sql : null);

            if (streamBatch.size() == streamBatchSize)
                executeBatch(false);
        }

        /**
         * @param lastBatch Whether open data streamers must be flushed and closed after this batch.
         * @throws SQLException if failed.
         */
        private void executeBatch(boolean lastBatch) throws SQLException {
            checkError();

            if (lastBatch)
                lastRespOrder = order;

            try {
                respSem.acquire();

                sendRequestNotWaitResponse(
                    new JdbcOrderedBatchExecuteRequest(schema, streamBatch, autoCommit, lastBatch, order),
                    streamingStickyIo);

                streamBatch = null;

                lastStreamQry = null;

                if (lastBatch) {
                    try {
                        lastRespFut.get();
                    }
                    catch (IgniteCheckedException ignored) {
                        // No-op.
                        // No exceptions are expected here.
                    }

                    checkError();
                }
                else
                    order++;
            }
            catch (InterruptedException e) {
                throw new SQLException("Streaming operation was interrupted", INTERNAL_ERROR, e);
            }
        }

        /**
         * Throws at the user thread exception that was thrown at the {@link #asyncRespReaderThread} thread.
         *
         * @throws SQLException Saved exception.
         */
        void checkError() throws SQLException {
            if (err != null) {
                Exception err0 = err;

                err = null;

                if (err0 instanceof SQLException)
                    throw (SQLException)err0;
                else {
                    onDisconnect(streamingStickyIo);

                    if (err0 instanceof SocketTimeoutException)
                        throw new SQLException("Connection timed out.", CONNECTION_FAILURE, err0);
                    throw new SQLException("Failed to communicate with Ignite cluster on JDBC streaming.",
                        CONNECTION_FAILURE, err0);
                }
            }
        }

        /**
         * @throws SQLException On error.
         */
        void close() throws SQLException {
            close0();

            checkError();
        }

        /**
         */
        void close0() {
            if (connCnt.get() > 0) {
                try {
                    executeBatch(true);
                }
                catch (SQLException e) {
                    err = e;

                    LOG.log(Level.WARNING, "Exception during batch send on streamed connection close", e);
                }
            }

            if (asyncRespReaderThread != null)
                asyncRespReaderThread.interrupt();
        }

        /**
         *
         */
        void readResponses() {
            try {
                while (true) {
                    JdbcResponse resp = streamingStickyIo.readResponse();

                    if (resp.response() instanceof JdbcOrderedBatchExecuteResult) {
                        JdbcOrderedBatchExecuteResult res = (JdbcOrderedBatchExecuteResult)resp.response();

                        respSem.release();

                        if (res.errorCode() != ClientListenerResponse.STATUS_SUCCESS) {
                            err = new BatchUpdateException(res.errorMessage(),
                                IgniteQueryErrorCode.codeToSqlState(res.errorCode()),
                                res.errorCode(), res.updateCounts());
                        }

                        // Receive the response for the last request.
                        if (res.order() == lastRespOrder) {
                            lastRespFut.onDone();

                            break;
                        }
                    }
                    else if (resp.status() != ClientListenerResponse.STATUS_SUCCESS)
                        err = new SQLException(resp.error(), IgniteQueryErrorCode.codeToSqlState(resp.status()));
                    else
                        assert false : "Invalid response: " + resp;
                }
            }
            catch (Exception e) {
                err = e;
            }
        }
    }

    /**
     * @return True if query cancellation supported, false otherwise.
     */
    boolean isQueryCancellationSupported() {
        return partitionAwareness || singleIo.isQueryCancellationSupported();
    }

    /**
     * @param nodeIds Set of node's UUIDs.
     * @return Ignite endpoint to use for request/response transferring.
     */
    private JdbcThinTcpIo cliIo(List<UUID> nodeIds) {
        if (!partitionAwareness)
            return singleIo;

        if (txIo != null)
            return txIo;

        if (nodeIds == null || nodeIds.isEmpty())
            return randomIo();

        JdbcThinTcpIo io = null;

        if (nodeIds.size() == 1)
            io = ios.get(nodeIds.get(0));
        else {
            int initNodeId = RND.nextInt(nodeIds.size());

            int iterCnt = 0;

            while (io == null) {
                io = ios.get(nodeIds.get(initNodeId));

                initNodeId = initNodeId == nodeIds.size() ? 0 : initNodeId + 1;

                iterCnt++;

                if (iterCnt == nodeIds.size())
                    break;
            }
        }

        return io != null ? io : randomIo();
    }

    /**
     * Returns random tcpIo, based on random UUID, generated in a custom way with the help of {@code Random}
     * instead of {@code SecureRandom}. It's valid, cause cryptographically strong pseudo
     * random number generator is not required in this particular case. {@code Random} is much faster
     * than {@code SecureRandom}.
     *
     * @return random tcpIo
     */
    private JdbcThinTcpIo randomIo() {
        byte[] randomBytes = new byte[16];

        RND.nextBytes(randomBytes);

        randomBytes[6]  &= 0x0f;  /* clear version        */
        randomBytes[6]  |= 0x40;  /* set to version 4     */
        randomBytes[8]  &= 0x3f;  /* clear variant        */
        randomBytes[8]  |= 0x80;  /* set to IETF variant  */

        long msb = 0;

        long lsb = 0;

        for (int i=0; i<8; i++)
            msb = (msb << 8) | (randomBytes[i] & 0xff);

        for (int i=8; i<16; i++)
            lsb = (lsb << 8) | (randomBytes[i] & 0xff);

        UUID randomUUID =  new UUID(msb, lsb);

        Map.Entry<UUID, JdbcThinTcpIo> entry = ios.ceilingEntry(randomUUID);

        return entry != null ? entry.getValue() : ios.floorEntry(randomUUID).getValue();
    }

    /**
     * @return Current server index.
     */
    public int serverIndex() {
        return srvIdx;
    }

    /**
     * Get next server index.
     *
     * @param len Number of servers.
     * @return Index of the next server to connect to.
     */
    private static int nextServerIndex(int len) {
        if (len == 1)
            return 0;
        else {
            long nextIdx = IDX_GEN.getAndIncrement();

            return (int)(nextIdx % len);
        }
    }

    /**
     * Establishes a connection to ignite endpoint, trying all specified hosts and ports one by one.
     * Stops as soon as any connection is established.
     *
     * @throws SQLException If failed to connect to ignite cluster.
     */
    private void connectInCommonMode() throws SQLException {
        HostAndPortRange[] srvs = connProps.getAddresses();

        List<Exception> exceptions = null;

        for (int i = 0; i < srvs.length; i++) {
            srvIdx = nextServerIndex(srvs.length);

            HostAndPortRange srv = srvs[srvIdx];

            try {
                InetAddress[] addrs = InetAddress.getAllByName(srv.host());

                for (InetAddress addr : addrs) {
                    for (int port = srv.portFrom(); port <= srv.portTo(); ++port) {
                        try {
                            JdbcThinTcpIo cliIo = new JdbcThinTcpIo(connProps, new InetSocketAddress(addr, port),
                                0);

                            cliIo.timeout(netTimeout);

                            singleIo = cliIo;

                            connCnt.incrementAndGet();

                            return;
                        }
                        catch (Exception exception) {
                            if (exceptions == null)
                                exceptions = new ArrayList<>();

                            exceptions.add(exception);
                        }

                    }
                }
            }
            catch (Exception exception) {
                if (exceptions == null)
                    exceptions = new ArrayList<>();

                exceptions.add(exception);
            }
        }

        handleConnectExceptions(exceptions);
    }

    /**
     * Prepare and throw general {@code SQLException} with all specified exceptions as suppressed items.
     *
     * @param exceptions Exceptions list.
     * @throws SQLException Umbrella exception.
     */
    private void handleConnectExceptions(List<Exception> exceptions) throws SQLException {
        if (connCnt.get() == 0 && exceptions != null) {
            close();

            if (exceptions.size() == 1) {
                Exception ex = exceptions.get(0);

                if (ex instanceof SQLException)
                    throw (SQLException)ex;
                else if (ex instanceof IOException)
                    throw new SQLException("Failed to connect to Ignite cluster [url=" + connProps.getUrl() + ']',
                        CLIENT_CONNECTION_FAILED, ex);
            }

            SQLException e = new SQLException("Failed to connect to server [url=" + connProps.getUrl() + ']',
                CLIENT_CONNECTION_FAILED);

            for (Exception ex : exceptions)
                e.addSuppressed(ex);

            throw e;
        }
    }

    /**
     * Establishes a connection to ignite endpoint, trying all specified hosts and ports one by one.
     * Stops as soon as all iosArr are established.
     *
     * @param baseEndpointVer Base endpoint version.
     * @return last connected endpoint version.
     * @throws SQLException If failed to connect to at least one ignite endpoint,
     * or if endpoints versions are less than base endpoint version.
     */
    private IgniteProductVersion connectInBestEffortAffinityMode(IgniteProductVersion baseEndpointVer) throws SQLException {
        List<Exception> exceptions = null;

        for (int i = 0; i < connProps.getAddresses().length; i++) {
            HostAndPortRange srv = connProps.getAddresses()[i];

            try {
                InetAddress[] addrs = InetAddress.getAllByName(srv.host());

                for (InetAddress addr : addrs) {
                    for (int port = srv.portFrom(); port <= srv.portTo(); ++port) {
                        try {
                            JdbcThinTcpIo cliIo =
                                new JdbcThinTcpIo(connProps, new InetSocketAddress(addr, port), 0);

                            if (!cliIo.isPartitionAwarenessSupported()) {
                                cliIo.close();

                                throw new SQLException("Failed to connect to Ignite node [url=" +
                                    connProps.getUrl() + "]. address = [" + addr + ':' + port + "]." +
                                    "Node doesn't support partition awareness mode.",
                                    INTERNAL_ERROR);
                            }

                            IgniteProductVersion endpointVer = cliIo.igniteVersion();

                            if (baseEndpointVer != null && baseEndpointVer.compareTo(endpointVer) > 0) {
                                cliIo.close();

                                throw new SQLException("Failed to connect to Ignite node [url=" +
                                    connProps.getUrl() + "], address = [" + addr + ':' + port + "]," +
                                    "the node version [" + endpointVer + "] " +
                                    "is smaller than the base one [" + baseEndpointVer + "].",
                                    INTERNAL_ERROR);
                            }

                            cliIo.timeout(netTimeout);

                            JdbcThinTcpIo ioToSameNode = ios.putIfAbsent(cliIo.nodeId(), cliIo);

                            // This can happen if the same node has several IPs or if connection manager background
                            // timer task runs concurrently.
                            if (ioToSameNode != null)
                                cliIo.close();
                            else
                                connCnt.incrementAndGet();

                            return cliIo.igniteVersion();
                        }
                        catch (Exception exception) {
                            if (exceptions == null)
                                exceptions = new ArrayList<>();

                            exceptions.add(exception);
                        }
                    }
                }
            }
            catch (Exception exception) {
                if (exceptions == null)
                    exceptions = new ArrayList<>();

                exceptions.add(exception);
            }
        }

        handleConnectExceptions(exceptions);

        return null;
    }

    /**
     * Recreates affinity cache if affinity topology version was changed and adds partition result to sql cache.
     *
     * @param qryReq Query request.
     * @param res Jdbc Response.
     */
    private void updateAffinityCache(JdbcQueryExecuteRequest qryReq, JdbcResponse res) {
        if (partitionAwareness) {
            AffinityTopologyVersion resAffVer = res.affinityVersion();

            if (resAffVer != null && (affinityCache == null || affinityCache.version().compareTo(resAffVer) < 0)) {
                affinityCache = new AffinityCache(
                    resAffVer,
                    connProps.getPartitionAwarenessPartitionDistributionsCacheSize(),
                    connProps.getPartitionAwarenessSqlCacheSize());
            }

            // Partition result was requested.
            if (res.response() instanceof JdbcQueryExecuteResult && qryReq.partitionResponseRequest()) {
                PartitionResult partRes = ((JdbcQueryExecuteResult)res.response()).partitionResult();

                if (partRes == null || affinityCache.version().equals(partRes.topologyVersion())) {
                    int cacheId = (partRes != null && partRes.tree() != null) ?
                        GridCacheUtils.cacheId(partRes.cacheName()) :
                        -1;

                    PartitionClientContext partClientCtx = partRes != null ?
                        new PartitionClientContext(partRes.partitionsCount()) :
                        null;

                    QualifiedSQLQuery qry = new QualifiedSQLQuery(qryReq.schemaName(), qryReq.sqlQuery());

                    JdbcThinPartitionResultDescriptor partResDescr =
                        new JdbcThinPartitionResultDescriptor(partRes, cacheId, partClientCtx);

                    affinityCache.addSqlQuery(qry, partResDescr);
                }
            }
        }
    }

    /**
     * Calculates query retries count for given {@param req}.
     *
     * @param stickyIo sticky connection, if any.
     * @param req Jdbc request.
     *
     * @return retries count.
     */
    private int calculateRetryAttemptsCount(JdbcThinTcpIo stickyIo, JdbcRequest req) {
        if (!partitionAwareness)
            return NO_RETRIES;

        if (stickyIo != null)
            return NO_RETRIES;

        if (req.type() == JdbcRequest.META_TABLES ||
            req.type() == JdbcRequest.META_COLUMNS ||
            req.type() == JdbcRequest.META_INDEXES ||
            req.type() == JdbcRequest.META_PARAMS ||
            req.type() == JdbcRequest.META_PRIMARY_KEYS ||
            req.type() == JdbcRequest.META_SCHEMAS ||
            req.type() == JdbcRequest.CACHE_PARTITIONS)
            return DFLT_RETRIES_CNT;

        if (req.type() == JdbcRequest.QRY_EXEC) {
            JdbcQueryExecuteRequest qryExecReq = (JdbcQueryExecuteRequest)req;

            String trimmedQry = qryExecReq.sqlQuery().trim();

            // Last symbol is ignored.
            for (int i = 0; i < trimmedQry.length() - 1; i++) {
                if (trimmedQry.charAt(i) == ';')
                    return NO_RETRIES;
            }

            return trimmedQry.toUpperCase().startsWith("SELECT") ? DFLT_RETRIES_CNT : NO_RETRIES;
        }

        return NO_RETRIES;
    }

    /**
     * Request Timeout Task
     */
    private class RequestTimeoutTask implements Runnable {
        /** Request id. */
        private final long reqId;

        /** Sticky singleIo. */
        private final JdbcThinTcpIo stickyIO;

        /** Remaining query timeout. */
        private int remainingQryTimeout;

        /** Flag that shows whether TimerTask was expired or not. */
        private AtomicBoolean expired;

        /**
         * @param reqId Request Id to cancel in case of timeout
         * @param initReqTimeout Initial request timeout
         */
        RequestTimeoutTask(long reqId, JdbcThinTcpIo stickyIO, int initReqTimeout) {
            this.reqId = reqId;

            this.stickyIO = stickyIO;

            remainingQryTimeout = initReqTimeout;

            expired = new AtomicBoolean(false);
        }

        /** {@inheritDoc} */
        @Override public void run() {
            try {
                if (remainingQryTimeout <= 0) {
                    expired.set(true);

                    sendQueryCancelRequest(new JdbcQueryCancelRequest(reqId), stickyIO);

                    qryTimeoutScheduledFut.cancel(false);

                    return;
                }

                remainingQryTimeout -= REQUEST_TIMEOUT_PERIOD;
            }
            catch (SQLException e) {
                LOG.log(Level.WARNING,
                    "Request timeout processing failure: unable to cancel request [reqId=" + reqId + ']', e);

                qryTimeoutScheduledFut.cancel(false);
            }
        }
    }

    /**
     * Connection Handler Task
     */
    private class ConnectionHandlerTask  implements Runnable {
        /** Map with reconnection delays. */
        private Map<InetSocketAddress, Integer> reconnectionDelays = new HashMap<>();

        /** Map with reconnection delays remainder. */
        private Map<InetSocketAddress, Integer> reconnectionDelaysRemainder = new HashMap<>();

        /** {@inheritDoc} */
        @Override public void run() {
            try {
                for (Map.Entry<InetSocketAddress, Integer> delayEntry : reconnectionDelaysRemainder.entrySet())
                    reconnectionDelaysRemainder.put(delayEntry.getKey(), delayEntry.getValue() - RECONNECTION_DELAY);

                Set<InetSocketAddress> aliveSockAddrs =
                    ios.values().stream().map(JdbcThinTcpIo::socketAddress).collect(Collectors.toSet());

                IgniteProductVersion prevIgniteEndpointVer = null;

                for (int i = 0; i < connProps.getAddresses().length; i++) {
                    HostAndPortRange srv = connProps.getAddresses()[i];

                    try {
                        InetAddress[] addrs = InetAddress.getAllByName(srv.host());

                        for (InetAddress addr : addrs) {
                            for (int port = srv.portFrom(); port <= srv.portTo(); ++port) {
                                InetSocketAddress sockAddr = null;

                                try {
                                    sockAddr = new InetSocketAddress(addr, port);

                                    if (aliveSockAddrs.contains(sockAddr)) {
                                        reconnectionDelaysRemainder.remove(sockAddr);
                                        reconnectionDelays.remove(sockAddr);

                                        continue;
                                    }

                                    Integer delayRemainder = reconnectionDelaysRemainder.get(sockAddr);

                                    if (delayRemainder != null && delayRemainder != 0)
                                        continue;

                                    if (closed) {
                                        maintenanceExecutor.shutdown();

                                        return;
                                    }

                                    JdbcThinTcpIo cliIo =
                                        new JdbcThinTcpIo(connProps, new InetSocketAddress(addr, port), 0);

                                    if (!cliIo.isPartitionAwarenessSupported()) {
                                        processDelay(sockAddr);

                                        LOG.log(Level.WARNING, "Failed to connect to Ignite node [url=" +
                                            connProps.getUrl() + "]. address = [" + addr + ':' + port + "]." +
                                            "Node doesn't support best effort affinity mode.");

                                        cliIo.close();

                                        continue;
                                    }

                                    if (prevIgniteEndpointVer != null &&
                                        !prevIgniteEndpointVer.equals(cliIo.igniteVersion())) {
                                        processDelay(sockAddr);

                                        LOG.log(Level.WARNING, "Failed to connect to Ignite node [url=" +
                                            connProps.getUrl() + "]. address = [" + addr + ':' + port + "]." +
                                            "Different versions of nodes are not supported in best " +
                                            "effort affinity mode.");

                                        cliIo.close();

                                        continue;
                                    }

                                    cliIo.timeout(netTimeout);

                                    JdbcThinTcpIo ioToSameNode = ios.putIfAbsent(cliIo.nodeId(), cliIo);

                                    // This can happen if the same node has several IPs or if ensureConnected() runs
                                    // concurrently
                                    if (ioToSameNode != null)
                                        cliIo.close();
                                    else
                                        connCnt.incrementAndGet();

                                    prevIgniteEndpointVer = cliIo.igniteVersion();

                                    if (closed) {
                                        maintenanceExecutor.shutdown();

                                        cliIo.close();

                                        ios.remove(cliIo.nodeId());

                                        return;
                                    }
                                }
                                catch (Exception exception) {
                                    if (sockAddr != null)
                                        processDelay(sockAddr);

                                    LOG.log(Level.WARNING, "Failed to connect to Ignite node [url=" +
                                        connProps.getUrl() + "]. address = [" + addr + ':' + port + "].");
                                }
                            }
                        }
                    }
                    catch (Exception exception) {
                        LOG.log(Level.WARNING, "Failed to connect to Ignite node [url=" +
                            connProps.getUrl() + "]. server = [" + srv + "].");
                    }
                }
            }
            catch (Exception e) {
                LOG.log(Level.WARNING, "Connection handler processing failure. Reconnection processes was stopped."
                    , e);

                connectionsHndScheduledFut.cancel(false);
            }
        }

        /**
         * Increase reconnection delay if needed and store it to corresponding maps.
         *
         * @param sockAddr Socket address.
         */
        private void processDelay(InetSocketAddress sockAddr) {
            Integer delay = reconnectionDelays.get(sockAddr);

            delay = delay == null ? RECONNECTION_DELAY : delay * 2;

            if (delay > RECONNECTION_MAX_DELAY)
                delay = RECONNECTION_MAX_DELAY;

            reconnectionDelays.put(sockAddr, delay);

            reconnectionDelaysRemainder.put(sockAddr, delay);
        }
    }
}


text:
Federal Court Rules Against Huntsville's Segregated Caste System of Schools
From Alternet, a clip:
. . . . "The record in this case is not as clear as the Board suggests, and the fact that the district integrated the student bodies of many of its schools in the early 1970s does not automatically lead to the conclusion that the district does not currently operate a dual system," she wrote. She pointed out that not only were many schools still segregated, but the opportunity to take advanced classes also appeared linked to race.
She noted testimony from a white mother who withdrew her child from a predominantly black high school because it offered fewer advanced academic courses than other schools.
"While private choices seem to have precipitated the existing racial polarization of the district's schools, it is not clear...that the district has not contributed to the situation," she wrote. "There is a significant disparity between the educational programs in the district's predominately African-American secondary schools and the educational programs in the district's predominately white schools."
That disparity, she said, could even be a violation of the Equal Protection Clause of the 14th Amendment.
Huntsville schools had taken several steps to improve educational outcomes for black students, including adopting universal school breakfast programs and increasing pre-kindergarten classrooms. But the judge's ruling seemed skeptical of whether the district would continue these efforts once court oversight ended.
"The Board submits that the district's conduct over the past 50 years demonstrates good faith. Recent events, though, have hurt the board's record," she wrote. She catalogued Huntsville's 20-year failure to file required reports, its track record of missing data and incomplete information, and its public criticism of a requirement in the order that the district allow students to transfer into schools where they are a racial minority.
Haikala set two magistrate judges to the task of gathering information and to work with the district and the Justice Department to come up with a plan to address any other issues needed to get the district in compliance with the order, and ultimately, to end it.
Huntsville's children, she wrote, "have no control over where they live now, but giving them a strong education is the surest way to ensure that they will have choices about where they will live in the future and what they will do when they become adults."
You can read Judge Haikala's entire order here. You can search ProPublica's database to see whether your district is, or has ever been, under a school desegregation order and check school segregation in your hometown.
Labels: Alabama Schools, desegregation, Huntsville, school segregation, segregation
Member of FBI-Raided School Funds Todd Rokita AFTE...
Holy Moses Batman! Arne Met with the Badass Teachers!
Evan Bayh Loves Christel DeHaan and Hedge Funders:...
Now That Education Has Been the "Civil Rights Issu...
Haslam Continues Ed Policy Based on Secrecy, Favor...
New Jersey's Hedge Fund Guru In Indiana
Value-Added Modeling (VAM) is pseudoscience, but p...
Lily Gives Arne a Big Hug
Behning's Corporate School Money Still Flowing
Haslam's Secret Meeting at Ground Zero of Secret C...
Getting to Know KnowledgeWorks, Part 1
Our overall scores are unspectacular because of ou...
Why Rhonda's and Lili's Resignations Are More Impo...
Doug Martin's Podcast on War Report on Public Educ...
Why the push to make students "Career Ready"?
Opt Out: Stop the Education Genocide
At KIPP, "they wouldn't have desks at first" and t...
Arizona Charter, Heritage Academy, Teaching the Be...
TURNcoats Meet in Rosemont, IL to Promote Common Core
In Response to Bill Wraga's Review of The Mismeasu...
Federal Court Rules Against Huntsville's Segregate...
NEA, SEIU, and Eli Broad
Why Cuomo Will Lose: Her Name is Zephyr Teachout
Read Sean Crowley
Beware of Youth Entrepreneurs (YE) Right Wing Indo...
Doug Martin Guest on the War Report on Public Educ...
Barbara Madeloni Discusses Testing, Teaching, Inco...
Understanding Why the TURN Cancer Has to Be Cut Ou...
Attacking Diane Ravitch? Or Questions Too Uncomfo...
Broadie McIntyre Demotes Top Ranked Principal to M...
Charter Cap in Massachusetts Will Not Be Lifted
Ken Derstine Commentary
Andre Carson's Wife and the Mind Trust/Indy Chamber
TURNcoat, Mary Ricker, to Serve as Exec VP for Wei...
Ravitch Lashes Out at Union Misleadership Critique
Picket the Koch Heads Education Privatization Meet...
Doug Martin's Letter to Gordon Hendry and the Indi...
Chicago City of Murder (CCOM)
Compelling evidence
Open letter to Ellie Herman, or how Green Dot's Ma...
Following Rhonda's Advice: Be a "Little Badass"
Hechinger Report Pulls Out the Stops to Save the G...
Weingarten Riding High on Teacher Union Dues
The State Board of Ed, the Uneducated Educated, an...
A Teacher's Take on Common Core
The input that matters most
The Gild Is Already Off the Lily, But She is Golde...
Doug Martin's Letter to the Indiana State Board of...
Duncan's Latest Party Balloon Just Got Popped in T...
The Meaningless Moratorium Has Ended Before Anyone...
Email the Indiana State Board of Ed: Another Power...
Kindergarten Achievement Tests Before Kindergarten
Ravitch Waves Goodbye to Common Core and Throws Ki...
David Brooks: In Praise of Segregation
Picket, Boycott, Shut Down Weingarten's Common Cor...
Join Me at the Rise Above The Mark Kokomo Show, Ju...
A bad way to rate teachers

redpajama_set_name: RedPajamaCommonCrawl


text:
How Fertilizer Is Making Climate Change Worse
Paul Tullis
1:30 PM IST, 10 Sep 2020 1:20 AM IST, 15 Sep 2020 1:30 PM IST, 10 Sep 2020 1:20 AM IST, 15 Sep 2020
(Bloomberg) -- The explosion that rocked Beirut last month, killing at least 190, was a grim echo of prior accidents caused by the explosive synthetic fertilizer ammonium nitrate.
Tianjin, China, 2015: 173 dead. West, Texas, 2013: 15 dead. Toulouse, France, 2001: 31 dead. Such incidents go back at least as far as 1947, when 581 people were killed in Texas City, Texas. The substance can also be used with destructive intent, as was the case with the antigovernment terrorist Timothy McVeigh, who killed 168 people in Oklahoma City in 1995.
Yet ammonium nitrate's deadly potential isn't its most dire threat to human life. As a widely-used synthetic fertilizer, it and its chemical cousins ammonium sulfate, sodium nitrate and potassium nitrate are significant contributors to climate change.
Its production is energy-intensive, requiring the burning of fossil fuels. After farmers apply these synthetic fertilizers to crops, chains of chemical reactions generate nitrous oxide, or N2O, a greenhouse gas. The International Fertilizer Association pegs the amount of anthropogenic GHG emissions for which the industry is responsible at 2.5%, but all greenhouse gasses are not created equal. N2O has a far greater global warming potential than either methane or carbon dioxide—265 times more by weight as CO2.
Even worse, "nitrous oxide emissions are higher than previously thought, and going up faster than previously thought," said Rona Thompson, senior scientist at the Norwegian Institute for Air Research.
Green groups have been pushing for years to get farmers to reduce their fertilizer use, and many are starting to listen. "Emissions in the U.S. and Europe have stabilized and started to go down, and farmers maintained or slightly increased yield while using no more nitrogen fertilizer," Thompson said.
Market factors have also influenced the reduction. Still, there's room for improvement, particularly in China, where a "more is better" approach to ammonium nitrate persists. Sometimes farmers pour on more than can possibly be taken up by crops, resulting in more adverse climate effects with no discernible benefit.
Alternatives include organics such as manure, and deployment of cover crops like soy and other legumes that convert nitrogen in the air into plant food. But these methods will only take food production so far. Estimates of the percentage of humans who would not be alive today without synthetic fertilizer range from around 40% to 50%.
With fertilizer one of agriculture's biggest operating expenses, it also pays to find the optimal amount of ammonium nitrate to apply to soil. AgroCares, based in the Netherlands, has developed a scanning device about the size of a flashlight that translates spectral information into a nutrient value, determined through a large database of soil samples and a machine learning algorithm.
Paired with a smartphone app, the device provides information similar to that produced by labs for U.S. and European farmers, but more accessible to the developing world. In parts of Africa, many farmers use fertilizers without knowing the balance of nutrients in their soil, said AgroCares project manager Florent Mournetas.
"You need to have a balance of nitrogen, phosphate, and potassium. When you only apply ammonium nitrate, the plants use up the other nutrients in the soil and it becomes depleted, so farmers are not seeing the yields they need" even after spending $60—a small fortune for a farmer in Tanzania or Kenya—on a bag of fertilizer. A $10 investment in soil testing gets them more bang for their fertilizer buck—and avoids overuse of climate-forcing synthetics such as ammonium nitrate.
In the last few years, U.S. biotech firms from California to St. Louis to Boston have developed microbial solutions to replace at least some of the synthetic fertilizers used with hungry crops such as corn and wheat.
Before use of ammonium nitrate became widespread, microbes existing naturally in the soil provided some nitrogen to plants. But with large amounts of ammonium nitrate poured into the soil around them, they don't bother expending energy on nitrogen production. Legumes are able to circumvent this by chemically shielding the microbes in their roots, convincing them they're in a nitrogen-poor environment.
"We go in and break the wiring in the microbe that connects their ability to sense nitrogen in the soil to their decision to become a source of nitrogen for a farmer," said Karsten Temme, chief executive of Pivot Bio, based in Berkeley, California. "The goal is less fertilizer required."
Now in its third commercial growing season, Pivot prices its product to produce yields equivalent to what the same dollar amount of ammonium nitrate would provide. The advantage, Temme said, is that the microbes do their job more consistently over the growing season, and don't wash away with the heavy rains that are becoming more frequent in the Corn Belt.
"A lot of fertilizer is just completely leaching out of the soil before the plants even have a chance to take it up," said Amanda Raster, science program manager at U.S. Farmers & Ranchers Alliance, a funding partner of agribusiness lobby American Farm Bureau Federation.
Joyn Bio, a joint venture of synthetic biology innovator Gingko Bioworks and seed and spray powerhouse Bayer AG, is developing its own microbial salad for crops. It's also working on a method of applying a microbial formulation directly to corn seed—a concept proven by AgraQuest, where Joyn CEO Mike Miille was previously CEO—or mixing it in with fertilizer.
By reducing the need for fertilizer, such methods can lower agriculture costs while further reducing greenhouse gas emissions. "The fuel associated with a tractor, aerial spraying—that's a huge cost for growers," said Miille, who has a Ph.D. in agricultural chemistry from the University of California, Davis.
"Farmers just love being on the cutting edge of whatever's new," Raster of the farmers alliance said. "They're very receptive to new ways of thinking if you can show them that the economics pencil out."
Stay Updated With OnWeb News On BloombergQuint


text:
San Pawl Milqi is the ruin of a Roman-period agricultural villa and a pagan temple, the most extensive to have ever been unearthed in Malta. A christian church was built on site based on the pseudo-history and religious doctrine that the site has biblical connections. On site of a present chapel was a temple dedicated to the Greek God Apollo and a Roman villa. According to religious tradition the villa is where St. Publius, the governor and first bishop of Malta, welcomed St. Paul after his shipwreck.

Apart from a copied and translated scripture attributed to Saint Luke, of which original source is now lost and has been translated from languages to languages, there are no periodic authors that wrote about the shipwreck at the time and no temporary authors supplement the tradition. Since the myth was founded, authors were careful in their writings to suit the Christian scripture which says Melite (not Malta).

There is no archaeological evidence in support of Christian claims, and it is considered a word of mouth and misnomer by name dating to the middle ages. Evidence of Christian worship on the site only dates back to the building of the first chapel in the fourteenth century. According to Anthony Bonanno, archeological research in the entire area of St Paul's Bay found no evidence of the Christian tradition related to the supposed shipwreck in the area.

History

The site has been in use since prehistoric times; a couple of tombs date back to the Zebbug and possibly the Borg in-Nadur phases of the Maltese Bronze Age.

The first building on the site was probably built in the Phoenician-Punic period, when the site was used intermittently for agriculture. A small number of structures remain from this period and one burial bears a neo-Punic inscription.

In the Roman period, the site's position on the slopes of a fertile valley and vicinity to the Roman harbour at Salina meant that it was ideally suited to the production of olive oil.  The establishment was expanded; the original central courtyard was transformed into an industrial area. The trapetum (a rotating mill used to separate pips from olive fruit), anchor points and at least two presses can still be seen, as well as a set of settling vats used to purify oil.

Although large enough to have been the property of a rich aristocrat, the villa does not contain any residential quarters of any particular richness. The four rooms which can be identified as serving residential needs were, in fact, only decorated with painted wall plasters and common cocciopesto flooring.

The site was eventually reduced in size and surrounded by a thick fortification wall. This wall was erected circa the third century A.D. by the Romans as a mean for defence from invaders. Its fortified walls, constant water supply and good position meant that it was ideally located to control the nearby port and valleys.

During the Arab period the site was majorly destroyed due to sea invasions and attacks. The Arabs decided to use the remains to fortify the site with limited construction techniques.

A church was built on part of the site in the fourteenth century, but after more than a century it fell into disuse and in 1616 was replaced by a church dedicated to the welcoming of St. Paul. This church, which still stands today, is the oldest record connecting the site to the traditional event.

Excavation
Although the remains of the villa have long been well known, scientific excavations, led by the Missione Archeologica Italiana a Malta, did not commence until 1963. The final report on these excavations is yet to be published.

The site was included on the Antiquities List of 1925.

Today
Today, the site is managed by Heritage Malta and closed to the public except for annual occasions.

References

External links
National Inventory of the Cultural Property of the Maltese Islands

Archaeological sites in Malta
National Inventory of the Cultural Property of the Maltese Islands
Ancient Roman buildings and structures in Malta
Sites managed by Heritage Malta
Fortifications in Malta
Buildings and structures in St. Paul's Bay

redpajama_set_name: RedPajamaWikipedia


Hong Kong Battery Ltd is located in hong kong, we are the shipment, qc, hong kong c / o, timely delivery, supplier, mainly for the north america, southeast asia, western europe markets.
The Way Hong (Hong Kong) Co.
The Way Hong (Hong Kong) Co. is located in hong kong.
Realty Hong Kong Limited is located in hong kong.
Coba Hong Kong is located in hong kong, we are the salt, pepper supplier.
Pearl Hong Kong is located in hong kong, we are the lollipop supplier.
Vford Hong Kong Ltd. is located in hong kong.
Hong Kong Cran-Max is located in hong kong.
Cato Hong Kong Limited is located in hong kong, we are the baby item, product design, development, inventor assistance, supplier.
GOAL HONG KONG COMPANY is located in hong kong.
Hong Kong Workshop is located in hong kong, we are the arts & crafts, supplier.
Ahlers Bridge Hong Kong is located in hong kong.
OpenTRES Hong Kong Limited is located in hong kong.
SGS Hong Kong Limited is located in hong kong.
Imation Hong Kong Limited is located in hong kong.
hong kong db shopq is located in hong kong, we are the handbags supplier.
ASAHIKEIKI( HONG KONG )LIMITED is located in hong kong, we are the thermostat, supplier.
LeadMaster Hong Kong Ltd is located in hong kong.
Kingsford (Hong Kong) Ltd. is located in hong kong.
VMS Hong Kong Limited is located in hong kong.
creSer Hong Kong Limited is located in hong kong, we are the spare part supplier, mainly for the south america markets.


The Reserve Bank of Australia (RBA) has painted a pretty upbeat picture of the domestic economy even as it held interest rates at a record low for the 18th consecutive meeting today.
This is a "Goldilocks" outcome for equity investors who are having to stomach a significant increase in volatility for the S&P/ASX 200 (Index:^AXJO) (ASX:XJO) because low interest rates are supportive of share prices while the generally positive outlook from our usually conservative central bankers will bolster risk appetite.
A Goldilocks moment is when the economy isn't running too hot where the RBA will be forced to lift interest rates but isn't too cool as well to worry investors about growth.
The RBA's decision to keep interest rates at 1.5% will put a smile on the faces of shareholders in interest rate sensitive stocks like banking giants Commonwealth Bank of Australia (ASX: CBA) and Westpac Banking Corp (ASX: WBC), as well as infrastructure companies like Transurban Group (ASX: TCL) and Sydney Airport Holdings Pty Ltd (ASX: SYD).
Anaemic wages growth has bottomed. The RBA thinks that the poor wage growth which has been holding back the economy has troughed and is poised to recover as some employers are finding it difficult to find workers. Just don't expect a speedy recovery.
Trade war and China fears? What trade war and China fears? If the RBA is concerned about the Trump trade war, they aren't showing it. The rising risk of global trade barriers which are hammering stock markets around the world barely got a mention. If anything, the RBA is pretty optimistic about Chinese economic growth.
Growth is poised to accelerate. I would like to say "buckle in" but that might be overplaying it even though the RBA stressed that the Australian economy is forecast to grow faster in 2018 than the paltry 2.4% it achieved last year. But hey, faster growth is still good news for everyone!
Rising costs of debt even with record low interest rates. This is an interesting conundrum for the RBA who noted that bond yields have been rising, even in Australia. This is another reason why the RBA may stand pat on interest rates even as economic growth picks up steam. Throw in the risks of a trade war and record high household debt to the mix, and you can understand why the RBA may need to sit on its hands for the rest of 2018, if not beyond!
Worried about surplus apartments? You wouldn't be alone if you were concerned about the number of apartments that are set to hit the market at a time when the housing market is cooling. The RBA has flagged this risk and it doesn't have an answer to address this potential issue apart from hoping that APRA's credit controls will help avert any disasters.
Overall, the RBA has pointed to a lot more positives about the local economy than negatives. Astute investors might read this as a sign to buy any market dip.
If you are hunting for some blue-chip buying ideas, the experts at the Motley Fool may have just the thing for you.
They have produced a free report on their favourite blue-chip stock picks for 2018 and you can see what these are by click on the link below.
Motley Fool contributor Brendon Lau owns shares of Westpac Banking. The Motley Fool Australia owns shares of and has recommended Sydney Airport Holdings Limited. The Motley Fool Australia has recommended Transurban Group. We Fools may not all hold the same opinions, but we all believe that considering a diverse range of insights makes us better investors. The Motley Fool has a disclosure policy. This article contains general investment advice only (under AFSL 400691). Authorised by Scott Phillips.


text:
Q: A record pointed to an external ip + virtualhosts Good morning, I have 2 servers (#1 and #2)
My domain name is pointed to #1 and there in the DNS zone I pointed the "A record" to #2 IP address, (with this setup I can have mails on #1 and website on #2).
I know it's easier to make it the other way around but #2 is 100% configured by hand (#1 has cpanel) and I want to avoid potential DNS and mail issues.
The #2 is running Apache2 and I have virtual hosts configured there, however my domain name loads /var/www content (apache default) and not /home/myuser/www/ which is the patch specified as DocumentRoot.
I know virtual hosts are properly configured because previously I had the domain name pointed to #2 and they worked well.
What I am missing here guys?
apache2.conf: http://pastebin.com/52WB7LUw

redpajama_set_name: RedPajamaStackExchange


Great article. I had noticed several years ago that when I would google laminate flooring, vehicle info., etc, that ads would appear on FB and other sites I visited with those products. It felt like big brother was watching and that is exactly what is going on. I guess the best thing we can do for ourselves is to limit our visits to "who is your celebrity twin" type sites and only visit sites that are as secure as possible.
Yes it does seem like someone is over your shoulder watching you click links. Thanks for the comment.
I thought the same when my post was automatically being sent to FB and LinkedIn.


gold/copper/coal/iron/hematite/chrome ore sepration/concentration equipment . Tags: Copper Ore Dressing Equipment/flotation Processing Plant . Copper Ore .. Tags: Copper Ore Concentration Plant Manufacturer . Ore Beneficiation Plant.
Tags: Magnetite Ore Processing Line . Magnetite Ore Dressing Line . Sea Sand Iron Ore ... Tags: Iron Ore Beneficiation Line . Ore Processing Equipment . Ore.
Magnetite Iron Chrome Chromite Ore Beneficiation Plant , Find Complete Details . the mineral samples to your company, let your company run the ore dressing.
Copper lead zinc ore dressing beneficiation processing plants production line .. Gold, Iron, Lead, Zinc ore spiral classifier mineral processing for sale.
Iron Ore Processing Plant , Find Complete Details about Iron Ore Processing Plant,Iron Ore Processing Plant,Metal Processing Machines,Iron Ore Beneficiation Line from Mineral . We can supply a complete set of gold ore dressing machine.
gold/copper/coal/iron/hematite/chrome ore beneficiation equipment plant(jig). 1 Set (Min. Order) ... Low Price China Manufacturer Supply Ore Dressing Machine.
Hengcheng Small Gravity Plant Equipment Quartz Rock Gold Ore . process flow for various ore beneficiation, including iron ore, tin ore, copper ore, gold ore, . We have made many large&small scale ore dressing lines at home and abroad.
dressing ilmenite niobite limonite siderite pyrite magnetite hematite iron ore processing plant . for water treatment latest limonite iron ore beneficiation process.
Hot sale flotation cell for ilmenite ore dressing technology .. Tags: Magnetic Separator Beneficiation . Permanent Magnetic Separator . Iron Ore Dressing.
25 Years Professional Fiberglass Mineral Iron Ore Spiral Separator .. Competitive Price FG10 Gold Spiral Separator/Spiral Classifier For Ore Dressing Plant .. Spiral separator for ores upgrading,mineral processing,beneficiation.
Gravity Separation Equipment For Monazite Sand Ore , Find Complete Details about Gravity . such as iron, ilmenite, chromite, tungsten tin ore, niobium tantalum ore, gold placer, . Starting by running the mineral beneficiation experiment. . to your company, let your company run the ore dressing experiments test for us?
Chrome Ore Beneficiation Plant, Wholesale Various High Quality Chrome Ore . iron ore Beneficiation production line copper ore processing plant, copper . Ore dressing plant in Sudan, different capacity CIL plant EPC design for overseas.
Tags: Iron Ore Quarry . Graphite Mining Process . Stone Aggregate Crusher. Ore beneficiation , Ore Dressing SF Graphite Ore Flotation Cells. US $2100 25000 /.


Some people avoid bankruptcy out of a misplaced worry that it will ruin their credit rating and ability to borrow in the future. The surprising reality is that filing for bankruptcy usually improves a person's credit. Most people can qualify for consumer loans within a year or two.
Bankruptcy is no cakewalk, but it is an opportunity to get true debt relief, to get back on your financial feet and to restore good credit. The law firm of Stamps & Stamps, Attorneys at Law, can help you explore your debt relief solutions and separate fact from fiction so that you can make an informed decision.
When you file for bankruptcy, it is true that your credit score will dip initially. However, your credit score is probably poor already if you have a high debt-to-income ratio, especially if you are in default on loans or late paying your bills.
Our lead bankruptcy lawyer, Eric Stamps, pulls your credit report from the three main credit reporting agencies and compares your current scores with your projected score 12 months after filing for bankruptcy. For most of our clients, the projected credit score is 50 to 150 points higher than their current score. The simple math is that lenders and credit card companies see a better credit risk without all that debt weighing you down.
You will probably receive credit card offers within months of filing bankruptcy. Used in moderation, these will actually help you rebuild good credit.
You should be eligible for car loans at reasonable rates within one year or so.
You should be able to obtain a home loan at reasonable rates within two years or so.
Stamps & Stamps, Attorneys at Law, offers a free initial consultation to answer your questions about credit scores and all aspects of bankruptcy. We serve the Dayton area and surrounding counties of Ohio. Call us at (937) 247-6447 or 888-435-0085, or contact us online.


text:
<?php

declare(strict_types=1);

namespace App\Tests\RelationshipVoter;

use App\RelationshipVoter\AbstractVoter;
use App\RelationshipVoter\Cohort as Voter;
use App\Service\PermissionChecker;
use App\Entity\Cohort;
use App\Entity\ProgramYear;
use App\Entity\ProgramYearInterface;
use App\Service\Config;
use Mockery as m;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

class CohortTest extends AbstractBase
{
    public function setUp(): void
    {
        parent::setUp();
        $this->permissionChecker = m::mock(PermissionChecker::class);
        $this->voter = new Voter($this->permissionChecker);
    }

    public function testAllowsRootFullAccess()
    {
        $this->checkRootEntityAccess(m::mock(Cohort::class), [AbstractVoter::VIEW, AbstractVoter::EDIT]);
    }

    public function testCanView()
    {
        $token = $this->createMockTokenWithNonRootSessionUser();
        $entity = m::mock(Cohort::class);
        $response = $this->voter->vote($token, $entity, [AbstractVoter::VIEW]);
        $this->assertEquals(VoterInterface::ACCESS_GRANTED, $response, "View allowed");
    }

    public function testCanEdit()
    {
        $token = $this->createMockTokenWithNonRootSessionUser();
        $entity = m::mock(Cohort::class);
        $entity->shouldReceive('getProgramYear')->andReturn(m::mock(ProgramYearInterface::class));
        $this->permissionChecker->shouldReceive('canUpdateProgramYear')->andReturn(true);
        $response = $this->voter->vote($token, $entity, [AbstractVoter::EDIT]);
        $this->assertEquals(VoterInterface::ACCESS_GRANTED, $response, "Edit allowed");
    }

    public function testCanNotEdit()
    {
        $token = $this->createMockTokenWithNonRootSessionUser();
        $entity = m::mock(Cohort::class);
        $entity->shouldReceive('getProgramYear')->andReturn(m::mock(ProgramYearInterface::class));
        $this->permissionChecker->shouldReceive('canUpdateProgramYear')->andReturn(false);
        $response = $this->voter->vote($token, $entity, [AbstractVoter::EDIT]);
        $this->assertEquals(VoterInterface::ACCESS_DENIED, $response, "Edit denied");
    }
}

redpajama_set_name: RedPajamaGithub


text:
Q: get all details of validation after each epoch in training with keras I use keras ImageDataGenerator and fit_generator to train my images. After each epoch, the validation_loss and the validation_accuracy is printed on the console. Now is there an option in keras to print the datails of the validation on all the validation data?
For example I have 100 images in 5 class, as the validation data. Assume the val_loss after the first epoch is 75%, now I want to know which of those images got classified wrong and which is classified correct (in every  epoch).
I know I can test all the validation data with model.predict() one by one, but I need to get this prediction (validation) result in every epoch.


text:
Under-Qalified Paramedic Errors Lawyers | EMT Errors
Paramedics and EMTs are highly qualified health care professionals, and they do great work within the realm in which they are assigned. When it comes to triage in an emergency room, however, not all paramedics are fit for the task. By allowing an under-qualified paramedic or EMT to perform triage procedures within an emergency room, a hospital is widening its margin of error.
This step is often taken as a money-saving measure. In reality, nonpublic aid hospitals are not hurting for money. In fact, these institutions are wholly supported by insurance and pharmaceutical companies, two of the richest industries in the world. At the outset, a hospital and its staff should be more concerned about your well-being and your fast recovery.
There are very specific and simple measures in place that, if followed correctly, would eliminate these unnecessary, costly, life-threatening errors.
Consult Our Chicago, Illinois, Emergency Room Errors Lawyer
At Cirignani Heller & Harman, LLP, our attorneys are determined not only to get the compensation our clients deserve in these negligence cases but also to make a proactive and significant impact in the way these negligent hospitals follow the systems and processes in place that prevent these errors in the future. We want to save future patients from the same pain and stress that you are experiencing.
Contact Cirignani Heller & Harman, LLP
If you or a loved one is suffering after an error due to negligence by a hospital allowing an unqualified paramedic in an emergency room to serve as triage, contact us. We offer free initial consultations and contingency fees. Call (312) 346-8700.


text:
Eglingen es una localidad y comuna francesa, situada en el departamento de Alto Rin, en la región  de Alsacia.

Demografía

Referencias

Enlaces externos

 Eglingen en el Insee
 Eglingen en el sitio de informaciones generales quid.fr

 Plan d'Eglingen en Mapquest

Localidades de Alto Rin