use of io.mycat.proxy.reactor.ReactorEnvThread in project Mycat2 by MyCATApache.
the class RowSetQuery method runTextQuery.
public static PromiseInternal<SqlResult<Void>> runTextQuery(String curSql, MySQLClientSession mySQLClientSession, StreamMysqlCollector collectorArg) {
if (mySQLClientSession.getCurNIOHandler() != null) {
throw new IllegalArgumentException();
}
PromiseInternal<SqlResult<Void>> promise = VertxUtil.newPromise();
if (mySQLClientSession.getIOThread() == Thread.currentThread()) {
VertxMycatTextCollector<Object, Object> resultSetHandler = new VertxMycatTextCollector<Object, Object>((Collector) collectorArg);
if (LOGGER.isDebugEnabled()) {
if (curSql.startsWith("XA ROLLBACK")) {
LOGGER.debug("session id:{} sql:{}", mySQLClientSession.sessionId(), curSql, new Throwable());
}
LOGGER.debug("session id:{} sql:{}", mySQLClientSession.sessionId(), curSql);
}
resultSetHandler.request(mySQLClientSession, MySQLCommandType.COM_QUERY, curSql.getBytes(), new ResultSetCallBack<MySQLClientSession>() {
@Override
public void onFinishedSendException(Exception exception, Object sender, Object attr) {
MycatException mycatException = new MycatException(MySQLErrorCode.ER_UNKNOWN_ERROR, exception.getMessage());
LOGGER.error("session id:{} sql:{}", mySQLClientSession.sessionId(), curSql, mycatException);
promise.tryFail(mycatException);
}
@Override
public void onFinishedException(Exception exception, Object sender, Object attr) {
MycatException mycatException = new MycatException(MySQLErrorCode.ER_UNKNOWN_ERROR, exception.getMessage());
LOGGER.error("session id:{} sql:{}", mySQLClientSession.sessionId(), curSql, mycatException);
promise.tryFail(mycatException);
}
@Override
public void onFinished(boolean monopolize, MySQLClientSession mysql, Object sender, Object attr) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("onFinished session id:{} sql:{}", mySQLClientSession.sessionId(), curSql);
}
MySqlResult<Void> mySqlResult = new MySqlResult<>(resultSetHandler.getRowCount(), resultSetHandler.getAffectedRows(), resultSetHandler.getLastInsertId(), null, Optional.ofNullable(resultSetHandler.getRowResultDecoder()).map(i -> i.rowDesc).map(i -> i.columnDescriptor()).orElse(Collections.emptyList()));
promise.complete(mySqlResult);
}
@Override
public void onErrorPacket(ErrorPacketImpl errorPacket, boolean monopolize, MySQLClientSession mysql, Object sender, Object attr) {
MycatException mycatException = new MycatException(errorPacket.getErrorCode(), errorPacket.getErrorMessageString());
LOGGER.error("onErrorPacket session id:{} sql:{}", mySQLClientSession.sessionId(), curSql, mycatException);
promise.tryFail(mycatException);
}
});
} else {
mySQLClientSession.getIOThread().addNIOJob(new NIOJob() {
@Override
public void run(ReactorEnvThread reactor) throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.error("nio job session id:{} sql:{}", mySQLClientSession.sessionId(), curSql, new Throwable());
}
runTextQuery(curSql, mySQLClientSession, collectorArg).onComplete(promise);
}
@Override
public void stop(ReactorEnvThread reactor, Exception reason) {
promise.tryFail(reason);
}
@Override
public String message() {
return "proxy query text result set";
}
});
}
return promise;
}
use of io.mycat.proxy.reactor.ReactorEnvThread in project Mycat2 by MyCATApache.
the class MySQLDatasourcePool method createSession.
public Future<MySQLClientSession> createSession() {
if (!(Thread.currentThread() instanceof ReactorEnvThread)) {
return waitForIdleSession(false);
}
int limitCount = this.getSessionLimitCount();
synchronized (this) {
if (allSessions.size() >= limitCount && idleSessions.isEmpty()) {
return waitForIdleSession(true);
}
}
if (idleSessions.isEmpty()) {
Future<MySQLClientSession> future = innerCreateCon();
return future.recover(new Function<Throwable, Future<MySQLClientSession>>() {
final AtomicInteger retryCount = new AtomicInteger(0);
final long startTime = System.currentTimeMillis();
@Override
public Future<MySQLClientSession> apply(Throwable t) {
PromiseInternal<MySQLClientSession> promise = VertxUtil.newPromise();
long now = System.currentTimeMillis();
long maxConnectTimeout = MySQLDatasourcePool.this.getMaxConnectTimeout();
if (retryCount.get() >= limitCount) {
promise.tryFail(new MycatException("retry get connection fail:" + getName()));
} else if (startTime + maxConnectTimeout > now) {
promise.tryFail(new MycatException("retry get connection timeout:" + getName()));
} else {
retryCount.incrementAndGet();
waitForIdleSession(true).recover(this).onComplete(promise);
}
return promise.future();
}
});
} else {
MySQLClientSession session = idleSessions.removeFirst();
if (session.checkOpen()) {
session.setIdle(false);
session.switchNioHandler(null);
return Future.succeededFuture(session);
} else {
return session.close(false, "has closed").flatMap(unused -> createSession());
}
}
}
use of io.mycat.proxy.reactor.ReactorEnvThread in project Mycat2 by MyCATApache.
the class MySQLDatasourcePool method removeSession.
@Override
public Future<Void> removeSession(MySQLClientSession session, boolean normal, String reason) {
if (session.getIOThread() == Thread.currentThread()) {
decrementSessionCounter();
allSessions.remove(session);
idleSessions.remove(session);
session.resetPacket();
try {
session.channel().close();
} catch (Throwable ignore) {
LOGGER.error("", ignore);
}
return Future.succeededFuture();
}
PromiseInternal<Void> promise = VertxUtil.newPromise();
session.getIOThread().addNIOJob(new NIOJob() {
@Override
public void run(ReactorEnvThread reactor) throws Exception {
removeSession(session, normal, reason).onComplete(promise);
}
@Override
public void stop(ReactorEnvThread reactor, Exception hint) {
removeSession(session, normal, reason).onComplete(promise);
}
@Override
public String message() {
return "removeSession";
}
});
return promise.future();
}
use of io.mycat.proxy.reactor.ReactorEnvThread in project Mycat2 by MyCATApache.
the class MySQLDatasourcePool method addIdleSession.
public final Future<Void> addIdleSession(MySQLClientSession session) {
if (session.getIOThread() == Thread.currentThread()) {
if (!session.checkOpen()) {
return removeSession(session, false, "has close");
}
if (session.isMonopolized()) {
LOGGER.error("sessionId:{} isMonopolized", session.sessionId());
return removeSession(session, false, "monopolized");
}
try {
/**
* mycat对应透传模式对mysql session的占用
* niohandler对应透传以及task类对mysql session的占用
*/
assert session.getMycat() == null;
assert !session.hasClosed();
assert session.currentProxyBuffer() == null;
assert !session.isIdle();
session.setCursorStatementId(-1);
session.resetPacket();
session.setIdle(true);
session.switchNioHandler(IdleHandler.INSTANCE);
session.change2ReadOpts();
idleSessions.addFirst(session);
MycatMonitor.onAddIdleMysqlSession(session);
return VertxUtil.newSuccessPromise();
} catch (Exception e) {
LOGGER.error("", e);
return removeSession(session, false, e.getMessage());
}
} else {
PromiseInternal<Void> promise = VertxUtil.newPromise();
session.getIOThread().addNIOJob(new NIOJob() {
@Override
public void run(ReactorEnvThread reactor) throws Exception {
addIdleSession(session).onComplete(promise);
}
@Override
public void stop(ReactorEnvThread reactor, Exception reason) {
addIdleSession(session).onComplete(promise);
}
@Override
public String message() {
return "add idle session";
}
});
return promise.future();
}
}
use of io.mycat.proxy.reactor.ReactorEnvThread in project Mycat2 by MyCATApache.
the class MySQLDatasourcePool method waitForIdleSession.
private Future<MySQLClientSession> waitForIdleSession(boolean wait) {
PromiseInternal<MySQLClientSession> promise = VertxUtil.newPromise();
ReactorEnvThread reactorEnvThread;
if (Thread.currentThread() instanceof ReactorEnvThread) {
reactorEnvThread = (ReactorEnvThread) Thread.currentThread();
} else {
reactorEnvThread = this.server.getReactorManager().getRandomReactor();
}
if (wait) {
ScheduleUtil.getTimer().schedule(() -> {
nextStageForSession(promise, reactorEnvThread);
}, datasourceConfig.getMaxConnectTimeout() / datasourceConfig.getMaxRetryCount(), TimeUnit.MILLISECONDS);
} else {
nextStageForSession(promise, reactorEnvThread);
}
return promise;
}
Aggregations