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