All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.kv.util.migrator.MigrateConfig Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

The newest version!
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.util.migrator;

import static oracle.kv.util.migrator.impl.ConfigBase.raiseInvalidConfigError;
import static oracle.kv.util.migrator.impl.Constants.CONFIG_CURRENT_VERSION;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import oracle.kv.impl.util.CommandParser;
import oracle.kv.util.migrator.MainCommandParser.CommandParserHandler;
import oracle.kv.util.migrator.impl.util.JsonUtils;
import oracle.kv.util.migrator.impl.util.MigratorUtils;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * The migrate configuration include the configuration for data source, data
 * sink and overall configuration for the data migration.
 *
 * It contains below information:
 *  o source: the source type
 *  o sink: the sink type
 *  o abortOnError: indicates if terminate entire migration process if any error
 *  o errorOutput: the directory of the files that logs the entries failed to
 *                 migrate, each data source input corresponds to an error file
 *  o errorFileLimitMB: the maximum number of bytes to write to an error file
 *                      if the given limit has been written to a file, another
 *                      file will be opened, the current file will be renamed
 *                      to xxx.log.
 *  o errorFileCount: the max count of files can be used for each source
 *  o checkpointOutput: the directory of the checkpoint files that logs the
 *                      completion status of each data source
 *  o sourceConfig: the configuration of source
 *  o sinkConfig: the configuration of sink
 */

@JsonIgnoreProperties(ignoreUnknown = true)
public class MigrateConfig {

    public static final String CHECKPOINT_DIR_FLAG = "-checkpoint";
    public static final String ERROR_DIR_FLAG = "-error";
    public static final String ABORT_ON_ERROR_FLAG = "-abort-on-error";

    private static String COMMAND_ARGS =
        CommandParser.optional(ABORT_ON_ERROR_FLAG) + "\n\t" +
        CommandParser.optional(ERROR_DIR_FLAG + " ") + "\n\t" +
        CommandParser.optional(CHECKPOINT_DIR_FLAG + " ") +
        "\n\t" + CommandParser.optional(CommandParser.VERBOSE_FLAG);

    private int version;
    private String source;
    private String sink;
    private boolean abortOnError;
    private String errorOutput;
    private int errorFileLimitMB;
    private int errorFileCount;
    private String checkpointOutput;

    private DataSourceConfig sourceConfig;
    private DataSinkConfig sinkConfig;

    MigrateConfig() {
    }

    public MigrateConfig(String source,
                         String sink,
                         boolean abortOnError) {
        this(source, sink, abortOnError, null, null);
    }

    public MigrateConfig(String source,
                         String sink,
                         boolean abortOnError,
                         String errorOutput,
                         String checkpointOutput) {
        this(source, sink, abortOnError, errorOutput, 0, 0, checkpointOutput,
             CONFIG_CURRENT_VERSION);
    }

    public MigrateConfig(String source,
                         String sink,
                         boolean abortOnError,
                         String errorOutput,
                         int errorFileLimitMB,
                         int errorFileCount,
                         String checkpointOutput,
                         int version) {

        this.version = version;
        this.source = source;
        this.sink = sink;
        this.abortOnError = abortOnError;
        this.errorOutput = errorOutput;
        this.errorFileLimitMB = errorFileLimitMB;
        this.errorFileCount = errorFileCount;
        this.checkpointOutput = checkpointOutput;

        validate(false);
    }

    public static MigrateConfig createFromJson(String json) {
        MigrateConfig config =
            (MigrateConfig)JsonUtils.parseJson(json, MigrateConfig.class, null);
        try {
            config.validate(false);
        } catch (IllegalArgumentException iae) {
            raiseInvalidConfigError(null, iae.getMessage(), config);
        }
        return config;
    }

    public static MigrateConfig parseFromFile(String file) {
        MigrateConfig config =
            (MigrateConfig)JsonUtils.parseJsonFile(file,
                                                   MigrateConfig.class,
                                                   null);
        try {
            config.validate(false);
        } catch (IllegalArgumentException iae) {
            raiseInvalidConfigError(null, iae.getMessage(), config);
        }
        return config;
    }

    public void parseArgs(MainCommandParser parser) {
        /*
         * Supported arguments:
         *  [-checkpoint ]
         *  [-error ]
         *  [-abort-on-error]
         */
        parser.setHandler(new CommandParserHandler() {
            @Override
            public boolean checkArg(String arg) {
                if (arg.equals(CHECKPOINT_DIR_FLAG)) {
                    checkpointOutput = parser.nextArg(arg);
                    return true;
                }
                if (arg.equals(ERROR_DIR_FLAG)) {
                    errorOutput = parser.nextArg(arg);
                    return true;
                }
                if (arg.equals(ABORT_ON_ERROR_FLAG)) {
                    abortOnError = true;
                    return true;
                }
                return false;
            }
            @Override
            public void validate() {
                MigrateConfig.this.validate(true);
            }
            @Override
            public String getUsage() {
                return null;
            }
        });
        parser.parseArgs();
    }

    public void validate(boolean parseArg) {
        if (version > CONFIG_CURRENT_VERSION) {
            throw new IllegalArgumentException("The configuration version " +
                "is at version " + version + " but the supported version by " +
                "the utility is at version " + CONFIG_CURRENT_VERSION +
                ", please upgrade the migrator utility.");
        }
        if (source == null) {
            String param =
                (parseArg ? MainCommandParser.SOURCE_FLAG : "source");
            throw new IllegalArgumentException(
                "missing required parameter: " + param);
        }
        if (sink == null) {
            String param = (parseArg ? MainCommandParser.SINK_FLAG : "sink");
            throw new IllegalArgumentException(
                "missing required parameter: " + param);
        }
        if (checkpointOutput != null) {
            File file = new File(checkpointOutput);
            if (file.exists()) {
                MigratorUtils.checkFileExist(file, true, true, true);
            }
        }
        if (errorOutput != null) {
            File file = new File(errorOutput);
            if (file.exists()) {
                MigratorUtils.checkFileExist(file, true, true, true);
            }
        }
    }

    public static String getCommandArgs() {
        return COMMAND_ARGS;
    }

    public int getVersion() {
        return version;
    }

    public String getSource() {
        return source;
    }

    public String getSink() {
        return sink;
    }

    public boolean getAbortOnError() {
        return abortOnError;
    }

    public String getErrorOutput() {
        return errorOutput;
    }

    public int getErrorFileLimitMB() {
        return errorFileLimitMB;
    }

    public int getErrorFileCount() {
        return errorFileCount;
    }

    public String getCheckpointOutput() {
        return checkpointOutput;
    }

    MigrateConfig setSourceConfig(DataSourceConfig sourceConfig) {
        this.sourceConfig = sourceConfig;
        return this;
    }

    MigrateConfig setSinkConfig(DataSinkConfig sinkConfig) {
        this.sinkConfig = sinkConfig;
        return this;
    }

    @JsonIgnore
    DataSourceConfig getSourceConfig() {
        return sourceConfig;
    }

    @JsonIgnore
    DataSinkConfig getSinkConfig() {
        return sinkConfig;
    }

    @JsonAnyGetter
    Map getConfigs() {
        Map configs = null;
        if (sourceConfig != null) {
            if (configs == null) {
                configs = new HashMap();
            }
            configs.put(sourceConfig.getName(), sourceConfig);
        }
        if (sinkConfig != null) {
            if (configs == null) {
                configs = new HashMap();
            }
            configs.put(sinkConfig.getName(), sinkConfig);
        }
        return configs;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof MigrateConfig)) {
            return false;
        }

        final MigrateConfig cfg1 = (MigrateConfig)obj;

        if (version != cfg1.getVersion() ||
            !Objects.equals(source, cfg1.source) ||
            !Objects.equals(sink, cfg1.sink) ||
            abortOnError != cfg1.abortOnError ||
            !Objects.equals(errorOutput, cfg1.errorOutput) ||
            !Objects.equals(checkpointOutput, cfg1.checkpointOutput)) {
            return false;
        }

        if (sourceConfig != null) {
            if (cfg1.sourceConfig == null ||
                !sourceConfig.equals(cfg1.sourceConfig)) {
                return false;
            }
        } else {
            if (cfg1.sourceConfig != null) {
                return false;
            }
        }

        if (sinkConfig != null) {
            if (cfg1.sinkConfig == null ||
                !sinkConfig.equals(cfg1.sinkConfig)) {
                return false;
            }
        } else {
            if (cfg1.sinkConfig != null) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int code = Integer.hashCode(version);
        if (source != null) {
            code += source.hashCode();
        }
        if (sink != null) {
            code += sink.hashCode();
        }
        code += Boolean.valueOf(abortOnError).hashCode();
        if (errorOutput != null) {
            code += errorOutput.hashCode();
        }
        if (checkpointOutput != null) {
            code += checkpointOutput.hashCode();
        }
        if (sourceConfig != null) {
            code += sourceConfig.hashCode();
        }
        if (sinkConfig != null) {
            code += sinkConfig.hashCode();
        }
        return code;
    }

    public String toJsonString(boolean pretty) {
        return JsonUtils.print(this, pretty);
    }

    @Override
    public String toString() {
        return toJsonString(false);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy