[ 
https://issues.apache.org/jira/browse/IGNITE-19247?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Alexander Belyak updated IGNITE-19247:
--------------------------------------
    Description: 
This is very basic acceptance test.

Code below just create <TABLES> tables with <COLUMNS+1> columns (int key and 
varchar cols) and insert <ROWS> rows into each table (with SLEEP ms interval 
between operations, with <RETRY> attemps.

 
{noformat}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TimeoutExceptionReproducer {
    private static final String DB_URL = "jdbc:ignite:thin://172.24.1.2:10800";
    private static final int COLUMNS = 10;

    private static final String TABLE_NAME = "K";
    private static final int ROWS = 1000;

    private static final int TABLES = 10;

    private static final int BATCH_SIZE = 10;

    private static final int SLEEP = 30;

    private static final int RETRY = 10;

    private static String getCreateSql(String tableName) {
        StringBuilder sql = new StringBuilder("create table 
").append(tableName).append(" (id int primary key");

        for (int i = 0; i < COLUMNS; i++) {
            sql.append(", col").append(i).append(" varchar NOT NULL");
        }

        sql.append(")");

        return sql.toString();
    }

    private static final void s() {
        if (SLEEP > 0) {
            try {
                Thread.sleep(SLEEP);
            } catch (InterruptedException e) {
                // NoOp
            }
        }
    }

    private static void createTables(Connection connection, String tableName) 
throws SQLException {
        try (Statement stmt = connection.createStatement()) {
            System.out.println("Creating " + tableName);

            stmt.executeUpdate("drop table if exists " + tableName );
            s();
            stmt.executeUpdate(getCreateSql(tableName));
            s();
        }
    }

    private static String getInsertSql(String tableName) {
        StringBuilder sql = new StringBuilder("insert into 
").append(tableName).append(" values(?");

        for (int i = 0; i < COLUMNS; i++) {
            sql.append(", ?");
        }

        sql.append(")");

        return sql.toString();
    }

    private static void insertBatch(PreparedStatement ps) {
        int retryCounter = 0;
        while(retryCounter <= RETRY) {
            try {
                ps.executeBatch();

                return;
            } catch (SQLException e) {
                System.err.println(retryCounter + " error while executing " + 
ps + ":" + e);

                retryCounter++;
            }
        }
    }

    private static void insertData(Connection connection, String tableName) 
throws SQLException {
        long ts = System.currentTimeMillis();
        try (PreparedStatement ps = 
connection.prepareStatement(getInsertSql(tableName))) {
            int batch = 0;

            for (int i = 0; i < ROWS; i++) {
                ps.setInt(1, i);

                for (int j = 2; j < COLUMNS + 2; j++) {
                    ps.setString(j, "value" + i + "_" + j);
                }

                ps.addBatch();
                batch++;

                if (batch == BATCH_SIZE) {
                    batch = 0;
                    insertBatch(ps);
                    ps.clearBatch();

                    System.out.println("Batch " + BATCH_SIZE + " took " + 
(System.currentTimeMillis() - ts) + " to get " + i + " rows");

                    s();
                    ts = System.currentTimeMillis();
                }
            }

            if (batch > 0) {
                insertBatch(ps);
                ps.clearBatch();
                s();
            }
        }
    }

    private static int testData(Connection connection, String tableName) throws 
SQLException {
        try (Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery("select count(*) from " + 
tableName);) {
            rs.next();

            int count = rs.getInt(1);

            int result = ROWS - count;

            if (result == 0) {
                System.out.println("Found " + count + " rows in " + tableName);
            } else {
                System.err.println("Found " + count + " rows in " + tableName + 
" instead of " + ROWS);
            }

            s();

            return result;
        }
    }

    public static void main(String[] args) throws SQLException {
        int lostRows = 0;
        try (Connection connection = DriverManager.getConnection(DB_URL)) {
            for (int i = 0; i < TABLES; i++) {
                String tableName = TABLE_NAME + i;
                createTables(connection, tableName);

                insertData(connection, tableName);

                lostRows += testData(connection, tableName);
            }
        }

        System.exit(lostRows);
    }
}
{noformat}
 And we can see some problems, like:

1) Replication timeout exception

2) Data loss

even if there are only one node in the cluster, small number of columns, tables 
and rows and huge sleep between operations.

  was:
{color:#0033b3}import {color}{color:#000000}java.sql.Connection{color};
{color:#0033b3}import {color}{color:#000000}java.sql.DriverManager{color};
{color:#0033b3}import {color}{color:#000000}java.sql.PreparedStatement{color};
{color:#0033b3}import {color}{color:#000000}java.sql.ResultSet{color};
{color:#0033b3}import {color}{color:#000000}java.sql.SQLException{color};
{color:#0033b3}import {color}{color:#000000}java.sql.Statement{color};

{color:#0033b3}public class {color}{color:#000000}TimeoutExceptionReproducer 
{color}{
{color:#0033b3}private static final {color}{color:#000000}String 
{color}{color:#871094}DB_URL {color}= 
{color:#067d17}"jdbc:ignite:thin://172.24.1.2:10800"{color};
{color:#0033b3}private static final int {color}{color:#871094}COLUMNS {color}= 
{color:#1750eb}10{color};

{color:#0033b3}private static final {color}{color:#000000}String 
{color}{color:#871094}TABLE_NAME {color}= {color:#067d17}"K"{color};
{color:#0033b3}private static final int {color}{color:#871094}ROWS {color}= 
{color:#1750eb}1000{color};

{color:#0033b3}private static final int {color}{color:#871094}TABLES {color}= 
{color:#1750eb}10{color};

{color:#0033b3}private static final int {color}{color:#871094}BATCH_SIZE 
{color}= {color:#1750eb}10{color};

{color:#0033b3}private static final int {color}{color:#871094}SLEEP {color}= 
{color:#1750eb}30{color};

{color:#0033b3}private static final int {color}{color:#871094}RETRY {color}= 
{color:#1750eb}10{color};

{color:#0033b3}private static {color}{color:#000000}String 
{color}{color:#00627a}getCreateSql{color}({color:#000000}String 
{color}tableName) {
{color:#000000}StringBuilder sql {color}= {color:#0033b3}new 
{color}StringBuilder({color:#067d17}"create table 
"{color}).append(tableName).append({color:#067d17}" (id int primary 
key"{color});

{color:#0033b3}for {color}({color:#0033b3}int {color}i = 
{color:#1750eb}0{color}; i < {color:#871094}COLUMNS{color}; i++) {
{color:#000000}sql{color}.append({color:#067d17}", 
col"{color}).append(i).append({color:#067d17}" varchar NOT NULL"{color});
}

{color:#000000}sql{color}.append({color:#067d17}")"{color});

{color:#0033b3}return {color}{color:#000000}sql{color}.toString();
}

{color:#0033b3}private static final void {color}{color:#00627a}s{color}() {
{color:#0033b3}if {color}({color:#871094}SLEEP {color}> 
{color:#1750eb}0{color}) {
{color:#0033b3}try {color}{
{color:#000000}Thread{color}.sleep({color:#871094}SLEEP{color});
} {color:#0033b3}catch {color}({color:#000000}InterruptedException {color}e) {
{color:#8c8c8c}// NoOp
{color}{color:#8c8c8c} {color}}
}
}

{color:#0033b3}private static void 
{color}{color:#00627a}createTables{color}({color:#000000}Connection 
{color}connection, {color:#000000}String {color}tableName) 
{color:#0033b3}throws {color}{color:#000000}SQLException {color}{
{color:#0033b3}try {color}({color:#000000}Statement stmt {color}= 
connection.createStatement()) {
{color:#000000}System{color}.{color:#871094}out{color}.println({color:#067d17}"Creating
 " {color}+ tableName);

{color:#000000}stmt{color}.executeUpdate({color:#067d17}"{color}{color:#067d17}drop
 table if exists {color}{color:#067d17}" {color}+ tableName );
s();
{color:#000000}stmt{color}.executeUpdate(getCreateSql(tableName));
s();
}
}

{color:#0033b3}private static {color}{color:#000000}String 
{color}{color:#00627a}getInsertSql{color}({color:#000000}String 
{color}tableName) {
{color:#000000}StringBuilder sql {color}= {color:#0033b3}new 
{color}StringBuilder({color:#067d17}"insert into 
"{color}).append(tableName).append({color:#067d17}" values(?"{color});

{color:#0033b3}for {color}({color:#0033b3}int {color}i = 
{color:#1750eb}0{color}; i < {color:#871094}COLUMNS{color}; i++) {
{color:#000000}sql{color}.append({color:#067d17}", ?"{color});
}

{color:#000000}sql{color}.append({color:#067d17}")"{color});

{color:#0033b3}return {color}{color:#000000}sql{color}.toString();
}

{color:#0033b3}private static void 
{color}{color:#00627a}insertBatch{color}({color:#000000}PreparedStatement 
{color}ps) {
{color:#0033b3}int {color}retryCounter = {color:#1750eb}0{color};
{color:#0033b3}while{color}(retryCounter <= {color:#871094}RETRY{color}) {
{color:#0033b3}try {color}{
ps.executeBatch();

{color:#0033b3}return{color};
} {color:#0033b3}catch {color}({color:#000000}SQLException {color}e) {
{color:#000000}System{color}.{color:#871094}err{color}.println(retryCounter + 
{color:#067d17}" error while executing " {color}+ ps + {color:#067d17}":" 
{color}+ e);

retryCounter++;
}
}
}

{color:#0033b3}private static void 
{color}{color:#00627a}insertData{color}({color:#000000}Connection 
{color}connection, {color:#000000}String {color}tableName) 
{color:#0033b3}throws {color}{color:#000000}SQLException {color}{
{color:#0033b3}long {color}ts = 
{color:#000000}System{color}.currentTimeMillis();
{color:#0033b3}try {color}({color:#000000}PreparedStatement ps {color}= 
connection.prepareStatement(getInsertSql(tableName))) {
{color:#0033b3}int {color}batch = {color:#1750eb}0{color};

{color:#0033b3}for {color}({color:#0033b3}int {color}i = 
{color:#1750eb}0{color}; i < {color:#871094}ROWS{color}; i++) {
{color:#000000}ps{color}.setInt({color:#1750eb}1{color}, i);

{color:#0033b3}for {color}({color:#0033b3}int {color}j = 
{color:#1750eb}2{color}; j < {color:#871094}COLUMNS {color}+ 
{color:#1750eb}2{color}; j++) {
{color:#000000}ps{color}.setString(j, {color:#067d17}"value" {color}+ i + 
{color:#067d17}"_" {color}+ j);
}

{color:#000000}ps{color}.addBatch();
batch++;

{color:#0033b3}if {color}(batch == {color:#871094}BATCH_SIZE{color}) {
batch = {color:#1750eb}0{color};
insertBatch({color:#000000}ps{color});
{color:#000000}ps{color}.clearBatch();

{color:#000000}System{color}.{color:#871094}out{color}.println({color:#067d17}"Batch
 " {color}+ {color:#871094}BATCH_SIZE {color}+ {color:#067d17}" took " {color}+ 
({color:#000000}System{color}.currentTimeMillis() - ts) + {color:#067d17}" to 
get " {color}+ i + {color:#067d17}" rows"{color});

s();
ts = {color:#000000}System{color}.currentTimeMillis();
}
}

{color:#0033b3}if {color}(batch > {color:#1750eb}0{color}) {
insertBatch({color:#000000}ps{color});
{color:#000000}ps{color}.clearBatch();
s();
}
}
}

{color:#0033b3}private static int 
{color}{color:#00627a}testData{color}({color:#000000}Connection 
{color}connection, {color:#000000}String {color}tableName) 
{color:#0033b3}throws {color}{color:#000000}SQLException {color}{
{color:#0033b3}try {color}({color:#000000}Statement stmt {color}= 
connection.createStatement();
{color:#000000}ResultSet rs {color}= 
{color:#000000}stmt{color}.executeQuery({color:#067d17}"{color}{color:#067d17}select
 count(*) from {color}{color:#067d17}" {color}+ tableName);) {
{color:#000000}rs{color}.next();

{color:#0033b3}int {color}{color:#000000}count {color}= 
{color:#000000}rs{color}.getInt({color:#1750eb}1{color});

{color:#0033b3}int {color}{color:#000000}result {color}= {color:#871094}ROWS 
{color}- {color:#000000}count{color};

{color:#0033b3}if {color}({color:#000000}result {color}== 
{color:#1750eb}0{color}) {
{color:#000000}System{color}.{color:#871094}out{color}.println({color:#067d17}"Found
 " {color}+ {color:#000000}count {color}+ {color:#067d17}" rows in " {color}+ 
tableName);
} {color:#0033b3}else {color}{
{color:#000000}System{color}.{color:#871094}err{color}.println({color:#067d17}"Found
 " {color}+ {color:#000000}count {color}+ {color:#067d17}" rows in " {color}+ 
tableName + {color:#067d17}" instead of " {color}+ {color:#871094}ROWS{color});
}

s();

{color:#0033b3}return {color}{color:#000000}result{color};
}
}

{color:#0033b3}public static void 
{color}{color:#00627a}main{color}({color:#000000}String{color}[] args) 
{color:#0033b3}throws {color}{color:#000000}SQLException {color}{
{color:#0033b3}int {color}lostRows = {color:#1750eb}0{color};
{color:#0033b3}try {color}({color:#000000}Connection connection {color}= 
{color:#000000}DriverManager{color}.getConnection({color:#871094}DB_URL{color}))
 {
{color:#0033b3}for {color}({color:#0033b3}int {color}i = 
{color:#1750eb}0{color}; i < {color:#871094}TABLES{color}; i++) {
{color:#000000}String tableName {color}= {color:#871094}TABLE_NAME {color}+ i;
createTables({color:#000000}connection{color}, {color:#000000}tableName{color});

insertData({color:#000000}connection{color}, {color:#000000}tableName{color});

lostRows += testData({color:#000000}connection{color}, 
{color:#000000}tableName{color});
}
}

{color:#000000}System{color}.exit(lostRows);
}
}


> Replication is timed out
> ------------------------
>
>                 Key: IGNITE-19247
>                 URL: https://issues.apache.org/jira/browse/IGNITE-19247
>             Project: Ignite
>          Issue Type: Bug
>          Components: general
>    Affects Versions: 3.0
>            Reporter: Alexander Belyak
>            Priority: Critical
>              Labels: ignite-3
>             Fix For: 3.0
>
>
> This is very basic acceptance test.
> Code below just create <TABLES> tables with <COLUMNS+1> columns (int key and 
> varchar cols) and insert <ROWS> rows into each table (with SLEEP ms interval 
> between operations, with <RETRY> attemps.
>  
> {noformat}
> import java.sql.Connection;
> import java.sql.DriverManager;
> import java.sql.PreparedStatement;
> import java.sql.ResultSet;
> import java.sql.SQLException;
> import java.sql.Statement;
> public class TimeoutExceptionReproducer {
>     private static final String DB_URL = 
> "jdbc:ignite:thin://172.24.1.2:10800";
>     private static final int COLUMNS = 10;
>     private static final String TABLE_NAME = "K";
>     private static final int ROWS = 1000;
>     private static final int TABLES = 10;
>     private static final int BATCH_SIZE = 10;
>     private static final int SLEEP = 30;
>     private static final int RETRY = 10;
>     private static String getCreateSql(String tableName) {
>         StringBuilder sql = new StringBuilder("create table 
> ").append(tableName).append(" (id int primary key");
>         for (int i = 0; i < COLUMNS; i++) {
>             sql.append(", col").append(i).append(" varchar NOT NULL");
>         }
>         sql.append(")");
>         return sql.toString();
>     }
>     private static final void s() {
>         if (SLEEP > 0) {
>             try {
>                 Thread.sleep(SLEEP);
>             } catch (InterruptedException e) {
>                 // NoOp
>             }
>         }
>     }
>     private static void createTables(Connection connection, String tableName) 
> throws SQLException {
>         try (Statement stmt = connection.createStatement()) {
>             System.out.println("Creating " + tableName);
>             stmt.executeUpdate("drop table if exists " + tableName );
>             s();
>             stmt.executeUpdate(getCreateSql(tableName));
>             s();
>         }
>     }
>     private static String getInsertSql(String tableName) {
>         StringBuilder sql = new StringBuilder("insert into 
> ").append(tableName).append(" values(?");
>         for (int i = 0; i < COLUMNS; i++) {
>             sql.append(", ?");
>         }
>         sql.append(")");
>         return sql.toString();
>     }
>     private static void insertBatch(PreparedStatement ps) {
>         int retryCounter = 0;
>         while(retryCounter <= RETRY) {
>             try {
>                 ps.executeBatch();
>                 return;
>             } catch (SQLException e) {
>                 System.err.println(retryCounter + " error while executing " + 
> ps + ":" + e);
>                 retryCounter++;
>             }
>         }
>     }
>     private static void insertData(Connection connection, String tableName) 
> throws SQLException {
>         long ts = System.currentTimeMillis();
>         try (PreparedStatement ps = 
> connection.prepareStatement(getInsertSql(tableName))) {
>             int batch = 0;
>             for (int i = 0; i < ROWS; i++) {
>                 ps.setInt(1, i);
>                 for (int j = 2; j < COLUMNS + 2; j++) {
>                     ps.setString(j, "value" + i + "_" + j);
>                 }
>                 ps.addBatch();
>                 batch++;
>                 if (batch == BATCH_SIZE) {
>                     batch = 0;
>                     insertBatch(ps);
>                     ps.clearBatch();
>                     System.out.println("Batch " + BATCH_SIZE + " took " + 
> (System.currentTimeMillis() - ts) + " to get " + i + " rows");
>                     s();
>                     ts = System.currentTimeMillis();
>                 }
>             }
>             if (batch > 0) {
>                 insertBatch(ps);
>                 ps.clearBatch();
>                 s();
>             }
>         }
>     }
>     private static int testData(Connection connection, String tableName) 
> throws SQLException {
>         try (Statement stmt = connection.createStatement();
>             ResultSet rs = stmt.executeQuery("select count(*) from " + 
> tableName);) {
>             rs.next();
>             int count = rs.getInt(1);
>             int result = ROWS - count;
>             if (result == 0) {
>                 System.out.println("Found " + count + " rows in " + 
> tableName);
>             } else {
>                 System.err.println("Found " + count + " rows in " + tableName 
> + " instead of " + ROWS);
>             }
>             s();
>             return result;
>         }
>     }
>     public static void main(String[] args) throws SQLException {
>         int lostRows = 0;
>         try (Connection connection = DriverManager.getConnection(DB_URL)) {
>             for (int i = 0; i < TABLES; i++) {
>                 String tableName = TABLE_NAME + i;
>                 createTables(connection, tableName);
>                 insertData(connection, tableName);
>                 lostRows += testData(connection, tableName);
>             }
>         }
>         System.exit(lostRows);
>     }
> }
> {noformat}
>  And we can see some problems, like:
> 1) Replication timeout exception
> 2) Data loss
> even if there are only one node in the cluster, small number of columns, 
> tables and rows and huge sleep between operations.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to