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

com.kolibrifx.plovercrest.server.streams.folds.FoldStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2017, KolibriFX AS. Licensed under the Apache License, version 2.0.
 */

package com.kolibrifx.plovercrest.server.streams.folds;

import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicLong;
import com.kolibrifx.plovercrest.client.PlovercrestException;
import com.kolibrifx.plovercrest.client.TableMetadata;
import com.kolibrifx.plovercrest.server.internal.folds.FoldReader;
import com.kolibrifx.plovercrest.server.internal.folds.FoldReaderSetup;
import com.kolibrifx.plovercrest.server.internal.folds.FoldWriter;
import com.kolibrifx.plovercrest.server.internal.folds.Timestamped;
import com.kolibrifx.plovercrest.server.internal.streams.NullStreamObserver;
import com.kolibrifx.plovercrest.server.streams.PollableReader;
import com.kolibrifx.plovercrest.server.streams.Stream;
import com.kolibrifx.plovercrest.server.streams.StreamObserver;
import com.kolibrifx.plovercrest.server.streams.StreamWriter;

public class FoldStream implements Stream {
    private final List> inputs;
    private final TableMetadata metadata;
    private final CombinatorStrategy combinatorStrategy;
    private final FoldSetup setup;
    private final Class elementClass;
    private final String name;

    public FoldStream(final String name,
                      final Class elementClass,
                      final List> inputs,
                      final TableMetadata metadata,
                      final CombinatorStrategy combinatorStrategy,
                      final FoldSetup setup) {
        this.name = name;
        this.elementClass = elementClass;
        this.inputs = inputs;
        this.metadata = metadata;
        this.combinatorStrategy = combinatorStrategy;
        this.setup = setup;
    }

    @Override
    public PollableReader createReaderFromTimestamp(final long timestamp, final StreamObserver observer) {
        final Queue> outputQueue = new ArrayDeque<>();
        final FoldWriter foldWriter = new FoldWriter() {
            @Override
            public void write(final long timestamp, final T value) {
                outputQueue.add(new Timestamped<>(timestamp, value));
            }
        };
        //final long adjustedTimestamp = setup.seekTakePrevious(timestamp, inputs);
        final FoldReaderSetup params = setup.setupReader(timestamp, foldWriter, inputs);
        return new FoldReader(timestamp, combinatorStrategy, observer, params.getInputs(),
                                    params.getFoldCallback(), outputQueue);
    }

    @Override
    public PollableReader createReaderFromIndex(final long index, final StreamObserver observer) {
        throw new PlovercrestException("Index queries is not supported");
    }

    @Override
    public StreamWriter getWriter() {
        throw new PlovercrestException("Fold stream are read-only");
    }

    @Override
    public long getFirstTimestamp() {
        final AtomicLong timestamp = new AtomicLong();
        final PollableReader reader = createReaderFromTimestamp(0, (ts, index, el) -> timestamp.set(ts));
        if (reader.poll()) {
            return timestamp.get();
        } else {
            return -1;
        }
    }

    @Override
    public long getLastTimestamp() {
        return setup.getLastOutputTimestamp(inputs, combinatorStrategy);
    }

    @Override
    public long getDataLengthInBytes() {
        return 0;
    }

    @Override
    public long getEntryCount() {
        return -1;
    }

    @Override
    public TableMetadata getMetadata() {
        return metadata;
    }

    @Override
    public long getLastValidTimestamp() {
        long result = Long.MAX_VALUE;
        for (final Stream input : inputs) {
            result = Math.min(result, input.getLastValidTimestamp());
        }
        return result;
    }

    @Override
    public boolean isFrozen() {
        return false;
    }

    @Override
    public boolean delete() {
        return false;
    }

    @Override
    public boolean rename(final String newName) {
        return false;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Class getElementClass() {
        return elementClass;
    }

    @Override
    public long seekPreviousTimestamp(final long targetTimestamp) {
        final long lastTimestamp = getLastTimestamp();
        if (lastTimestamp < 0) {
            return -1;
        }
        final AtomicLong observed = new AtomicLong();
        final long adjustedTimestamp = Math.min(targetTimestamp, lastTimestamp);
        final PollableReader reader = createReaderFromTimestamp(adjustedTimestamp, new NullStreamObserver() {
            @Override
            public void onObserve(final long timestamp, final long index, final T element) {
                observed.set(timestamp);
            }
        });
        if (reader.poll()) {
            return observed.get();
        } else {
            // FIXME: can happen due to createReaderFromTimestamp() not seeking backwards properly.
            // Returning the target instead of -1 is a workaround.
            //return -1;
            return adjustedTimestamp;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy