org.onlab.stc.ScenarioStore.java Source code

Java tutorial

Introduction

Here is the source code for org.onlab.stc.ScenarioStore.java

Source

/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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 org.onlab.stc;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.onlab.stc.Coordinator.Status;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.stc.Coordinator.Status.*;
import static org.onlab.stc.Coordinator.print;

/**
 * Maintains state of scenario execution.
 */
class ScenarioStore {

    private final ProcessFlow processFlow;
    private final File storeFile;
    private final File logDir;

    private final List<StepEvent> events = Lists.newArrayList();
    private final Map<String, Status> statusMap = Maps.newConcurrentMap();

    private long startTime = Long.MAX_VALUE;
    private long endTime = Long.MIN_VALUE;

    /**
     * Creates a new scenario store for the specified process flow.
     *
     * @param processFlow scenario process flow
     * @param logDir      scenario log directory
     * @param name        scenario name
     */
    ScenarioStore(ProcessFlow processFlow, File logDir, String name) {
        this.processFlow = processFlow;
        this.logDir = logDir;
        this.storeFile = new File(logDir, name + ".stc");
        load();
    }

    /**
     * Resets status of all steps to waiting and clears all events.
     */
    void reset() {
        events.clear();
        statusMap.clear();
        processFlow.getVertexes().forEach(step -> statusMap.put(step.name(), WAITING));
        try {
            removeLogs();
            PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
            cfg.clear();
            cfg.save();
            startTime = Long.MAX_VALUE;
            endTime = Long.MIN_VALUE;
        } catch (ConfigurationException e) {
            print("Unable to store file %s", storeFile);
        }

    }

    /**
     * Returns set of all test steps.
     *
     * @return set of steps
     */
    Set<Step> getSteps() {
        return processFlow.getVertexes();
    }

    /**
     * Returns a chronological list of step or group records.
     *
     * @return list of events
     */
    synchronized List<StepEvent> getEvents() {
        return ImmutableList.copyOf(events);
    }

    /**
     * Returns the status record of the specified test step.
     *
     * @param step test step or group
     * @return step status record
     */
    Status getStatus(Step step) {
        return checkNotNull(statusMap.get(step.name()), "Step %s not found", step.name());
    }

    /**
     * Marks the specified test step as being in progress.
     *
     * @param step test step or group
     */
    synchronized void markStarted(Step step) {
        add(new StepEvent(step.name(), IN_PROGRESS, step.command()));
        save();
    }

    /**
     * Marks the specified test step as being complete.
     *
     * @param step   test step or group
     * @param status new step status
     */
    synchronized void markComplete(Step step, Status status) {
        add(new StepEvent(step.name(), status, null));
        save();
    }

    /**
     * Returns true if all steps in the store have been marked as completed
     * regardless of the completion status.
     *
     * @return true if all steps completed one way or another
     */
    synchronized boolean isComplete() {
        return !statusMap.values().stream().anyMatch(s -> s == WAITING || s == IN_PROGRESS);
    }

    /**
     * Indicates whether there are any failures.
     *
     * @return true if there are failed steps
     */
    boolean hasFailures() {
        for (Status status : statusMap.values()) {
            if (status == FAILED) {
                return true;
            }
        }
        return false;
    }

    /**
     * Registers a new step record.
     *
     * @param event step event
     */
    private synchronized void add(StepEvent event) {
        events.add(event);
        statusMap.put(event.name(), event.status());
        startTime = Math.min(startTime, event.time());
        endTime = Math.max(endTime, event.time());
    }

    /**
     * Loads the states from disk.
     */
    private void load() {
        try {
            PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
            cfg.getKeys().forEachRemaining(prop -> add(StepEvent.fromString(cfg.getString(prop))));
            cfg.save();
        } catch (ConfigurationException e) {
            print("Unable to load file %s", storeFile);
        }
    }

    /**
     * Saves the states to disk.
     */
    private void save() {
        try {
            PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
            events.forEach(event -> cfg.setProperty("T" + event.time(), event.toString()));
            cfg.save();
        } catch (ConfigurationException e) {
            print("Unable to store file %s", storeFile);
        }
    }

    /**
     * Removes all scenario log files.
     */
    private void removeLogs() {
        File[] logFiles = logDir.listFiles();
        if (logFiles != null && logFiles.length > 0) {
            for (File file : logFiles) {
                if (!file.delete()) {
                    print("Unable to delete log file %s", file);
                }
            }
        }
    }

    /**
     * Returns the scenario run start time.
     *
     * @return start time in mills since start of epoch
     */
    public long startTime() {
        return startTime;
    }

    /**
     * Returns the scenario run end time or current time if the scenario
     * is still running.
     *
     * @return end time (or current time) in mills since start of epoch
     */
    public long endTime() {
        return endTime > 0 ? endTime : System.currentTimeMillis();
    }
}