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();
}
}
}
use of com.alibaba.cobar.mysql.bio.Channel 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.Channel in project cobar by alibaba.
the class MultiNodeExecutor method newExecute.
/**
* 新通道的执行
*/
private void newExecute(final RouteResultsetNode rrn, final boolean autocommit, 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) {
handleFailure(ss, rrn, new SimpleErrInfo(new UnknownDataNodeException("Unknown dataNode '" + rrn.getName() + "'"), ErrorCode.ER_BAD_DB_ERROR, sc, rrn));
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 (final Exception e) {
handleFailure(ss, rrn, new SimpleErrInfo(e, ErrorCode.ER_BAD_DB_ERROR, sc, rrn));
return;
}
c.setRunning(true);
Channel old = ss.getTarget().put(rrn, c);
if (old != null && c != old) {
old.close();
}
// 执行
execute0(rrn, c, autocommit, ss, flag);
}
});
}
use of com.alibaba.cobar.mysql.bio.Channel in project cobar by alibaba.
the class MySQLDataSource method idleCheck.
public void idleCheck(long timeout) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Channel[] items = this.items;
long time = TimeUtil.currentTimeMillis() - timeout;
for (int i = 0; i < items.length; i++) {
Channel c = items[i];
if (c != null && time > c.getLastAcitveTime()) {
c.closeNoActive();
--idleCount;
items[i] = null;
}
}
} finally {
lock.unlock();
}
}
use of com.alibaba.cobar.mysql.bio.Channel in project cobar by alibaba.
the class MySQLDataSource method getChannel.
/**
* @return never null
*/
public Channel getChannel() throws Exception {
// 尝试从池中取得可用资源
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 当活跃资源大于等于池大小时,记录告警信息。
if (activeCount >= size) {
StringBuilder s = new StringBuilder();
s.append(Alarms.DEFAULT).append("[name=").append(name).append(",active=");
s.append(activeCount).append(",size=").append(size).append(']');
ALARM.error(s.toString());
}
// 检查池中是否有可用资源
final Channel[] items = this.items;
for (int i = 0; idleCount > 0 && i < items.length; i++) {
if (items[i] != null) {
Channel c = items[i];
items[i] = null;
--idleCount;
if (c.isClosed()) {
continue;
} else {
++activeCount;
return c;
}
}
}
// 将创建新连接,在此先假设创建成功。
++activeCount;
} finally {
lock.unlock();
}
// 创建新的资源
Channel c = factory.make(this);
try {
c.connect(node.getConfig().getWaitTimeout());
} catch (Exception e) {
lock.lock();
try {
--activeCount;
} finally {
lock.unlock();
}
c.closeNoActive();
throw e;
}
return c;
}
Aggregations