package codeine.db.mysql;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
public class MXJController
{
public static int MYSQL_KILL_DELAY = 60000;
private static Logger log = Logger.getLogger(MXJController.class);
public static int MAX_STARTUP_INTERVAL = 80 * 1000;
private final int RESTART_INTERVAL = 2 * 60 * 1000;
public static String MAX_CONNECTIONS = "1000";
public static String QUERY_CACHE_SIZE = "134217728"; //128M
public static String MAX_ALLOWED_PACKET = "4M";
public static String WAIT_TIMEOUT = "31536000";
public static String KEY_BUFFER_SIZE = "67108864"; //64M
public static String TABLE_OPEN_CACHE = "256";
public static String SORT_BUFFER_SIZE = "4194304"; //4M
public static String READ_BUFFER_SIZE = "1048576"; //1M
public static String TMP_TABLE_SIZE = "67108864"; //64M
public static String MAX_HEAP_TABLE_SIZE = "67108864"; //64M
public static String MAX_SEEKS_FOR_KEY = "1000";
public static Boolean LOW_PRIORITY_UPDATES = false;
public static boolean DUMP_QUERIES_LOG = false;
private Map<String, String> m_mpAdditionalOptions = new HashMap<String, String>();
private SpecificMysqldResource m_mysqld = null;
private String m_sBasePath;
private int m_iPort;
private int m_iServerID;
private boolean m_bEnableBinaryLog;
private static long m_lastRestart = 0;
private String binDir;
public MXJController(String basePath, int port, String binDir)
{
m_sBasePath = basePath;
m_iPort = port;
this.binDir = binDir;
}
public synchronized boolean start()
{
if(m_mysqld != null)
{
log.debug("MySQL database already started");
return false;
}
try
{
File baseDir = new File(getBaseDir());
File dataDir = new File(getDataDir());
dataDir.mkdirs();
File outFile = new File(dataDir, "mysql.out");
PrintStream mysqlOut = new PrintStream(new FileOutputStream(outFile));
m_mysqld = new SpecificMysqldResource(baseDir, dataDir, null, false, mysqlOut, binDir);
Map<String, String> options = buildOptions();
if(m_mysqld.isRunning())
{
log.info("Found old MySQL running database - terminating...");
m_mysqld.setKillDelay(1);
m_mysqld.shutdown();
}
log.info("Starting MySQL on port " + m_iPort);
m_mysqld.setKillDelay(MAX_STARTUP_INTERVAL);
m_mysqld.start("MySQL Controller", options);
return true;
}
catch(Exception e)
{
log.error("cannot open database", e);
m_mysqld = null;
return false;
}
}
public void addOptions(Map<String, String> mpAddtional)
{
m_mpAdditionalOptions.putAll(mpAddtional);
}
protected Map<String, String> buildOptions()
{
Map<String,String> options = new HashMap<String,String>();
options.put("port",String.valueOf(m_iPort));
options.put("max_seeks_for_key", MAX_SEEKS_FOR_KEY);
options.put("max_allowed_packet", MAX_ALLOWED_PACKET);
options.put("max_connections", MAX_CONNECTIONS);
options.put("wait_timeout", WAIT_TIMEOUT);
options.put("query_cache_size", QUERY_CACHE_SIZE);
options.put("key_buffer_size", KEY_BUFFER_SIZE);
options.put("table_open_cache", TABLE_OPEN_CACHE);
options.put("sort_buffer_size", SORT_BUFFER_SIZE);
options.put("read_buffer_size", READ_BUFFER_SIZE);
options.put("innodb_buffer_pool_size", String.valueOf(512L * 1024 * 1024));
options.put("tmp_table_size", TMP_TABLE_SIZE);
options.put("max_heap_table_size", MAX_HEAP_TABLE_SIZE);
options.put("skip-name-resolve", "true");
if (LOW_PRIORITY_UPDATES)
{
options.put("low_priority_updates", "true");
}
options.putAll(m_mpAdditionalOptions);
if(isEnableBinaryLog())
{
options.put("log-bin", "mysql-bin");
}
if(getServerID() > 0)
{
options.put("server-id", String.valueOf(getServerID()));
}
// options.put("skip-innodb", null);
options.put("user", MysqlConstants.DB_USER);
if (DUMP_QUERIES_LOG)
{
options.put("log", System.getProperty("mysql.datadir") + File.separator + "queries.log");
}
return options;
}
public synchronized void stopMysqld()
{
if(m_mysqld != null)
{
System.out.println("Shutting down, please wait...");
log.info("Shutting down MySql");
m_mysqld.setKillDelay(MYSQL_KILL_DELAY);
m_mysqld.shutdown();
}
m_mysqld = null;
}
public void stop()
{
try
{
stopMysqld();
System.out.println("done");
}
catch(Throwable t)
{
log.warn("MXJShutdownThread.run() - caught exception", t);
}
}
private synchronized void restartMysqld()
{
stopMysqld();
delay(10);
start();
delay(10);
}
/**
* TO DO - nambar : Auto restart of mysql database causing issues
* it looks like the feeder starts the mysql database when not needed
* Auto restart was originally made since mysqld does not know to recover from NFS issues
*/
public void restartMysqldIfNotRestartedLately()
{
if(m_lastRestart + RESTART_INTERVAL < System.currentTimeMillis())
{
restartMysqld();
m_lastRestart = System.currentTimeMillis();
}
}
private void delay(int sec)
{
try
{
Thread.sleep(sec * 1000);
}
catch (InterruptedException e)
{
log.error("delay() - interrupted", e);
}
}
public boolean isEnableBinaryLog()
{
return m_bEnableBinaryLog;
}
public void setEnableBinaryLog(boolean enableBinaryLog)
{
m_bEnableBinaryLog = enableBinaryLog;
}
public int getServerID()
{
return m_iServerID;
}
public void setServerID(int serverID)
{
m_iServerID = serverID;
}
public int getPort()
{
return m_iPort;
}
public void setPort(int port)
{
m_iPort = port;
}
public String getDataDir()
{
return m_sBasePath + File.separator + "data";
}
public String getBaseDir()
{
return m_sBasePath + File.separator + "mysql";
}
public void cleanReplicationLogs()
{
try
{
Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", "/bin/rm " + getDataDir() + "/*-relay-*"});
}
catch (IOException e)
{
log.warn("unable to cleanup replication logs", e);
}
}
public boolean isRunning()
{
return m_mysqld.isRunning();
}
}