package com.tesora.dve.mysqlapi.repl; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.NoSuchElementException; import java.util.Set; import java.util.StringTokenizer; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.log4j.Logger; import com.tesora.dve.common.PEFileUtils; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.externalservice.ExternalServiceConfig; public class MyReplicationSlaveConfig implements ExternalServiceConfig { Logger logger = Logger.getLogger(MyReplicationSlaveConfig.class); private static String CONFIG_DELIMETER=","; private static String REPL_IGNORE_TABLE_KEY = "replicate-ignore-table"; private static String REPL_INCLUDE_DB_KEY = "replicate-include-db"; private static String REPL_SLAVE_SKIP_ERRORS = "slave-skip-errors"; public static String REPL_SLAVE_MASTER_RETRY_CONNECT = "master-retry-connect"; public static String REPL_SLAVE_MASTER_RETRY_COUNT = "master-retry-count"; public static String REPL_SLAVE_SLAVE_NET_TIMEOUT = "slave-net-timeout"; private final static long DEFAULT_MASTER_CONNECT_RETRY_INTERVAL = 60; private final static long DEFAULT_MAX_MASTER_RETRY_ATTEMPTS = 86400; private final static long DEFAULT_SLAVE_RETRY_TIME_LIMIT = 3600; private PropertiesConfiguration configProps; private String masterHost; private int masterPort; private int slaveServerID; private String masterUserid; private String masterPwd; private String initialBinlogName; private long initialBinlogPosition; private Set<String> includeDBList=null; private String configFile=null; private Set<String> ignoreTableList=null; private MyReplErrorAdjudicator adjudicator = null; private long masterConnectRetry=DEFAULT_MASTER_CONNECT_RETRY_INTERVAL; // in seconds private long masterRetryCount=DEFAULT_MAX_MASTER_RETRY_ATTEMPTS; private long slaveNetTimeout=DEFAULT_SLAVE_RETRY_TIME_LIMIT; // in seconds public MyReplicationSlaveConfig() {}; public MyReplicationSlaveConfig(String masterHost, int masterPort, int slaveServerID, String masterUserid, String masterPwd, String initialBinlogName, long initialBinlogPosition, String configFile) throws PEException { this.masterHost = masterHost; this.masterPort = masterPort; this.slaveServerID = slaveServerID; this.masterUserid = masterUserid; this.masterPwd = masterPwd; this.initialBinlogName = initialBinlogName; this.initialBinlogPosition = initialBinlogPosition; this.configFile = configFile; loadConfigFile(); } public String getMasterHost() { return masterHost; } public void setMasterHost(String masterHost) { this.masterHost = masterHost; } public int getMasterPort() { return masterPort; } public void setMasterPort(int masterPort) { this.masterPort = masterPort; } public String getInitialBinlogName() { return initialBinlogName; } public void setInitialBinlogName(String initialBinlogName) { this.initialBinlogName = initialBinlogName; } public long getInitialBinlogPosition() { return initialBinlogPosition; } public void setInitialBinlogPosition(long initialBinlogPosition) { this.initialBinlogPosition = initialBinlogPosition; } public int getSlaveServerID() { return slaveServerID; } public void setSlaveServerID(int slaveServerID) { this.slaveServerID = slaveServerID; } public String getMasterUserid() { return masterUserid; } public void setMasterUserid(String masterUserid) { this.masterUserid = masterUserid; } public String getMasterPwd() { return masterPwd; } public void setMasterPwd(String masterPwd) { this.masterPwd = masterPwd; } public MyBinLogPosition getInitialMyBinLogPosition() { return new MyBinLogPosition(masterHost, initialBinlogName, initialBinlogPosition); } public Set<String> getIgnoreTableList() { if ( configFile == null ) return Collections.emptySet(); if ( ignoreTableList != null ) return ignoreTableList; ignoreTableList = new HashSet<String>(Arrays.asList(configProps.getStringArray(REPL_IGNORE_TABLE_KEY))); return ignoreTableList; } public Set<String> getIncludeDBList() { if ( configFile == null ) return Collections.emptySet(); if ( includeDBList != null) return includeDBList; includeDBList = new HashSet<String>(Arrays.asList(configProps.getStringArray(REPL_INCLUDE_DB_KEY))); return includeDBList; } public MyReplErrorAdjudicator getReplErrorAdjudicator() { if (adjudicator == null) { adjudicator = new MyReplErrorAdjudicator(); } return adjudicator; } public long getMasterConnectRetry() { return masterConnectRetry; } public long getMasterRetryCount() { return masterRetryCount; } public long getSlaveNetTimeout() { return slaveNetTimeout; } private void loadConfigFile() throws PEException { if ( configFile != null && configProps == null ) { configProps = PEFileUtils.loadPropertiesConfigFromClasspath(getClass(), configFile); if (adjudicator == null) { adjudicator = new MyReplErrorAdjudicator(new LinkedHashSet<String>(Arrays.asList(configProps.getStringArray(REPL_SLAVE_SKIP_ERRORS)))); } masterConnectRetry = configProps.getLong(REPL_SLAVE_MASTER_RETRY_CONNECT, DEFAULT_MASTER_CONNECT_RETRY_INTERVAL); masterRetryCount = configProps.getLong(REPL_SLAVE_MASTER_RETRY_COUNT, DEFAULT_MAX_MASTER_RETRY_ATTEMPTS); slaveNetTimeout = configProps.getLong(REPL_SLAVE_SLAVE_NET_TIMEOUT, DEFAULT_SLAVE_RETRY_TIME_LIMIT); } } @Override public void unmarshall(String config) throws PEException { StringTokenizer st = new StringTokenizer(config, CONFIG_DELIMETER); String currentToken=null, currentValue=null; try { currentToken = "Host"; masterHost = st.nextToken().trim(); currentToken = "Port"; currentValue = st.nextToken().trim(); masterPort = Integer.valueOf(currentValue); currentToken = "Userid"; masterUserid = st.nextToken().trim(); currentToken = "Password"; masterPwd = st.nextToken().trim(); currentToken = "Slave ID"; currentValue = st.nextToken().trim(); slaveServerID = Integer.valueOf(currentValue); currentToken = "Initial Binlog Filename"; initialBinlogName = st.nextToken().trim(); currentToken = "Initial Binlog Position"; currentValue = st.nextToken().trim(); initialBinlogPosition = Integer.valueOf(currentValue); } catch (NoSuchElementException nse) { throw new PEException( "Configuration string for MyReplicationSlaveService doesn't contain enough values",nse); } catch (NumberFormatException nfe) { throw new PEException("Configuration value for " + currentToken + " must be numeric - received '" + currentValue + "'", nfe); } // if the next token exists it is the configFile if ( st.hasMoreTokens() ) { configFile = st.nextToken().trim(); loadConfigFile(); } } @Override public String marshall() { StringBuilder configOut = new StringBuilder().append(masterHost).append(CONFIG_DELIMETER) .append(masterPort).append(CONFIG_DELIMETER) .append(masterUserid).append(CONFIG_DELIMETER) .append(masterPwd).append(CONFIG_DELIMETER) .append(slaveServerID).append(CONFIG_DELIMETER) .append(initialBinlogName).append(CONFIG_DELIMETER) .append(initialBinlogPosition); if ( configFile != null ) configOut.append(CONFIG_DELIMETER).append(configFile); return configOut.toString(); } }