Search in sources :

Example 1 with MySQLChannel

use of com.alibaba.cobar.mysql.bio.MySQLChannel in project cobar by alibaba.

the class SingleNodeExecutor method execute0.

/**
     * 数据通道执行
     */
private void execute0(RouteResultsetNode rrn, BlockingSession ss, Channel c, int flag) {
    final ServerConnection sc = ss.getSource();
    // 检查连接是否已关闭
    if (sc.isClosed()) {
        c.setRunning(false);
        endRunning();
        ss.clear();
        return;
    }
    try {
        // 执行并等待返回
        MySQLChannel mc = (MySQLChannel) c;
        BinaryPacket bin = mc.execute(rrn, sc, sc.isAutocommit());
        // 接收和处理数据
        switch(bin.data[0]) {
            case OkPacket.FIELD_COUNT:
                {
                    mc.setRunning(false);
                    if (mc.isAutocommit()) {
                        ss.clear();
                    }
                    endRunning();
                    // OK_PACKET
                    bin.packetId = ++packetId;
                    // set lastInsertId
                    setLastInsertId(bin, sc);
                    sc.write(bin.write(sc.allocate(), sc));
                    break;
                }
            case ErrorPacket.FIELD_COUNT:
                {
                    LOGGER.warn(mc.getErrLog(rrn.getStatement(), mc.getErrMessage(bin), sc));
                    mc.setRunning(false);
                    if (mc.isAutocommit()) {
                        ss.clear();
                    }
                    endRunning();
                    // ERROR_PACKET
                    bin.packetId = ++packetId;
                    sc.write(bin.write(sc.allocate(), sc));
                    break;
                }
            default:
                // HEADER|FIELDS|FIELD_EOF|ROWS|LAST_EOF
                handleResultSet(rrn, ss, mc, bin, flag);
        }
    } catch (IOException e) {
        LOGGER.warn(new StringBuilder().append(sc).append(rrn).toString(), e);
        c.close();
        String msg = e.getMessage();
        handleError(ErrorCode.ER_YES, msg == null ? e.getClass().getSimpleName() : msg, ss);
    } catch (RuntimeException e) {
        LOGGER.warn(new StringBuilder().append(sc).append(rrn).toString(), e);
        c.close();
        String msg = e.getMessage();
        handleError(ErrorCode.ER_YES, msg == null ? e.getClass().getSimpleName() : msg, ss);
    }
}
Also used : ServerConnection(com.alibaba.cobar.server.ServerConnection) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) IOException(java.io.IOException) BinaryPacket(com.alibaba.cobar.net.mysql.BinaryPacket)

Example 2 with MySQLChannel

use of com.alibaba.cobar.mysql.bio.MySQLChannel in project cobar by alibaba.

the class RollbackExecutor method rollback.

/**
     * 事务回滚
     */
public void rollback(final BlockingSession session) {
    final ServerConnection source = session.getSource();
    final ConcurrentMap<RouteResultsetNode, Channel> target = session.getTarget();
    final int initNodeCount = target.size();
    if (initNodeCount <= 0) {
        ByteBuffer buffer = source.allocate();
        source.write(source.writeToBuffer(OkPacket.OK, buffer));
        return;
    }
    // 初始化
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        this.isFail.set(false);
        this.nodeCount = initNodeCount;
    } finally {
        lock.unlock();
    }
    if (source.isClosed()) {
        decrementCountToZero();
        return;
    }
    // 执行
    Executor committer = source.getProcessor().getCommitter();
    int started = 0;
    for (RouteResultsetNode rrn : target.keySet()) {
        final MySQLChannel mc = (MySQLChannel) target.get(rrn);
        if (mc != null) {
            mc.setRunning(true);
            committer.execute(new Runnable() {

                @Override
                public void run() {
                    _rollback(mc, session);
                }
            });
            ++started;
        }
    }
    if (started < initNodeCount) {
        decrementCountBy(initNodeCount - started);
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) Executor(java.util.concurrent.Executor) RouteResultsetNode(com.alibaba.cobar.route.RouteResultsetNode) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel) ServerConnection(com.alibaba.cobar.server.ServerConnection) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) ByteBuffer(java.nio.ByteBuffer)

Example 3 with MySQLChannel

use of com.alibaba.cobar.mysql.bio.MySQLChannel in project cobar by alibaba.

the class BlockingSession method clear.

/**
     * MUST be called at the end of {@link NodeExecutor}
     * 
     * @param pessimisticRelease true if this method might be invoked
     *            concurrently with {@link #kill()}
     */
private void clear(boolean pessimisticRelease) {
    for (RouteResultsetNode rrn : target.keySet()) {
        Channel c = target.remove(rrn);
        // 通道不存在或者已被关闭
        if (c == null || c.isClosed()) {
            continue;
        }
        // 如果通道正在运行中,则关闭当前通道。
        if (c.isRunning() || (pessimisticRelease && source.isClosed())) {
            c.close();
            continue;
        }
        // 非事务中的通道,直接释放资源。
        if (c.isAutocommit()) {
            c.release();
            continue;
        }
        // 事务中的通道,需要先回滚后再释放资源。
        MySQLChannel mc = (MySQLChannel) c;
        try {
            BinaryPacket bin = mc.rollback();
            switch(bin.data[0]) {
                case OkPacket.FIELD_COUNT:
                    mc.release();
                    break;
                case ErrorPacket.FIELD_COUNT:
                    mc.close();
                    break;
                default:
                    throw new UnknownPacketException(bin.toString());
            }
        } catch (IOException e) {
            StringBuilder s = new StringBuilder();
            LOGGER.warn(s.append(mc).append("rollback").toString(), e);
            mc.close();
        } catch (RuntimeException e) {
            StringBuilder s = new StringBuilder();
            LOGGER.warn(s.append(mc).append("rollback").toString(), e);
            mc.close();
        }
    }
}
Also used : UnknownPacketException(com.alibaba.cobar.exception.UnknownPacketException) RouteResultsetNode(com.alibaba.cobar.route.RouteResultsetNode) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) IOException(java.io.IOException) BinaryPacket(com.alibaba.cobar.net.mysql.BinaryPacket)

Example 4 with MySQLChannel

use of com.alibaba.cobar.mysql.bio.MySQLChannel in project cobar by alibaba.

the class DefaultCommitExecutor method commit.

/**
     * 提交事务
     */
public void commit(final OkPacket packet, final BlockingSession session, final int initCount) {
    // 初始化
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        this.isFail.set(false);
        this.nodeCount = initCount;
        this.indicatedOK = packet;
    } finally {
        lock.unlock();
    }
    if (session.getSource().isClosed()) {
        decrementCountToZero();
        return;
    }
    // 执行
    final ConcurrentMap<RouteResultsetNode, Channel> target = session.getTarget();
    Executor committer = session.getSource().getProcessor().getCommitter();
    int started = 0;
    for (RouteResultsetNode rrn : target.keySet()) {
        if (rrn == null) {
            try {
                getLogger().error("null is contained in RoutResultsetNodes, source = " + session.getSource() + ", bindChannel = " + target);
            } catch (Exception e) {
            }
            continue;
        }
        final MySQLChannel mc = (MySQLChannel) target.get(rrn);
        if (mc != null) {
            mc.setRunning(true);
            committer.execute(new Runnable() {

                @Override
                public void run() {
                    _commit(mc, session);
                }
            });
            ++started;
        }
    }
    if (started < initCount && decrementCountBy(initCount - started)) {
        /**
             * assumption: only caused by front-end connection close. <br/>
             * Otherwise, packet must be returned to front-end
             */
        session.clear();
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) Executor(java.util.concurrent.Executor) RouteResultsetNode(com.alibaba.cobar.route.RouteResultsetNode) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) IOException(java.io.IOException) UnknownPacketException(com.alibaba.cobar.exception.UnknownPacketException)

Example 5 with MySQLChannel

use of com.alibaba.cobar.mysql.bio.MySQLChannel in project cobar by alibaba.

the class MultiNodeExecutor method execute0.

/**
     * 执行
     */
private void execute0(RouteResultsetNode rrn, Channel c, boolean autocommit, BlockingSession ss, int flag) {
    ServerConnection sc = ss.getSource();
    if (isFail.get() || sc.isClosed()) {
        c.setRunning(false);
        handleFailure(ss, rrn, null);
        return;
    }
    try {
        // 执行并等待返回
        BinaryPacket bin = ((MySQLChannel) c).execute(rrn, sc, autocommit);
        // 接收和处理数据
        final ReentrantLock lock = MultiNodeExecutor.this.lock;
        lock.lock();
        try {
            switch(bin.data[0]) {
                case ErrorPacket.FIELD_COUNT:
                    c.setRunning(false);
                    handleFailure(ss, rrn, new BinaryErrInfo((MySQLChannel) c, bin, sc, rrn));
                    break;
                case OkPacket.FIELD_COUNT:
                    OkPacket ok = new OkPacket();
                    ok.read(bin);
                    affectedRows += ok.affectedRows;
                    // set lastInsertId
                    if (ok.insertId > 0) {
                        insertId = (insertId == 0) ? ok.insertId : Math.min(insertId, ok.insertId);
                    }
                    c.setRunning(false);
                    handleSuccessOK(ss, rrn, autocommit, ok);
                    break;
                default:
                    // HEADER|FIELDS|FIELD_EOF|ROWS|LAST_EOF
                    final MySQLChannel mc = (MySQLChannel) c;
                    if (fieldEOF) {
                        for (; ; ) {
                            bin = mc.receive();
                            switch(bin.data[0]) {
                                case ErrorPacket.FIELD_COUNT:
                                    c.setRunning(false);
                                    handleFailure(ss, rrn, new BinaryErrInfo(mc, bin, sc, rrn));
                                    return;
                                case EOFPacket.FIELD_COUNT:
                                    handleRowData(rrn, c, ss);
                                    return;
                                default:
                                    continue;
                            }
                        }
                    } else {
                        // HEADER
                        bin.packetId = ++packetId;
                        List<MySQLPacket> headerList = new LinkedList<MySQLPacket>();
                        headerList.add(bin);
                        for (; ; ) {
                            bin = mc.receive();
                            switch(bin.data[0]) {
                                case ErrorPacket.FIELD_COUNT:
                                    c.setRunning(false);
                                    handleFailure(ss, rrn, new BinaryErrInfo(mc, bin, sc, rrn));
                                    return;
                                case EOFPacket.FIELD_COUNT:
                                    // FIELD_EOF
                                    bin.packetId = ++packetId;
                                    for (MySQLPacket packet : headerList) {
                                        buffer = packet.write(buffer, sc);
                                    }
                                    headerList = null;
                                    buffer = bin.write(buffer, sc);
                                    fieldEOF = true;
                                    handleRowData(rrn, c, ss);
                                    return;
                                default:
                                    // FIELDS
                                    bin.packetId = ++packetId;
                                    switch(flag) {
                                        case RouteResultset.REWRITE_FIELD:
                                            StringBuilder fieldName = new StringBuilder();
                                            fieldName.append("Tables_in_").append(ss.getSource().getSchema());
                                            FieldPacket field = PacketUtil.getField(bin, fieldName.toString());
                                            headerList.add(field);
                                            break;
                                        default:
                                            headerList.add(bin);
                                    }
                            }
                        }
                    }
            }
        } finally {
            lock.unlock();
        }
    } catch (final IOException e) {
        c.close();
        handleFailure(ss, rrn, new SimpleErrInfo(e, ErrorCode.ER_YES, sc, rrn));
    } catch (final RuntimeException e) {
        c.close();
        handleFailure(ss, rrn, new SimpleErrInfo(e, ErrorCode.ER_YES, sc, rrn));
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) OkPacket(com.alibaba.cobar.net.mysql.OkPacket) ServerConnection(com.alibaba.cobar.server.ServerConnection) IOException(java.io.IOException) LinkedList(java.util.LinkedList) MySQLPacket(com.alibaba.cobar.net.mysql.MySQLPacket) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) FieldPacket(com.alibaba.cobar.net.mysql.FieldPacket) BinaryPacket(com.alibaba.cobar.net.mysql.BinaryPacket)

Aggregations

MySQLChannel (com.alibaba.cobar.mysql.bio.MySQLChannel)5 IOException (java.io.IOException)4 Channel (com.alibaba.cobar.mysql.bio.Channel)3 BinaryPacket (com.alibaba.cobar.net.mysql.BinaryPacket)3 RouteResultsetNode (com.alibaba.cobar.route.RouteResultsetNode)3 ServerConnection (com.alibaba.cobar.server.ServerConnection)3 ReentrantLock (java.util.concurrent.locks.ReentrantLock)3 UnknownPacketException (com.alibaba.cobar.exception.UnknownPacketException)2 Executor (java.util.concurrent.Executor)2 FieldPacket (com.alibaba.cobar.net.mysql.FieldPacket)1 MySQLPacket (com.alibaba.cobar.net.mysql.MySQLPacket)1 OkPacket (com.alibaba.cobar.net.mysql.OkPacket)1 ByteBuffer (java.nio.ByteBuffer)1 LinkedList (java.util.LinkedList)1