com.cinchapi.concourse.server.upgrade.UpgradeTasks.java Source code

Java tutorial

Introduction

Here is the source code for com.cinchapi.concourse.server.upgrade.UpgradeTasks.java

Source

/*
 * Copyright (c) 2013-2016 Cinchapi Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.cinchapi.concourse.server.upgrade;

import static com.cinchapi.concourse.server.upgrade.UpgradeTask.getCurrentSystemVersion;

import java.util.Set;

import org.reflections.Reflections;

import com.cinchapi.concourse.server.GlobalState;
import com.cinchapi.concourse.server.io.FileSystem;
import com.cinchapi.concourse.server.upgrade.task.Upgrade2;
import com.cinchapi.concourse.util.Logger;
import com.cinchapi.concourse.util.Reflection;
import com.google.common.collect.Sets;

/**
 * A collection of methods that are responsible for bootstrapping and managing
 * the upgrade process.
 * 
 * @author Jeff Nelson
 */
public final class UpgradeTasks {

    static {
        Reflections.log = null; // turn off logging
    }

    /**
     * The package that contains all upgrade tasks.
     */
    private static final String[] pkgs = { "com.cinchapi.concourse.server.upgrade.task" };

    /**
     * Run all the upgrade tasks that are greater than the
     * {@link UpgradeTask#getCurrentSystemVersion() current system version}.
     */
    public static void runLatest() {
        int currentSystemVersion = 0;
        try {
            currentSystemVersion = bootstrap();
        } catch (Exception e) {
            String user = System.getProperty("user.name");
            Logger.error("An error occurred while trying to bootstrap the upgrade framework, "
                    + "which usually indicates that Concourse Server is configured to store "
                    + "data in one or more locations where the current user ({}) does not "
                    + "have write permission. Please check the prefs file at {} to make sure "
                    + "you have properly configured the buffer_directory and database_directory. "
                    + "If those properties are properly configured, please give \"{}\" write "
                    + "permission to those directories.", user, GlobalState.getPrefsFilePath(), user);
            throw e;
        }

        // Find the new upgrade tasks
        Set<UpgradeTask> tasks = Sets.newTreeSet();
        for (String pkg : pkgs) {
            Reflections reflections = new Reflections(pkg);
            Set<Class<? extends UpgradeTask>> classes = reflections.getSubTypesOf(UpgradeTask.class);
            classes.addAll(reflections.getSubTypesOf(SmartUpgradeTask.class));
            for (Class<? extends UpgradeTask> clazz : classes) {
                UpgradeTask task = Reflection.newInstance(clazz);
                if (task.version() > currentSystemVersion) {
                    tasks.add(task);
                }
            }
        }

        // Run the new upgrade tasks
        for (UpgradeTask task : tasks) {
            try {
                task.run();
            } catch (Exception e) {
                if (task instanceof Upgrade2) {
                    // CON-137: Even if Upgrade2 fails and we can't migrate
                    // data, still set the system version so we aren't
                    // blocked on this task in the future.
                    UpgradeTask.setCurrentSystemVersion(task.version());
                    Logger.info("Due to a bug in a previous " + "release, the system version has "
                            + "been force upgraded " + "to {}", task.version());
                } else {
                    throw e; // fail fast because we assume subsequent tasks
                             // depend on the one that failed
                }
            }
        }
    }

    /**
     * Bootstrap a new Concourse Server installation with the latest system
     * version, if necessary.
     * <p>
     * If this method detects that the Concourse Server installation is "fresh"
     * it will assign the latest system version without running any upgrade
     * tasks.
     * </p>
     * 
     * @return whatever the latest system version is after the affects, if any,
     *         of this method take affect; if the system is not fresh, calling
     *         this method has the same affect as calling
     *         {@link UpgradeTask#getCurrentSystemVersion()}.
     */
    private static int bootstrap() {
        String seal = ".douge";
        int currentSystemVersion = getCurrentSystemVersion();
        if (FileSystem.hasFile(seal)) {
            UpgradeTask theTask = null;
            // Go through the upgrade tasks and find the one with the largest
            // schema version.
            for (String pkg : pkgs) {
                Reflections reflections = new Reflections(pkg);
                Set<Class<? extends UpgradeTask>> classes = reflections.getSubTypesOf(UpgradeTask.class);
                classes.addAll(reflections.getSubTypesOf(SmartUpgradeTask.class));
                for (Class<? extends UpgradeTask> clazz : classes) {
                    UpgradeTask task = Reflection.newInstance(clazz);
                    if (theTask == null || task.version() > theTask.version()) {
                        theTask = task;
                    }
                }
            }
            UpgradeTask.setCurrentSystemVersion(theTask.version());
            Logger.info("The upgrade framework has been initialized " + "with a system version of {}",
                    theTask.version());
            FileSystem.deleteFile(seal);
            return theTask.version();

        }
        return currentSystemVersion;
    }

}