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

net.scattersphere.registry.StreamRegistry Maven / Gradle / Ivy

The newest version!
package net.scattersphere.registry;

import org.mapdb.Atomic;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;

/**
 * This is the cache class that is used to register all streams for jobs.  Stream data is stored for retrieval using
 * {@code MapDB}.
 *
 * Created by kenji on 1/25/15.
 */
public class StreamRegistry {

	private static final StreamRegistry instance = new StreamRegistry();
	private final Logger LOG = LoggerFactory.getLogger(StreamRegistry.class);

	private DB db;

    private static final String STATUS_KEY = "-status";
    private static final String SIZE_KEY = "-size";

	private StreamRegistry() {
		File file = new File("_scattersphereStore");

		try {
			db = DBMaker.newFileDB(file).make();
		} catch(Exception ex) {
			db = null;
			LOG.error("Unable to create a store for Scattersphere Streaming.", ex);
		}
	}

	/**
	 * Retrieves the static singleton instance of this class.
	 *
	 * @return {@link StreamRegistry} object.
	 */
	public static StreamRegistry instance() {
		return instance;
	}

	/**
	 * Opens a stream for writing.
	 *
	 * @param streamId The ID of the stream to write to.
	 */
	public void openStream(String streamId) {
		Objects.requireNonNull(db);
		Objects.requireNonNull(streamId);

        Atomic.Boolean status = db.getAtomicBoolean(streamId + STATUS_KEY);

        status.set(true);

		LOG.info("Opened stream: ID={} status={}", streamId, status.get());
	}

	/**
	 * Retrieves a {@link BlockingQueue} implementation of the stream by ID.  THis is used to retrieve data in the queue, stream
	 * block at a time.
	 *
	 * @param streamId The ID of the stream.
	 * @return {@link BlockingQueue} of {@code byte[]} objects.
	 */
	public BlockingQueue getStream(String streamId) {
		Objects.requireNonNull(db);
		Objects.requireNonNull(streamId);

		return db.getQueue(streamId);
	}

	/**
	 * Indicates whether or not a stream exists by ID.
	 *
	 * @param streamId The stream ID to check for.
	 * @return {@code true} if the stream exists, {@code false} otherwise.
	 */
	public boolean exists(String streamId) {
		Objects.requireNonNull(db);
		Objects.requireNonNull(streamId);

        BlockingQueue queue = db.getQueue(streamId);

        return queue != null;
	}

    /**
     * Queries to see whether or not a stream has been closed.
     *
     * @param streamId The stream ID to check for.
     * @return {@code true} if the stream is closed, {@code false} otherwise.
     */
    public boolean isClosed(String streamId) {
        Objects.requireNonNull(streamId);

        Atomic.Boolean status = db.getAtomicBoolean(streamId + STATUS_KEY);

        return !status.get();
    }

	/**
	 * Closes a stream, indicating that all data to the stream has ended.
	 *
	 * @param streamId The stream ID to close.
	 */
	public void closeStream(String streamId) {
		Objects.requireNonNull(db);
		Objects.requireNonNull(streamId);

        Atomic.Boolean status = db.getAtomicBoolean(streamId + STATUS_KEY);

        status.set(false);

		commit();

        LOG.info("Closed stream: ID={} status={}", streamId, status.get());
	}

	/**
	 * Returns the status of the specified stream.
	 *
	 * @param streamId The stream ID to get the status of.
	 * @return {@code String} containing the status, {@code NOT FOUND} if the stream was not found by the specified ID.
	 */
	public String getStatus(String streamId) {
		Objects.requireNonNull(db);
		Objects.requireNonNull(streamId);

        BlockingQueue queue = db.getQueue(streamId);

        if (queue != null) {
            Atomic.Boolean status = db.getAtomicBoolean(streamId + STATUS_KEY);

            if (status.get()) {
                return "ACTIVE";
            } else {
                if (isEmpty(streamId)) {
                    return "EMPTY";
                }

                return "INACTIVE";
            }
        }

		return "NOT FOUND";
	}

    /**
     * Writes a packet of data to a stream.
     *
     * @param streamId The stream ID to write to.
     * @param data {@code byte[]} array of data to write.
     */
    public void write(String streamId, byte[] data) {
        Objects.requireNonNull(streamId);
        Objects.requireNonNull(data);

        BlockingQueue queue = getStream(streamId);

        queue.add(data);

        Atomic.Integer counter = db.getAtomicInteger(streamId + SIZE_KEY);

        counter.incrementAndGet();

        commit();
    }

    /**
     * Returns the size (in packets) of the stream.
     *
     * @param streamId {@code String} containing the Stream ID.
     * @return {@code int} containing the number of packets written, {@code 0} if none, or non existent.
     */
    public int getSize(String streamId) {
        Objects.requireNonNull(streamId);

        Atomic.Integer counter = db.getAtomicInteger(streamId + SIZE_KEY);

        return counter.get();
    }

    /**
     * Determines if a stream is empty.
     *
     * @param streamId The stream ID to search for.
     * @return {@code true} if the stream is empty, {@code false} otherwise.
     */
    public boolean isEmpty(String streamId) {
        return getSize(streamId) == 0;
    }

    /**
     * This method decreases the size of the stream.
     *
     * @param streamId {@code String} containing the stream ID of which to decrement the size.
     */
    public void decrementStreamSize(String streamId) {
        Objects.requireNonNull(streamId);

        Atomic.Integer counter = db.getAtomicInteger(streamId + SIZE_KEY);

        if (counter.get() == 0) {
            return;
        }

        counter.decrementAndGet();

        commit();
    }

    /**
	 * Commits all data writes to the database.
	 */
	public void commit() {
		db.commit();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy