com.tesora.dve.mysqlapi.repl.MyReplErrorAdjudicator.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.mysqlapi.repl.MyReplErrorAdjudicator.java

Source

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.sql.SQLException;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

public class MyReplErrorAdjudicator {
    Logger logger = Logger.getLogger(MyReplErrorAdjudicator.class);

    enum ReplSkipErrorOption {
        UNKNOWN("UNKNOWN"), ALL("ALL"), OFF("OFF");

        private final String option;

        private ReplSkipErrorOption(String option) {
            this.option = option;
        }

        public String asString() {
            return option;
        }

        static public ReplSkipErrorOption fromString(String option) {
            for (ReplSkipErrorOption rseo : values()) {
                if (StringUtils.equalsIgnoreCase(rseo.asString(), option)) {
                    return rseo;
                }
            }
            return UNKNOWN;
        }
    }

    boolean skipAll = false;
    boolean off = true;
    TreeSet<Integer> skipErrorList = new TreeSet<Integer>();

    public MyReplErrorAdjudicator() {
        skipAll = false;
        off = true;
        skipErrorList.clear();
    }

    public MyReplErrorAdjudicator(Set<String> skipErrors) {
        parseOptions(skipErrors);

        if (!isOff()) {
            if (skipAll()) {
                logger.warn("Replication Slave has been configured with option '" + ReplSkipErrorOption.ALL
                        + "'.  Any errors encountered during processing will be ignored and replication will continue.");
            } else {
                logger.warn("Replication Slave has been configured to ignore the following SQL error code(s): "
                        + buildErrorCodeString());

            }
        }
    }

    public boolean skipAll() {
        return skipAll;
    }

    public boolean isOff() {
        return off;
    }

    public boolean validateErrorAndStop(int masterErrorCode) {
        return validateErrorAndStop(masterErrorCode, 0);
    }

    public boolean validateErrorAndStop(int masterErrorCode, Throwable slaveException) {
        if (skipAll()) {
            return false;
        }
        Throwable t = getRootException(slaveException);
        if (t instanceof SQLException) {
            return validateErrorAndStop(masterErrorCode, ((SQLException) t).getErrorCode());
        } else {
            return true;
        }
    }

    public boolean validateErrorAndStop(int masterErrorCode, int slaveErrorCode) {
        if (skipAll() || (masterErrorCode == slaveErrorCode))
            return false;

        if (isOff() && (masterErrorCode != slaveErrorCode))
            return true;

        return !skipErrorList.contains(masterErrorCode) || !skipErrorList.contains(slaveErrorCode);
    }

    // for testing
    TreeSet<Integer> getSkipErrorList() {
        return skipErrorList;
    }

    private void parseOptions(Set<String> skipErrors) {
        if (skipErrors == null) {
            return;
        }

        skipErrorList.clear();
        skipErrorList.add(0);
        for (String errorCode : skipErrors) {
            try {
                off = false;
                skipAll = false;
                skipErrorList.add(Integer.parseInt(errorCode));
            } catch (NumberFormatException e) {
                // could be all or off
                switch (ReplSkipErrorOption.fromString(errorCode)) {
                case ALL:
                    off = false;
                    skipAll = true;
                    skipErrorList.clear();
                    return;

                case OFF:
                default: // reset to off with invalid option
                    off = true;
                    skipAll = false;
                    skipErrorList.clear();
                    return;

                }
            }
        }
    }

    private String buildErrorCodeString() {
        StringBuilder ret = new StringBuilder();

        boolean first = true;
        for (Integer code : skipErrorList) {
            if (!first) {
                ret.append(", ");
            }
            ret.append(code);
            first = false;
        }

        return ret.toString();
    }

    private Throwable getRootException(Throwable exception) {
        Throwable root, lastEx = exception;
        for (root = exception; (root = root.getCause()) != null;) {
            lastEx = root;
        }
        return lastEx;
    }

}