Search in sources :

Example 6 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method pooledSessionFailoverByPrioritiesAndPooling.

@Test
public void pooledSessionFailoverByPrioritiesAndPooling() {
    UnreliableSocketFactory.flushAllStaticData();
    final String testUriPattern = "mysqlx://%s:%s@[%s]/%s?" + PropertyKey.xdevapiConnectTimeout.getKeyName() + "=100&" + PropertyKey.socketFactory.getKeyName() + "=" + UnreliableSocketFactory.class.getName();
    String testHosts = IntStream.range(1, 6).mapToObj(i -> "host" + i).peek(h -> UnreliableSocketFactory.mapHost(h, getTestHost())).map(h -> "(address=" + h + ":" + getTestPort() + ",priority=%d)").collect(Collectors.joining(","));
    String testUriPatternPriorities = String.format(testUriPattern, getTestUser() == null ? "" : getTestUser(), getTestPassword() == null ? "" : getTestPassword(), testHosts, getTestDatabase());
    String testUri = String.format(testUriPatternPriorities, 60, 80, 100, 20, 40);
    int[] hostsOrder = new int[] { 3, 2, 1, 5, 4 };
    final ClientFactory cf = new ClientFactory();
    Client client = cf.getClient(testUri, "{\"pooling\" : {\"enabled\" : true, \"maxSize\" : 10} }");
    for (int i = 0; i < hostsOrder.length; i++) {
        int h = hostsOrder[i];
        Session testSession = client.getSession();
        assertTrue(UnreliableSocketFactory.isConnected());
        // Pool this connection.
        testSession.close();
        String lastHost = UnreliableSocketFactory.getHostFromLastConnection();
        assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + h), lastHost);
        List<String> connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
        assertEquals(i == 0 ? 1 : 2, connectionAttempts.size());
        for (int a = 0; a < connectionAttempts.size() - 1; a++) {
            assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[i - 1 + a]), connectionAttempts.get(a));
        }
        UnreliableSocketFactory.downHost("host" + h);
        UnreliableSocketFactory.flushConnectionAttempts();
    }
    // None of the hosts is available by now.
    assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", () -> {
        client.getSession();
        return null;
    });
    // Final connection tried the last known to be good host (host4) and then the remaining hosts by their priority
    List<String> connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    for (int i = 0; i < hostsOrder.length; i++) {
        assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[(i + 4) % 5]), connectionAttempts.get(i));
    }
    UnreliableSocketFactory.dontDownHost("host" + hostsOrder[1]);
    UnreliableSocketFactory.flushConnectionAttempts();
    Session testSession = client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    testSession.close();
    connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    assertEquals(2, connectionAttempts.size());
    assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[0]), connectionAttempts.get(0));
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + hostsOrder[1]), connectionAttempts.get(1));
    UnreliableSocketFactory.flushConnectionAttempts();
    // Pick previous connection from the pool. Doesn't count as new connections.
    Session testSession1 = client.getSession();
    assertEquals(0, UnreliableSocketFactory.getHostsFromAllConnections().size());
    // Create a new connection.
    Session testSession2 = client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    testSession1.close();
    testSession2.close();
    connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    assertEquals(1, connectionAttempts.size());
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + hostsOrder[1]), connectionAttempts.get(0));
    client.close();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) XDevAPIError(com.mysql.cj.xdevapi.XDevAPIError) RowResult(com.mysql.cj.xdevapi.RowResult) JsonNumber(com.mysql.cj.xdevapi.JsonNumber) ServerMessages(com.mysql.cj.x.protobuf.Mysqlx.ServerMessages) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) Random(java.util.Random) Collection(com.mysql.cj.xdevapi.Collection) ByteBuffer(java.nio.ByteBuffer) Constants(com.mysql.cj.Constants) Future(java.util.concurrent.Future) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) SqlStatement(com.mysql.cj.xdevapi.SqlStatement) Map(java.util.Map) ClientImpl(com.mysql.cj.xdevapi.ClientImpl) CoreSession(com.mysql.cj.CoreSession) ServerVersion(com.mysql.cj.ServerVersion) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) Warning(com.mysql.cj.xdevapi.Warning) SocketFactory(com.mysql.cj.protocol.SocketFactory) Set(java.util.Set) BlockingQueue(java.util.concurrent.BlockingQueue) XdevapiSslMode(com.mysql.cj.conf.PropertyDefinitions.XdevapiSslMode) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) Executors(java.util.concurrent.Executors) PropertyDefinitions(com.mysql.cj.conf.PropertyDefinitions) Test(org.junit.jupiter.api.Test) ByteOrder(java.nio.ByteOrder) List(java.util.List) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) FeatureNotAvailableException(com.mysql.cj.exceptions.FeatureNotAvailableException) SqlMultiResult(com.mysql.cj.xdevapi.SqlMultiResult) InjectedSocketFactory(testsuite.InjectedSocketFactory) FindStatement(com.mysql.cj.xdevapi.FindStatement) Assertions.fail(org.junit.jupiter.api.Assertions.fail) IntStream(java.util.stream.IntStream) MysqlErrorNumbers(com.mysql.cj.exceptions.MysqlErrorNumbers) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) CompletableFuture(java.util.concurrent.CompletableFuture) JsonString(com.mysql.cj.xdevapi.JsonString) Schema(com.mysql.cj.xdevapi.Schema) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) Client(com.mysql.cj.xdevapi.Client) ClientProperty(com.mysql.cj.xdevapi.Client.ClientProperty) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) WeakReference(java.lang.ref.WeakReference) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) ExecutorService(java.util.concurrent.ExecutorService) Session(com.mysql.cj.xdevapi.Session) Properties(java.util.Properties) Frame(com.mysql.cj.x.protobuf.MysqlxNotice.Frame) Iterator(java.util.Iterator) DbDoc(com.mysql.cj.xdevapi.DbDoc) DocResult(com.mysql.cj.xdevapi.DocResult) Field(java.lang.reflect.Field) Compression(com.mysql.cj.conf.PropertyDefinitions.Compression) XProtocolError(com.mysql.cj.protocol.x.XProtocolError) SessionFactory(com.mysql.cj.xdevapi.SessionFactory) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Row(com.mysql.cj.xdevapi.Row) SqlResult(com.mysql.cj.xdevapi.SqlResult) MessageLite(com.google.protobuf.MessageLite) AfterEach(org.junit.jupiter.api.AfterEach) SelectStatement(com.mysql.cj.xdevapi.SelectStatement) PooledXProtocol(com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol) PropertyKey(com.mysql.cj.conf.PropertyKey) CJPacketTooBigException(com.mysql.cj.exceptions.CJPacketTooBigException) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) JsonString(com.mysql.cj.xdevapi.JsonString) Client(com.mysql.cj.xdevapi.Client) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Example 7 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testPreparedStatementsPooledConnections.

@Test
public void testPreparedStatementsPooledConnections() {
    assumeTrue(mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.14")), "MySQL 8.0.14+ is required to run this test.");
    Properties props = new Properties();
    props.setProperty(ClientProperty.POOLING_ENABLED.getKeyName(), "true");
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "1");
    try {
        this.schema.createCollection("testPrepStmtPooling", true).add("{\"_id\":\"1\"}").execute();
        ClientFactory cf = new ClientFactory();
        Client testClient = cf.getClient(this.baseUrl, props);
        Session testSession = testClient.getSession();
        int sessionThreadId = getThreadId(testSession);
        assertPreparedStatementsCount(sessionThreadId, 0, 1);
        FindStatement testFind = testSession.getDefaultSchema().getCollection("testPrepStmtPooling").find();
        // 1st execute -> don't prepare.
        testFind.execute();
        assertPreparedStatementsCountsAndId(testSession, 0, testFind, 0, -1);
        assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
        // 2nd execute -> prepare + execute.
        testFind.execute();
        assertPreparedStatementsCountsAndId(testSession, 1, testFind, 1, 1);
        assertPreparedStatementsStatusCounts(testSession, 1, 1, 0);
        assertPreparedStatementsCount(sessionThreadId, 1, 1);
        // Prepared statements won't live past closing the session, or returning it to the pool.
        testSession.close();
        assertPreparedStatementsCount(sessionThreadId, 0, 10);
        testSession = testClient.getSession();
        sessionThreadId = getThreadId(testSession);
        assertPreparedStatementsCount(sessionThreadId, 0, 1);
        // The underlying connection object in testFind is the same as the one returned from the pool to the new session.
        // This exec attempt counts.
        assertThrows(XProtocolError.class, "ERROR 5110 \\(HY000\\) Statement with ID=1 was not prepared", testFind::execute);
        if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.16"))) {
            // Mysqlx.Session.Reset doesn't clear PS counters.
            assertPreparedStatementsStatusCounts(testSession, 1, 2, 0);
        } else {
            assertPreparedStatementsStatusCounts(testSession, 0, 1, 0);
        }
        testFind = testSession.getDefaultSchema().getCollection("testPrepStmtPooling").find();
        // 1st execute -> don't prepare.
        testFind.execute();
        assertPreparedStatementsCountsAndId(testSession, 0, testFind, 0, -1);
        if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.16"))) {
            // Mysqlx.Session.Reset doesn't clear PS counters.
            assertPreparedStatementsStatusCounts(testSession, 1, 2, 0);
        } else {
            assertPreparedStatementsStatusCounts(testSession, 0, 1, 0);
        }
        // 2nd execute -> prepare + execute.
        testFind.execute();
        assertPreparedStatementsCountsAndId(testSession, 1, testFind, 1, 1);
        if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.16"))) {
            // Mysqlx.Session.Reset doesn't clear PS counters.
            assertPreparedStatementsStatusCounts(testSession, 2, 3, 0);
        } else {
            assertPreparedStatementsStatusCounts(testSession, 1, 2, 0);
        }
        assertPreparedStatementsCount(sessionThreadId, 1, 1);
        // Prepared statements won't live past closing the client and its sessions.
        testClient.close();
        assertPreparedStatementsCount(sessionThreadId, 0, 10);
        assertThrows(CJCommunicationsException.class, "Unable to write message", testFind::execute);
    } finally {
        this.schema.dropCollection("testPrepStmtPooling");
    }
}
Also used : ClientFactory(com.mysql.cj.xdevapi.ClientFactory) FindStatement(com.mysql.cj.xdevapi.FindStatement) Properties(java.util.Properties) Client(com.mysql.cj.xdevapi.Client) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Example 8 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testBug97730.

/**
 * Tests fix for Bug#97730 (31699993), xdev api: ConcurrentModificationException at Session.close.
 *
 * @throws Throwable
 */
@Test
public void testBug97730() throws Throwable {
    for (String pooling : new String[] { "false", "true" }) {
        Properties props = new Properties();
        props.setProperty(ClientProperty.POOLING_ENABLED.getKeyName(), pooling);
        ClientFactory cf = new ClientFactory();
        Client client = cf.getClient(this.baseUrl, props);
        List<Future<?>> futures = new ArrayList<>();
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            futures.add(executor.submit(() -> {
                client.getSession().close();
            }));
        }
        Exception exception = null;
        for (Future<?> f : futures) {
            try {
                f.get();
            } catch (ExecutionException e) {
                exception = e;
                break;
            }
        }
        executor.shutdown();
        if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
            executor.shutdownNow();
        }
        if (exception != null) {
            throw exception.getCause();
        }
    }
}
Also used : ClientFactory(com.mysql.cj.xdevapi.ClientFactory) ArrayList(java.util.ArrayList) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) CompletableFuture(java.util.concurrent.CompletableFuture) JsonString(com.mysql.cj.xdevapi.JsonString) Properties(java.util.Properties) Client(com.mysql.cj.xdevapi.Client) ExecutionException(java.util.concurrent.ExecutionException) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) FileNotFoundException(java.io.FileNotFoundException) FeatureNotAvailableException(com.mysql.cj.exceptions.FeatureNotAvailableException) ExecutionException(java.util.concurrent.ExecutionException) CJPacketTooBigException(com.mysql.cj.exceptions.CJPacketTooBigException) Test(org.junit.jupiter.api.Test)

Example 9 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testSessionAttributes_checkClient.

private void testSessionAttributes_checkClient(String url, Map<String, String> userAttributes) throws Exception {
    ClientFactory cf = new ClientFactory();
    Client c = cf.getClient(url, new Properties());
    try {
        Session s0 = c.getSession();
        testSessionAttributes_checkSession(s0, userAttributes);
        // return to pool
        s0.close();
        // check that pooled session set the same attributes
        // get it from pool
        Session s1 = c.getSession();
        s1.sql("SELECT 1").execute();
        assertNotEquals(s0, s1);
        Field fProtocol = CoreSession.class.getDeclaredField("protocol");
        fProtocol.setAccessible(true);
        assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
        testSessionAttributes_checkSession(s1, userAttributes);
    } finally {
        c.close();
    }
}
Also used : Field(java.lang.reflect.Field) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) Client(com.mysql.cj.xdevapi.Client) Properties(java.util.Properties) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session)

Example 10 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testBug28616573.

@Test
public void testBug28616573() throws Exception {
    RowResult res = this.session.sql("select @@global.mysqlx_max_connections, VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='Mysqlx_worker_threads_active'").execute();
    Row r = res.next();
    int mysqlxMaxConnections = r.getInt(0);
    int mysqlWorkerThreadsActive = Integer.parseInt(r.getString(1));
    // allow only 2 additional connections
    this.session.sql("SET @@global.mysqlx_max_connections=" + (mysqlWorkerThreadsActive + 2)).execute();
    Properties props = new Properties();
    props.setProperty(ClientProperty.POOLING_ENABLED.getKeyName(), "true");
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "2");
    props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "2000");
    props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "2000");
    try {
        ClientFactory cf = new ClientFactory();
        Client cli1 = cf.getClient(this.baseUrl, props);
        Client cli2 = cf.getClient(this.baseUrl, props);
        // new connection #1
        Session sess1 = cli1.getSession();
        sess1.sql("SELECT 1").execute();
        sess1.close();
        // reuse connection #1
        sess1 = cli1.getSession();
        // new connection #2
        Session sess2 = cli1.getSession();
        sess2.sql("SELECT 1").execute();
        assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", cli2::getSession);
        cli1.close();
        cli2.close();
    } finally {
        this.session.sql("SET @@global.mysqlx_max_connections=" + mysqlxMaxConnections).execute();
    }
}
Also used : RowResult(com.mysql.cj.xdevapi.RowResult) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) Row(com.mysql.cj.xdevapi.Row) Properties(java.util.Properties) Client(com.mysql.cj.xdevapi.Client) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Aggregations

Client (com.mysql.cj.xdevapi.Client)11 ClientFactory (com.mysql.cj.xdevapi.ClientFactory)11 Properties (java.util.Properties)11 CoreSession (com.mysql.cj.CoreSession)10 Session (com.mysql.cj.xdevapi.Session)10 Test (org.junit.jupiter.api.Test)10 CJCommunicationsException (com.mysql.cj.exceptions.CJCommunicationsException)7 JsonString (com.mysql.cj.xdevapi.JsonString)7 CJPacketTooBigException (com.mysql.cj.exceptions.CJPacketTooBigException)6 FeatureNotAvailableException (com.mysql.cj.exceptions.FeatureNotAvailableException)6 WrongArgumentException (com.mysql.cj.exceptions.WrongArgumentException)6 SessionImpl (com.mysql.cj.xdevapi.SessionImpl)6 FileNotFoundException (java.io.FileNotFoundException)6 Field (java.lang.reflect.Field)6 ExecutionException (java.util.concurrent.ExecutionException)6 PooledXProtocol (com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol)5 FindStatement (com.mysql.cj.xdevapi.FindStatement)5 Row (com.mysql.cj.xdevapi.Row)5 RowResult (com.mysql.cj.xdevapi.RowResult)5 MessageLite (com.google.protobuf.MessageLite)4