package org.apache.fullmatix.mysql; import java.io.OutputStreamWriter; import org.apache.helix.HelixConstants.ChangeType; import org.apache.helix.HelixAdmin; import org.apache.helix.HelixManager; import org.apache.helix.HelixManagerFactory; import org.apache.helix.InstanceType; import org.apache.helix.manager.zk.ZKHelixAdmin; import org.apache.helix.model.InstanceConfig; import org.apache.helix.participant.CustomCodeInvoker; import org.apache.helix.participant.HelixCustomCodeRunner; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; /** * @author kgopalak */ public class MySQLAgent { private static final Logger LOG = Logger.getLogger(MySQLAgent.class); private String _zkAddress; private String _clusterName; private InstanceConfig _instanceConfig; private String _instanceName; private Context _context; static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { LOG.error("Unable to load mysql jdbc driver", e); } } public MySQLAgent(String zkAddress, String clusterName, InstanceConfig instanceConfig) throws Exception { _zkAddress = zkAddress; _clusterName = clusterName; _instanceConfig = instanceConfig; _instanceName = instanceConfig.getInstanceName(); _context = new Context(); } public void start() throws Exception { MySQLAdmin mysqlAdmin = new MySQLAdmin(_instanceConfig); Replicator replicator = new Replicator(_instanceConfig); HelixManager helixManager = HelixManagerFactory.getZKHelixManager(_clusterName, _instanceName, InstanceType.PARTICIPANT, _zkAddress); _context.setHelixManager(helixManager); _context.setMysqlAdmin(mysqlAdmin); _context.setReplicator(replicator); MasterSlaveTransitionHandlerFactory factory = new MasterSlaveTransitionHandlerFactory(_context); helixManager.getStateMachineEngine().registerStateModelFactory("MasterSlave", factory); DatabaseTransitionHandlerFactory databaseTransitionHandlerFactory = new DatabaseTransitionHandlerFactory(_context); helixManager.getStateMachineEngine().registerStateModelFactory("OnlineOffline", databaseTransitionHandlerFactory, "DatabaseTransitionHandlerFactory"); TableTransitionHandlerFactory tableTransitionHandlerFactory = new TableTransitionHandlerFactory(_context); helixManager.getStateMachineEngine().registerStateModelFactory("OnlineOffline", tableTransitionHandlerFactory, "TableTransitionHandlerFactory"); helixManager.connect(); ReplicationManager observer = new ReplicationManager(_context); helixManager.addExternalViewChangeListener(observer); MasterSlaveRebalancer rebalancer = new MasterSlaveRebalancer(_context); HelixCustomCodeRunner helixCustomCodeRunner = new HelixCustomCodeRunner(helixManager, _zkAddress).invoke(rebalancer) .on(ChangeType.CONFIG, ChangeType.LIVE_INSTANCE) .usingLeaderStandbyModel("MasterSlave_rebalancer"); helixCustomCodeRunner.start(); monitor(); } private void monitor() throws Exception { MySQLAdmin mysqlAdmin = _context.getMysqlAdmin(); HelixAdmin helixAdmin = _context.getHelixManager().getClusterManagmentTool(); boolean isEnabled = _instanceConfig.getInstanceEnabled(); int failedPingCount = 0; while (true) { Thread.sleep(1000); if (!mysqlAdmin.ping()) { LOG.info("Mysql connection check failed"); failedPingCount = failedPingCount + 1; } else { failedPingCount = 0; if (!isEnabled) { LOG.info("Mysql connection check passed.Enabling the instance"); helixAdmin.enableInstance(_clusterName, _instanceName, true); isEnabled = true; } } if (failedPingCount == 30) { LOG.info("Mysql connection check failed 30 times, disabling the instance"); helixAdmin.enableInstance(_clusterName, _instanceName, false); isEnabled = false; } } } public void stop() { LOG.info("Stopping the MySQL agent. Disconnecting from the cluster"); _context.getHelixManager().disconnect(); } public static void main(String[] args) throws Exception { ConsoleAppender ca = new ConsoleAppender(); ca.setThreshold(Level.INFO); ca.setWriter(new OutputStreamWriter(System.out)); ca.setLayout(new PatternLayout("%-4r [%t] %-5p %c %x - %m%n")); Logger.getRootLogger().addAppender(ca); String clusterName = "mysql-cluster-test"; String instanceName = "kgopalak-ld.linkedin.biz_5555"; String zkAddress = "localhost:2181"; // TODO:stand alone way to start the agent HelixAdmin admin = new ZKHelixAdmin(zkAddress); InstanceConfig instanceConfig = admin.getInstanceConfig(clusterName, instanceName); MySQLAgent agent = new MySQLAgent(zkAddress, clusterName, instanceConfig); agent.start(); Thread.currentThread().join(); } }