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);
}
}
}
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);
}
}
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);
}
});
}
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);
}
}
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();
}
}
}
Aggregations