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

com.thinkaurelius.titan.hadoop.FaunusPathElement Maven / Gradle / Ivy

package com.thinkaurelius.titan.hadoop;

import static com.thinkaurelius.titan.hadoop.config.TitanHadoopConfiguration.PIPELINE_TRACK_PATHS;

import com.google.common.base.Preconditions;
import com.thinkaurelius.titan.diskstorage.configuration.Configuration;
import com.thinkaurelius.titan.hadoop.config.ModifiableHadoopConfiguration;

import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.io.WritableComparable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Abstract base class for Faunus vertices and relations.
 *
 * This class must implement Hadoop's Configurable even if no code calls setConf or getConf directly.
 * The reason to implement Configurable is interoperability with Hadoop's
 * WritableSerialization.WritableDeserializer class.  The deserializer calls ReflectionUtils.newInstance, which in
 * turn calls {@code x instanceof Configurable} and then calls {@code setConf} when true.  IOW, implementing
 * Configurable is important because that's how path elements get their configuration after being reflectively
 * instantiated with the no-arg constructor.
 *
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 * @author Matthias Broecheler ([email protected])
 */
public abstract class FaunusPathElement extends FaunusElement implements WritableComparable, Configurable {

    private static final Logger log =
            LoggerFactory.getLogger(FaunusPathElement.class);

    static final Tracker DEFAULT_TRACK = new Tracker();

    protected Tracker tracker;
    protected long pathCounter = 0;
    protected Configuration configuration;
    private org.apache.hadoop.conf.Configuration hadoopConf;

    public FaunusPathElement(final long id) {
        this(ModifiableHadoopConfiguration.immutableWithResources(), id);
    }

    public FaunusPathElement(final Configuration configuration, final long id) {
        super(id);
        this.configuration = configuration;
        if (this.configuration.get(PIPELINE_TRACK_PATHS)) {
            tracker = new Tracker((this instanceof FaunusVertex) ?
                    new FaunusVertex.MicroVertex(this.id) :
                    new StandardFaunusEdge.MicroEdge(this.id));
        } else {
            tracker = DEFAULT_TRACK;
        }
    }

    // Supports configuration after Hadoop deserializes instances of this class
    @Override
    public void setConf(org.apache.hadoop.conf.Configuration hadoopConf) {
        this.hadoopConf = hadoopConf;
        this.configuration = ModifiableHadoopConfiguration.of(hadoopConf);

        boolean trackPaths = this.configuration.get(PIPELINE_TRACK_PATHS);
        if (trackPaths) {
            this.tracker = new Tracker((this instanceof FaunusVertex) ?
                    new FaunusVertex.MicroVertex(this.id) :
                    new StandardFaunusEdge.MicroEdge(this.id));
        }
    }

    @Override
    public org.apache.hadoop.conf.Configuration getConf() {
        return hadoopConf;
    }

    public Configuration getFaunusConf() {
        return configuration;
    }

    @Override
    public FaunusSchemaManager getTypeManager() {
        return FaunusSchemaManager.getTypeManager(configuration);
    }

    @Override
    public FaunusVertexQuery query() {
        return new FaunusVertexQuery(this);
    }

    //##################################
    // Path Handling
    //##################################

    protected static class Tracker {

        final boolean trackPaths;
        final List> paths;
        final MicroElement microVersion;

        public Tracker(MicroElement microVersion) {
            this.trackPaths = true;
            this.microVersion = microVersion;
            this.paths = new ArrayList>();
        }

        public Tracker(List> paths, MicroElement microVersion) {
            this.trackPaths = true;
            this.microVersion = microVersion;
            this.paths = paths;
        }

        private Tracker() {
            this.trackPaths = false;
            this.paths = null;
            this.microVersion = null;
        }

    }

    public boolean hasTrackPaths() {
        return tracker.trackPaths;
    }

    private void checkPathsEnabled() {
        Preconditions.checkState(hasTrackPaths(),"Path calculations are not enabled");
    }

    public void addPath(final List path, final boolean append) throws IllegalStateException {
        checkPathsEnabled();
        if (append) path.add(tracker.microVersion);
        tracker.paths.add(path);
        log.trace("Added path {} to {} (append={})", path, this, append);
    }

    public void addPaths(final List> paths, final boolean append) throws IllegalStateException {
        checkPathsEnabled();
        if (append) {
            for (final List path : paths) {
                addPath(path, append);
            }
        } else {
            tracker.paths.addAll(paths);
            log.trace("Adding all paths in list {} to {} (append={})", paths, this, append);
        }
    }

    public List> getPaths() throws IllegalStateException {
        checkPathsEnabled();
        return tracker.paths;
    }

    public void getPaths(final FaunusElement element, final boolean append) {
        Preconditions.checkArgument(element instanceof FaunusPathElement);
        if (hasTrackPaths()) {
            addPaths(((FaunusPathElement) element).getPaths(), append);
        } else {
            pathCounter = pathCounter + ((FaunusPathElement) element).pathCount();
        }
    }

    public long incrPath(final long amount) throws IllegalStateException {
        if (hasTrackPaths())
            throw new IllegalStateException("Path calculations are enabled -- use addPath()");
        else
            pathCounter = pathCounter + amount;
        return pathCounter;
    }

    public boolean hasPaths() {
        if (hasTrackPaths())
            return !tracker.paths.isEmpty();
        else
            return pathCounter > 0;
    }

    public void clearPaths() {
        if (hasTrackPaths()) {
            tracker.paths.clear();
        } else
            this.pathCounter = 0;
        log.trace("Cleared paths on {}", this);
    }

    public long pathCount() {
        if (hasTrackPaths())
            return tracker.paths.size();
        else
            return this.pathCounter;
    }

    public void startPath() {
        if (hasTrackPaths()) {
            clearPaths();
            final List startPath = new ArrayList();
            startPath.add(tracker.microVersion);
            tracker.paths.add(startPath);
        } else {
            this.pathCounter = 1;
        }
    }


    public static abstract class MicroElement {

        protected final long id;

        public MicroElement(final long id) {
            this.id = id;
        }

        public long getId() {
            return this.id;
        }

        @Override
        public int hashCode() {
            return Long.valueOf(this.id).hashCode();
        }

        @Override
        public boolean equals(final Object object) {
            return (object.getClass().equals(this.getClass()) && this.id == ((MicroElement) object).getId());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy