Search in sources :

Example 1 with Channel

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

the class MultiNodeExecutor method execute.

/**
 * 多数据节点执行
 *
 * @param nodes never null
 */
public void execute(RouteResultsetNode[] nodes, final boolean autocommit, final BlockingSession ss, final int flag) {
    // 初始化
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        this.isFail.set(false);
        this.unfinishedNodeCount = nodes.length;
        this.errno = 0;
        this.errMessage = null;
        this.fieldEOF = false;
        this.packetId = 0;
        this.affectedRows = 0L;
        this.insertId = 0L;
        this.buffer = ss.getSource().allocate();
    } finally {
        lock.unlock();
    }
    if (ss.getSource().isClosed()) {
        decrementCountToZero();
        ss.getSource().recycle(this.buffer);
        return;
    }
    // 多节点处理
    ConcurrentMap<RouteResultsetNode, Channel> target = ss.getTarget();
    for (RouteResultsetNode rrn : nodes) {
        Channel c = target.get(rrn);
        if (c != null) {
            c.setRunning(true);
        }
    }
    ThreadPoolExecutor exec = ss.getSource().getProcessor().getExecutor();
    for (final RouteResultsetNode rrn : nodes) {
        final Channel c = target.get(rrn);
        if (c != null) {
            exec.execute(new Runnable() {

                @Override
                public void run() {
                    execute0(rrn, c, autocommit, ss, flag);
                }
            });
        } else {
            newExecute(rrn, autocommit, ss, flag);
        }
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) RouteResultsetNode(com.alibaba.cobar.route.RouteResultsetNode) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor)

Example 2 with Channel

use of com.alibaba.cobar.mysql.bio.Channel 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 Channel

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

the class SingleNodeExecutor method newExecute.

/**
 * 新数据通道的执行
 */
private void newExecute(final RouteResultsetNode rrn, final BlockingSession ss, final int flag) {
    final ServerConnection sc = ss.getSource();
    // 检查数据节点是否存在
    CobarConfig conf = CobarServer.getInstance().getConfig();
    final MySQLDataNode dn = conf.getDataNodes().get(rrn.getName());
    if (dn == null) {
        LOGGER.warn(new StringBuilder().append(sc).append(rrn).toString(), new UnknownDataNodeException());
        handleError(ErrorCode.ER_BAD_DB_ERROR, "Unknown dataNode '" + rrn.getName() + "'", ss);
        return;
    }
    // 提交执行任务
    sc.getProcessor().getExecutor().execute(new Runnable() {

        @Override
        public void run() {
            // 取得数据通道
            int i = rrn.getReplicaIndex();
            Channel c = null;
            try {
                c = (i == DEFAULT_REPLICA_INDEX) ? dn.getChannel() : dn.getChannel(i);
            } catch (Exception e) {
                LOGGER.warn(new StringBuilder().append(sc).append(rrn).toString(), e);
                String msg = e.getMessage();
                handleError(ErrorCode.ER_BAD_DB_ERROR, msg == null ? e.getClass().getSimpleName() : msg, ss);
                return;
            }
            // 检查连接是否已关闭。
            if (sc.isClosed()) {
                c.release();
                endRunning();
                return;
            }
            // 绑定数据通道
            c.setRunning(true);
            Channel old = ss.getTarget().put(rrn, c);
            if (old != null && old != c) {
                old.close();
            }
            // 执行
            execute0(rrn, ss, c, flag);
        }
    });
}
Also used : MySQLDataNode(com.alibaba.cobar.mysql.MySQLDataNode) UnknownDataNodeException(com.alibaba.cobar.exception.UnknownDataNodeException) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel) ServerConnection(com.alibaba.cobar.server.ServerConnection) CobarConfig(com.alibaba.cobar.CobarConfig) UnknownDataNodeException(com.alibaba.cobar.exception.UnknownDataNodeException) IOException(java.io.IOException)

Example 4 with Channel

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

the class SingleNodeExecutor method execute.

/**
 * 单数据节点执行
 */
public void execute(RouteResultsetNode rrn, BlockingSession ss, int flag) {
    // 初始化
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        this.packetId = 0;
        this.isRunning = true;
    } finally {
        lock.unlock();
    }
    // 检查连接是否已关闭
    if (ss.getSource().isClosed()) {
        endRunning();
        return;
    }
    // 单节点处理
    Channel c = ss.getTarget().get(rrn);
    if (c != null) {
        c.setRunning(true);
        bindingExecute(rrn, ss, c, flag);
    } else {
        newExecute(rrn, ss, flag);
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) MySQLChannel(com.alibaba.cobar.mysql.bio.MySQLChannel) Channel(com.alibaba.cobar.mysql.bio.Channel)

Example 5 with Channel

use of com.alibaba.cobar.mysql.bio.Channel 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)

Aggregations

Channel (com.alibaba.cobar.mysql.bio.Channel)14 ReentrantLock (java.util.concurrent.locks.ReentrantLock)8 MySQLChannel (com.alibaba.cobar.mysql.bio.MySQLChannel)7 RouteResultsetNode (com.alibaba.cobar.route.RouteResultsetNode)4 IOException (java.io.IOException)4 ServerConnection (com.alibaba.cobar.server.ServerConnection)3 CobarConfig (com.alibaba.cobar.CobarConfig)2 UnknownDataNodeException (com.alibaba.cobar.exception.UnknownDataNodeException)2 UnknownPacketException (com.alibaba.cobar.exception.UnknownPacketException)2 MySQLDataNode (com.alibaba.cobar.mysql.MySQLDataNode)2 Executor (java.util.concurrent.Executor)2 ConfigException (com.alibaba.cobar.config.util.ConfigException)1 BinaryPacket (com.alibaba.cobar.net.mysql.BinaryPacket)1 ByteBuffer (java.nio.ByteBuffer)1 SQLSyntaxErrorException (java.sql.SQLSyntaxErrorException)1 ThreadPoolExecutor (java.util.concurrent.ThreadPoolExecutor)1