package io.mycat.sqlengine; import io.mycat.net.BufferArray; import io.mycat.net.NetSystem; import io.mycat.server.MySQLFrontConnection; import io.mycat.server.NonBlockingSession; import io.mycat.server.packet.EOFPacket; import io.mycat.server.packet.ResultSetHeaderPacket; import io.mycat.server.packet.RowDataPacket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; public class EngineCtx { public static final Logger LOGGER = LoggerFactory .getLogger(EngineCtx.class); private final BatchSQLJob bachJob; private AtomicInteger jobId = new AtomicInteger(0); AtomicInteger packetId = new AtomicInteger(0); private final NonBlockingSession session; private AtomicBoolean finished = new AtomicBoolean(false); private AllJobFinishedListener allJobFinishedListener; private AtomicBoolean headerWrited = new AtomicBoolean(); private final ReentrantLock writeLock = new ReentrantLock(); public EngineCtx(NonBlockingSession session) { this.bachJob = new BatchSQLJob(); this.session = session; } public byte incPackageId() { return (byte) packetId.incrementAndGet(); } public void executeNativeSQLSequnceJob(String[] dataNodes, String sql, SQLJobHandler jobHandler) { for (String dataNode : dataNodes) { SQLJob job = new SQLJob(jobId.incrementAndGet(), sql, dataNode, jobHandler, this); bachJob.addJob(job, false); } } public ReentrantLock getWriteLock() { return writeLock; } public void setAllJobFinishedListener( AllJobFinishedListener allJobFinishedListener) { this.allJobFinishedListener = allJobFinishedListener; } public void executeNativeSQLParallJob(String[] dataNodes, String sql, SQLJobHandler jobHandler) { for (String dataNode : dataNodes) { SQLJob job = new SQLJob(jobId.incrementAndGet(), sql, dataNode, jobHandler, this); bachJob.addJob(job, true); } } /** * set no more jobs created */ public void endJobInput() { bachJob.setNoMoreJobInput(true); } public void writeHeader(List<byte[]> afields, List<byte[]> bfields) { if (headerWrited.compareAndSet(false, true)) { try { writeLock.lock(); // write new header ResultSetHeaderPacket headerPkg = new ResultSetHeaderPacket(); headerPkg.fieldCount = afields.size() + bfields.size() - 1; headerPkg.packetId = incPackageId(); LOGGER.debug("packge id " + headerPkg.packetId); MySQLFrontConnection sc = session.getSource(); BufferArray bufferArray = NetSystem.getInstance() .getBufferPool().allocateArray(); headerPkg.write(bufferArray); // wirte a fields for (byte[] field : afields) { field[3] = incPackageId(); bufferArray.write(field); } // write b field for (int i = 1; i < bfields.size(); i++) { byte[] bfield = bfields.get(i); bfield[3] = incPackageId(); bufferArray.write(bfield); } // write field eof EOFPacket eofPckg = new EOFPacket(); eofPckg.packetId = incPackageId(); eofPckg.write(bufferArray); sc.write(bufferArray); // LOGGER.info("header outputed ,packgId:" + eofPckg.packetId); } finally { writeLock.unlock(); } } } public void writeHeader(List<byte[]> afields) { if (headerWrited.compareAndSet(false, true)) { try { writeLock.lock(); // write new header ResultSetHeaderPacket headerPkg = new ResultSetHeaderPacket(); headerPkg.fieldCount = afields.size();// -1; headerPkg.packetId = incPackageId(); LOGGER.debug("packge id " + headerPkg.packetId); MySQLFrontConnection sc = session.getSource(); BufferArray bufferArray = NetSystem.getInstance() .getBufferPool().allocateArray(); // wirte a fields for (byte[] field : afields) { field[3] = incPackageId(); bufferArray.write(field); } // write field eof EOFPacket eofPckg = new EOFPacket(); eofPckg.packetId = incPackageId(); eofPckg.write(bufferArray); sc.write(bufferArray); // LOGGER.info("header outputed ,packgId:" + eofPckg.packetId); } finally { writeLock.unlock(); } } } public void writeRow(RowDataPacket rowDataPkg) { MySQLFrontConnection sc = session.getSource(); try { writeLock.lock(); rowDataPkg.packetId = incPackageId(); // 输出完整的 记录到客户端 rowDataPkg.write(sc); // LOGGER.info("write row ,packgId:" + rowDataPkg.packetId); } finally { writeLock.unlock(); } } public void writeEof() { MySQLFrontConnection sc = session.getSource(); EOFPacket eofPckg = new EOFPacket(); eofPckg.packetId = incPackageId(); eofPckg.write(sc); LOGGER.info("write eof ,packgId:" + eofPckg.packetId); } public NonBlockingSession getSession() { return session; } public void onJobFinished(SQLJob sqlJob) { boolean allFinished = bachJob.jobFinished(sqlJob); if (allFinished && finished.compareAndSet(false, true)) { LOGGER.info("all job finished for front connection: " + session.getSource()); allJobFinishedListener.onAllJobFinished(this); } } }