gobblin.runtime.spec_catalog.FlowCatalog.java Source code

Java tutorial

Introduction

Here is the source code for gobblin.runtime.spec_catalog.FlowCatalog.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 gobblin.runtime.spec_catalog;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Optional;
import com.google.common.util.concurrent.AbstractIdleService;
import com.google.common.base.Preconditions;
import com.typesafe.config.Config;

import gobblin.configuration.ConfigurationKeys;
import gobblin.instrumented.Instrumented;
import gobblin.runtime.api.GobblinInstanceEnvironment;
import gobblin.annotation.Alpha;
import gobblin.metrics.MetricContext;
import gobblin.metrics.Tag;
import gobblin.runtime.api.FlowSpec;
import gobblin.runtime.api.MutableSpecCatalog;
import gobblin.runtime.api.Spec;
import gobblin.runtime.api.SpecCatalog;
import gobblin.runtime.api.SpecCatalogListener;
import gobblin.runtime.api.SpecNotFoundException;
import gobblin.runtime.api.SpecSerDe;
import gobblin.runtime.api.SpecStore;
import gobblin.runtime.spec_store.FSSpecStore;
import gobblin.util.ClassAliasResolver;

@Alpha
public class FlowCatalog extends AbstractIdleService implements SpecCatalog, MutableSpecCatalog, SpecSerDe {

    public static final String DEFAULT_FLOWSPEC_STORE_CLASS = FSSpecStore.class.getCanonicalName();

    protected final SpecCatalogListenersList listeners;
    protected final Logger log;
    protected final MetricContext metricContext;
    protected final FlowCatalog.StandardMetrics metrics;
    protected final SpecStore specStore;

    private final ClassAliasResolver<SpecStore> aliasResolver;

    public FlowCatalog(Config config) {
        this(config, Optional.<Logger>absent());
    }

    public FlowCatalog(Config config, Optional<Logger> log) {
        this(config, log, Optional.<MetricContext>absent(), true);
    }

    public FlowCatalog(Config config, GobblinInstanceEnvironment env) {
        this(config, Optional.of(env.getLog()), Optional.of(env.getMetricContext()),
                env.isInstrumentationEnabled());
    }

    public FlowCatalog(Config config, Optional<Logger> log, Optional<MetricContext> parentMetricContext,
            boolean instrumentationEnabled) {
        this.log = log.isPresent() ? log.get() : LoggerFactory.getLogger(getClass());
        this.listeners = new SpecCatalogListenersList(log);
        if (instrumentationEnabled) {
            MetricContext realParentCtx = parentMetricContext
                    .or(Instrumented.getMetricContext(new gobblin.configuration.State(), getClass()));
            this.metricContext = realParentCtx.childBuilder(FlowCatalog.class.getSimpleName()).build();
            this.metrics = new StandardMetrics(this);
        } else {
            this.metricContext = null;
            this.metrics = null;
        }

        this.aliasResolver = new ClassAliasResolver<>(SpecStore.class);
        try {
            Config newConfig = config;
            if (config.hasPath(ConfigurationKeys.FLOWSPEC_STORE_DIR_KEY)) {
                newConfig = config.withValue(ConfigurationKeys.SPECSTORE_FS_DIR_KEY,
                        config.getValue(ConfigurationKeys.FLOWSPEC_STORE_DIR_KEY));
            }
            String specStoreClassName = DEFAULT_FLOWSPEC_STORE_CLASS;
            if (config.hasPath(ConfigurationKeys.FLOWSPEC_STORE_CLASS_KEY)) {
                specStoreClassName = config.getString(ConfigurationKeys.FLOWSPEC_STORE_CLASS_KEY);
            }
            this.log.info("Using audit sink class name/alias " + specStoreClassName);
            this.specStore = (SpecStore) ConstructorUtils.invokeConstructor(
                    Class.forName(this.aliasResolver.resolve(specStoreClassName)), newConfig, this);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException
                | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /***************************************************
     /* Catalog init and shutdown handlers             *
     /**************************************************/

    @Override
    protected void startUp() throws Exception {
        notifyAllListeners();
    }

    @Override
    protected void shutDown() throws Exception {
        this.listeners.close();
    }

    /***************************************************
     /* Catalog listeners                              *
     /**************************************************/

    protected void notifyAllListeners() {
        for (Spec spec : getSpecs()) {
            this.listeners.onAddSpec(spec);
        }
    }

    @Override
    public void addListener(SpecCatalogListener specListener) {
        Preconditions.checkNotNull(specListener);
        this.listeners.addListener(specListener);

        if (state() == State.RUNNING) {
            for (Spec spec : getSpecs()) {
                SpecCatalogListener.AddSpecCallback addJobCallback = new SpecCatalogListener.AddSpecCallback(spec);
                this.listeners.callbackOneListener(addJobCallback, specListener);
            }
        }
    }

    @Override
    public void removeListener(SpecCatalogListener specCatalogListener) {
        this.listeners.removeListener(specCatalogListener);
    }

    @Override
    public void registerWeakSpecCatalogListener(SpecCatalogListener specCatalogListener) {
        this.listeners.registerWeakSpecCatalogListener(specCatalogListener);
    }

    /***************************************************
     /* Catalog metrics                                *
     /**************************************************/

    @Nonnull
    @Override
    public MetricContext getMetricContext() {
        return this.metricContext;
    }

    @Override
    public boolean isInstrumentationEnabled() {
        return null != this.metricContext;
    }

    @Override
    public List<Tag<?>> generateTags(gobblin.configuration.State state) {
        return Collections.emptyList();
    }

    @Override
    public void switchMetricContext(List<Tag<?>> tags) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void switchMetricContext(MetricContext context) {
        throw new UnsupportedOperationException();
    }

    @Override
    public StandardMetrics getMetrics() {
        return this.metrics;
    }

    /**************************************************
    /* Catalog core functionality                     *
    /**************************************************/

    @Override
    public Collection<Spec> getSpecs() {
        try {
            return specStore.getSpecs();
        } catch (IOException e) {
            throw new RuntimeException("Cannot retrieve Specs from Spec store", e);
        }
    }

    @Override
    public Spec getSpec(URI uri) throws SpecNotFoundException {
        try {
            return specStore.getSpec(uri);
        } catch (IOException e) {
            throw new RuntimeException("Cannot retrieve Spec from Spec store for URI: " + uri, e);
        }
    }

    @Override
    public void put(Spec spec) {
        try {
            Preconditions.checkState(state() == State.RUNNING,
                    String.format("%s is not running.", this.getClass().getName()));
            Preconditions.checkNotNull(spec);

            log.info(String.format("Adding FlowSpec with URI: %s and Config: %s", spec.getUri(),
                    ((FlowSpec) spec).getConfigAsProperties()));
            if (specStore.exists(spec.getUri())) {
                specStore.updateSpec(spec);
                this.listeners.onUpdateSpec(spec);
            } else {
                specStore.addSpec(spec);
                this.listeners.onAddSpec(spec);
            }

        } catch (IOException | SpecNotFoundException e) {
            throw new RuntimeException("Cannot add Spec to Spec store: " + spec, e);
        }
    }

    @Override
    public void remove(URI uri) {
        try {
            Preconditions.checkState(state() == State.RUNNING,
                    String.format("%s is not running.", this.getClass().getName()));
            Preconditions.checkNotNull(uri);

            log.info(String.format("Removing FlowSpec with URI: %s", uri));
            Spec spec = specStore.getSpec(uri);
            this.listeners.onDeleteSpec(spec.getUri(), spec.getVersion());
            specStore.deleteSpec(uri);

        } catch (IOException | SpecNotFoundException e) {
            throw new RuntimeException("Cannot delete Spec from Spec store for URI: " + uri, e);
        }
    }

    @Override
    public byte[] serialize(Spec spec) {
        return SerializationUtils.serialize(spec);
    }

    @Override
    public Spec deserialize(byte[] spec) {
        return SerializationUtils.deserialize(spec);
    }
}