package org.opencloudb.sqlengine;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.opencloudb.MycatConfig;
import org.opencloudb.MycatSystem;
import org.opencloudb.backend.BackendConnection;
import org.opencloudb.backend.ConnectionMeta;
import org.opencloudb.backend.PhysicalDBNode;
import org.opencloudb.mysql.nio.handler.ResponseHandler;
import org.opencloudb.net.ConnectionInfo;
import org.opencloudb.net.mysql.ErrorPacket;
import org.opencloudb.route.RouteResultsetNode;
import org.opencloudb.server.parser.ServerParse;
public class SQLJob implements ResponseHandler, Runnable {
private final String sql;
private final String dataNode;
private final SQLJobHandler jobHandler;
private final EngineCtx ctx;
private final int id;
public SQLJob(int id, String sql, String dataNode,
SQLJobHandler jobHandler, EngineCtx ctx) {
super();
this.id = id;
this.sql = sql;
this.dataNode = dataNode;
this.jobHandler = jobHandler;
this.ctx = ctx;
}
public void run() {
RouteResultsetNode node = new RouteResultsetNode(dataNode,
ServerParse.SELECT, sql);
// create new connection
ConnectionInfo conINfo=ctx.getSession().getConInfo();
MycatConfig conf = MycatSystem.getInstance().getConfig();
PhysicalDBNode dn = conf.getDataNodes().get(node.getName());
ConnectionMeta conMeta = new ConnectionMeta(dn.getDatabase(),
conINfo.getCharset(), conINfo.getCharsetIndex(), true);
try {
dn.getConnection(conMeta, node, this, node);
} catch (Exception e) {
EngineCtx.LOGGER.info("can't get connection for sql ,error:" + e);
doFinished(true);
}
}
@Override
public void connectionAcquired(final BackendConnection conn) {
if (EngineCtx.LOGGER.isDebugEnabled()) {
EngineCtx.LOGGER.debug("con query sql:" + sql + " to con:" + conn);
}
conn.setResponseHandler(this);
try {
conn.query(sql);
} catch (UnsupportedEncodingException e) {
doFinished(true);
}
}
private void doFinished(boolean failed) {
jobHandler.finished(dataNode, failed);
ctx.onJobFinished(this);
}
@Override
public void connectionError(Throwable e, BackendConnection conn) {
EngineCtx.LOGGER.info("can't get connection for sql :" + sql);
doFinished(true);
}
@Override
public void errorResponse(byte[] err, BackendConnection conn) {
ErrorPacket errPg = new ErrorPacket();
errPg.read(err);
EngineCtx.LOGGER.info("error response " + new String(errPg.message)
+ " from of sql :" + sql + " at con:" + conn);
conn.release();
doFinished(true);
}
@Override
public void okResponse(byte[] ok, BackendConnection conn) {
// not called for query sql
}
@Override
public void fieldEofResponse(byte[] header, List<byte[]> fields,
byte[] eof, BackendConnection conn) {
jobHandler.onHeader(dataNode, header, fields);
}
@Override
public void rowResponse(byte[] row, BackendConnection conn) {
boolean finsihed = jobHandler.onRowData(dataNode, row);
if (finsihed) {
conn.close("not needed by user proc");
doFinished(false);
}
}
@Override
public void rowEofResponse(byte[] eof, BackendConnection conn) {
conn.release();
doFinished(false);
}
@Override
public void writeQueueAvailable() {
}
@Override
public void connectionClose(BackendConnection conn, String reason) {
doFinished(true);
}
public int getId() {
return id;
}
@Override
public String toString() {
return "SQLJob [ id=" + id + ",dataNode=" + dataNode
+ ",sql=" + sql + ", jobHandler=" + jobHandler + "]";
}
}