package fm.liu.timo.mysql.handler.xa;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.HashSet;
import org.pmw.tinylog.Logger;
import fm.liu.timo.config.ErrorCode;
import fm.liu.timo.mysql.packet.ErrorPacket;
import fm.liu.timo.net.connection.BackendConnection;
import fm.liu.timo.server.session.XATransactionSession;
import fm.liu.timo.server.session.XATransactionSession.XAState;
/**
* @author liuhuanting
*/
public class XAPrepareHandler extends XAHandler {
public XAPrepareHandler(XATransactionSession session, Collection<BackendConnection> cons) {
super(session, cons);
}
@Override
public void ok(byte[] ok, BackendConnection con) {
results.replace(con.getDatanodeID(), true);
if (decrement()) {
if (failed()) {
error();
return;
}
session.setState(XAState.PREPARED);
log();
session.xaCommit();
}
}
private void log() {
File file = new File(session.getXID().replace("'", ""));
try {
FileOutputStream out = new FileOutputStream(file);
ObjectOutputStream stream = new ObjectOutputStream(out);
stream.writeObject(results);
stream.flush();
out.getFD().sync();
stream.close();
out.close();
session.setPrepareLog(file);
} catch (IOException e) {
e.printStackTrace();
}
}
private void error() {
Collection<BackendConnection> connections = new HashSet<>();
results.entrySet().stream().filter(entry -> entry.getValue())
.forEach(i -> connections.add(cons.get(i)));
XARollbackHandler handler = new XARollbackHandler(session, connections, false);
connections.forEach(con -> con.query("XA ROLLBACK " + session.getXID(), handler));
session.getFront().writeErrMessage(ErrorCode.ER_YES, this.errMsg);
session.getFront().reset();
recycleResources();
}
@Override
public void error(byte[] error, BackendConnection con) {
ErrorPacket err = new ErrorPacket();
err.read(error);
String message = new String(err.message);
Logger.warn("error :{} received from :{} when XA PREPARE", con, message);
this.setFail(err.errno, message);
if (decrement()) {
error();
}
}
}