com.devexperts.qd.QDContract

Here are the examples of the java api com.devexperts.qd.QDContract taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

56 Examples 7

19 Source : CollectorManagementFactoryImpl.java
with Mozilla Public License 2.0
from devexperts

public CollectorManagement getInstance(DataScheme scheme, QDContract contract, String keyProperties) {
    return CollectorManagementImplOneContract.getInstance(scheme, contract, keyProperties);
}

19 Source : OutputStreamMessageConsumer.java
with Mozilla Public License 2.0
from devexperts

protected boolean acceptCursor(QDContract contract, RecordCursor cursor) {
    return true;
}

19 Source : StripedFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDAgent.Builder createVoidAgentBuilder(QDContract contract, DataScheme scheme) {
    return base.createVoidAgentBuilder(contract, scheme);
}

19 Source : StripedFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDCollector.Builder<?> collectorBuilder(QDContract contract) {
    return new AbstractCollectorBuilder(contract) {

        @Override
        public QDCollector build() {
            int n = getStripeProp(contract.toString());
            if (n <= 1)
                return base.collectorBuilder(getContract()).copyFrom(this).build();
            switch(contract) {
                case TICKER:
                    return new StripedTicker(base, this, n);
                case STREAM:
                    return new StripedStream(base, this, n);
                case HISTORY:
                    return new StripedHistory(base, this, n);
                default:
                    throw new IllegalArgumentException();
            }
        }

        private int getStripeProp(String contract) {
            return SystemProperties.getIntProperty(STRIPE_PROP + "." + contract, StripedFactory.this.n);
        }
    };
}

19 Source : HashFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDCollector.Builder<?> collectorBuilder(QDContract contract) {
    return new AbstractCollectorBuilder(contract) {

        @Override
        public QDCollector build() {
            QDTicker ticker = new HashTicker(this);
            switch(contract) {
                case TICKER:
                    return ticker;
                case STREAM:
                    return new StreamViaCollector(ticker, this);
                case HISTORY:
                    return new HistoryViaTicker(ticker, this);
                default:
                    throw new IllegalArgumentException();
            }
        }
    };
}

19 Source : LoggedQDFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDAgent.Builder createVoidAgentBuilder(QDContract contract, DataScheme scheme) {
    return delegate.createVoidAgentBuilder(contract, scheme);
}

19 Source : LoggedQDFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDCollector.Builder<?> collectorBuilder(QDContract contract) {
    return new AbstractCollectorBuilder(contract) {

        @Override
        public QDCollector build() {
            int n = counter.get(contract).next();
            log.debug("create" + contract + "(" + getScheme() + ", " + getStats() + ") = #" + n);
            switch(contract) {
                case TICKER:
                    return new LoggedTicker(log.child("ticker" + n), (QDTicker) buildViaDelegate(), this);
                case STREAM:
                    return new LoggedStream(log.child("stream" + n), (QDStream) buildViaDelegate(), this);
                case HISTORY:
                    return new LoggedHistory(log.child("history" + n), (QDHistory) buildViaDelegate(), this);
                default:
                    throw new IllegalArgumentException();
            }
        }

        private QDCollector buildViaDelegate() {
            return delegate.collectorBuilder(getContract()).copyFrom(this).build();
        }
    };
}

19 Source : QDEndpoint.java
with Mozilla Public License 2.0
from devexperts

private void collectorRedefined(QDContract contract) throws IllegalArgumentException {
    throw new IllegalArgumentException("Only one " + contract + " collector can be used");
}

19 Source : DistributorAdapter.java
with Mozilla Public License 2.0
from devexperts

/**
 * The <code>DistributorAdapter</code> adapts distributor side of QD to message API.
 * The distributor side of an QD is an aggregation of {@link QDDistributor}
 * for all its APIs (the <code>DistributorAdapter</code> creates its own distributors,
 * one distributor per API). Thus, the <code>DistributorAdapter</code> can be used
 * to represent an outside data provider in the specific QD.
 *
 * if you are a QD client - use this Adapter
 */
public clreplaced DistributorAdapter extends MessageAdapter implements QDFilter.UpdateListener {

    private static final QDContract[] QD_CONTRACTS = QDContract.values();

    private static final int N_CONTRACTS = QD_CONTRACTS.length;

    private static final MessageType[] ADD_MESSAGES = new MessageType[N_CONTRACTS];

    private static final MessageType[] REMOVE_MESSAGES = new MessageType[N_CONTRACTS];

    static {
        for (QDContract contract : QD_CONTRACTS) {
            ADD_MESSAGES[contract.ordinal()] = MessageType.forAddSubscription(contract);
            REMOVE_MESSAGES[contract.ordinal()] = MessageType.forRemoveSubscription(contract);
        }
    }

    /**
     * The factory for distributor side of an QD.
     */
    public static clreplaced Factory extends MessageAdapter.AbstractFactory {

        /**
         * Creates new factory. Accepts <code>null</code> parameters.
         */
        public Factory(QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter) {
            super(ticker, stream, history, filter);
        }

        public Factory(QDEndpoint endpoint, SubscriptionFilter filter) {
            super(endpoint, filter);
        }

        public Factory(QDTicker ticker) {
            this(ticker, null, null, null);
        }

        public Factory(QDStream stream) {
            this(null, stream, null, null);
        }

        public Factory(QDHistory history) {
            this(null, null, history, null);
        }

        public Factory(QDCollector collector) {
            this(collector instanceof QDTicker ? (QDTicker) collector : null, collector instanceof QDStream ? (QDStream) collector : null, collector instanceof QDHistory ? (QDHistory) collector : null, null);
        }

        @Override
        public MessageAdapter createAdapter(QDStats stats) {
            return new DistributorAdapter(endpoint, ticker, stream, history, getFilter(), stats);
        }
    }

    // ------------------------- instance fields -------------------------
    private final DataScheme scheme;

    // @NotNull
    private final QDFilter filter;

    private final QDCollector[] collectors = new QDCollector[N_CONTRACTS];

    private final AtomicReferenceArray<QDDistributor> distributors = new AtomicReferenceArray<>(N_CONTRACTS);

    // peer filters
    private final QDFilter[] peerFilter = new QDFilter[N_CONTRACTS];

    private final RecordListener subListener = new SubListener();

    private int phaseAdd;

    private int phaseRemove;

    // ------------------------- constructors -------------------------
    public DistributorAdapter(QDEndpoint endpoint, QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter, QDStats stats) {
        super(endpoint, stats);
        this.scheme = getCommonScheme(ticker, stream, history);
        this.filter = QDFilter.fromFilter(filter, scheme);
        collectors[QDContract.TICKER.ordinal()] = ticker;
        collectors[QDContract.STREAM.ordinal()] = stream;
        collectors[QDContract.HISTORY.ordinal()] = history;
    }

    public DistributorAdapter(QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter, QDStats stats) {
        this(null, ticker, stream, history, filter, stats);
    }

    // ------------------------- instance methods -------------------------
    public QDCollector getCollector(QDContract contract) {
        return collectors[contract.ordinal()];
    }

    /**
     * This method is used internally by distributor adapter to create agent for the corresponding
     * collector, filter, and keyProperties from this adapter's constructor.
     * This implementation returns <code>collector.createDistributor(filter, keyProperties)</code>.
     * This method may be overridden to create agent with other filter, otherwise customize the agent
     * that is being created, or to keep track of created agents.
     */
    protected QDDistributor createDistributor(QDCollector collector, SubscriptionFilter filter, String keyProperties) {
        return collector.distributorBuilder().withFilter(QDFilter.fromFilter(filter, scheme)).withKeyProperties(keyProperties).build();
    }

    private QDDistributor getOrCreateDistributor(int i) {
        QDDistributor distributor = distributors.get(i);
        if (distributor != null)
            return distributor;
        QDCollector collector = collectors[i];
        if (collector == null)
            return null;
        synchronized (this) {
            distributor = distributors.get(i);
            if (distributor != null)
                return distributor;
            distributor = createDistributor(collector, CompositeFilters.makeAnd(peerFilter[i], filter), getStats().getFullKeyProperties());
            distributors.set(i, distributor);
        }
        return distributor;
    }

    public String toString() {
        return super.toString() + (filter == QDFilter.ANYTHING ? "" : "[" + filter + "]");
    }

    @Override
    public DataScheme getScheme() {
        return scheme;
    }

    @Override
    public String getSymbol(char[] chars, int offset, int length) {
        QDCollector c;
        String s;
        for (int i = 0; i < N_CONTRACTS; i++) if ((c = collectors[i]) != null && (s = c.getSymbol(chars, offset, length)) != null)
            return s;
        return null;
    }

    // ========== Dynamic filters support ==========
    @Override
    public void filterUpdated(QDFilter filter) {
        markForImmediateRestart();
        close();
    }

    // ========== MessageAdapter Override ==========
    @Override
    protected void startImpl(MasterMessageAdapter master) {
        if (filter.isDynamic())
            QDLog.log.warn("Using dynamic filter '" + LogUtil.hideCredentials(filter) + "'" + " in distributor address will cause connection reset when filter changes");
        // listen for filter updates
        filter.addUpdateListener(this);
        // Legacy behavior: immediately send subscription if we are not using DESCRIBE_PROTOCOL messages,
        // which is when useDescribeProtocol() was not called before start.
        if (!useDescribeProtocol)
            sendSubscriptionFromAllCollectors();
        super.startImpl(master);
    }

    @Override
    protected void closeImpl() {
        filter.removeUpdateListener(this);
        for (int i = 0; i < N_CONTRACTS; i++) if (distributors.get(i) != null)
            distributors.get(i).close();
    }

    @Override
    protected void processData(DataIterator iterator, MessageType message) {
        if (!message.isData())
            throw new IllegalArgumentException(message.toString());
        if (!isAlive()) {
            reportIgnoredMessage("Adapter is " + getStatus(), message);
        } else {
            QDContract contract = message.getContract();
            if (contract != null) {
                QDDistributor distributor = getOrCreateDistributor(contract.ordinal());
                if (distributor == null) {
                    reportIgnoredMessage("Contract is not supported", message);
                } else {
                    distributor.processData(iterator);
                    // processed -- exit from method
                    return;
                }
            }
        }
        // silently ignore otherwise
        DataConsumer.VOID.processData(iterator);
    }

    @Override
    public boolean retrieveMessages(MessageVisitor visitor) {
        super.retrieveMessages(visitor);
        long mask = retrieveMask();
        mask = retrieveDescribeProtocolMessage(visitor, mask);
        mask = retrieveAddAndRemoveMessages(visitor, mask);
        // note: addMask was previously enclosed into finally block. This could lead to StockOverflow and
        // offers no real protection, since any exception should terminate ongoing connection anyway.
        addMask(mask);
        return mask != 0;
    }

    @Override
    public void prepareProtocolDescriptor(ProtocolDescriptor desc) {
        super.prepareProtocolDescriptor(desc);
        QDFilter stableFilter = CompositeFilters.toStableFilter(this.filter);
        if (stableFilter != QDFilter.ANYTHING)
            desc.setProperty(ProtocolDescriptor.FILTER_PROPERTY, stableFilter.toString());
        for (QDContract contract : QD_CONTRACTS) if (collectors[contract.ordinal()] != null) {
            desc.addSend(desc.newMessageDescriptor(MessageType.forAddSubscription(contract)));
            desc.addSend(desc.newMessageDescriptor(MessageType.forRemoveSubscription(contract)));
            desc.addReceive(desc.newMessageDescriptor(MessageType.forData(contract)));
        }
        desc.addReceive(desc.newMessageDescriptor(MessageType.RAW_DATA));
    }

    @Override
    public void processDescribeProtocol(ProtocolDescriptor desc, boolean logDescriptor) {
        super.processDescribeProtocol(desc, logDescriptor);
        QDFilterFactory filterFactory = CompositeFilters.getFactory(scheme);
        Map<String, QDFilter> filters = new HashMap<>();
        filters.put(null, QDFilter.ANYTHING);
        for (QDContract contract : QD_CONTRACTS) {
            if (collectors[contract.ordinal()] == null)
                // don't have collector for this contract -- don't care
                continue;
            boolean add = desc.canReceive(MessageType.forAddSubscription(contract));
            boolean remove = desc.canReceive(MessageType.forRemoveSubscription(contract));
            if (!add && !remove)
                // don't create distributor for this contract at all
                continue;
            if (add) {
                // Filters are supported for ADD_SUBSCRIPTION only
                MessageDescriptor md = desc.getReceive(MessageType.forAddSubscription(contract));
                String filter = md.getProperty(ProtocolDescriptor.FILTER_PROPERTY);
                if (// null is anyway in filters map (maps to QDFilter.ANYTHING)
                !filters.containsKey(filter))
                    try {
                        filters.put(filter, filterFactory.createFilter(filter, QDFilterContext.REMOTE_FILTER));
                    } catch (IllegalArgumentException e) {
                        QDLog.log.warn("Cannot parse filter '" + LogUtil.hideCredentials(filter) + "'" + " from " + LogUtil.hideCredentials(getRemoteHostAddress()) + ": " + e);
                        filters.put(filter, QDFilter.ANYTHING);
                    }
                peerFilter[contract.ordinal()] = filters.get(filter);
            }
            QDDistributor distributor = getOrCreateDistributor(contract.ordinal());
            distributor.getAddedRecordProvider().setRecordListener(add ? subListener : RecordListener.VOID);
            distributor.getRemovedRecordProvider().setRecordListener(remove ? subListener : RecordListener.VOID);
        }
    }

    @Override
    public boolean isProtocolDescriptorCompatible(ProtocolDescriptor desc) {
        for (QDContract contract : QD_CONTRACTS) if (collectors[contract.ordinal()] != null && (desc.canReceive(MessageType.forAddSubscription(contract)) || desc.canSend(MessageType.forData(contract)) || desc.canSend(MessageType.RAW_DATA))) {
            return true;
        }
        return false;
    }

    private void sendSubscriptionFromAllCollectors() {
        for (int i = 0; i < N_CONTRACTS; i++) if (collectors[i] != null) {
            QDDistributor distributor = getOrCreateDistributor(i);
            distributor.getAddedRecordProvider().setRecordListener(subListener);
            distributor.getRemovedRecordProvider().setRecordListener(subListener);
        }
    }

    private long retrieveAddAndRemoveMessages(MessageVisitor visitor, long mask) {
        // first process all add messages until they are all exhausted
        int cur = phaseAdd;
        int stop = phaseAdd;
        boolean hasMore = false;
        do {
            MessageType message = ADD_MESSAGES[cur];
            if (hasMessageMask(mask, message)) {
                SubscriptionProvider provider = distributors.get(cur).getAddedSubscriptionProvider();
                hasMore = visitSubscription(visitor, provider, message);
                if (!hasMore)
                    mask = clearMessageMask(mask, message);
            }
            phaseAdd = cur = (cur + 1) % N_CONTRACTS;
        } while (!hasMore && cur != stop);
        // then process remove messages if there's still potential room for them
        if (!hasMore)
            mask = retrieveRemoveMessages(visitor, mask);
        return mask;
    }

    private long retrieveRemoveMessages(MessageVisitor visitor, long mask) {
        int cur = phaseRemove;
        int stop = phaseRemove;
        boolean hasMore = false;
        do {
            MessageType message = REMOVE_MESSAGES[cur];
            if (hasMessageMask(mask, message)) {
                SubscriptionProvider provider = distributors.get(cur).getRemovedSubscriptionProvider();
                hasMore = visitSubscription(visitor, provider, message);
                if (!hasMore)
                    mask = clearMessageMask(mask, message);
            }
            phaseRemove = cur = (cur + 1) % N_CONTRACTS;
        } while (!hasMore && cur != stop);
        return mask;
    }

    // extension method for FeedAdapter in feed tool
    protected boolean visitSubscription(MessageVisitor visitor, SubscriptionProvider provider, MessageType message) {
        return visitor.visitSubscription(provider, message);
    }

    // extension method. It is used to delay subscription processing until credentials are known
    public void subscriptionAvailable(SubscriptionProvider provider) {
        if (provider == null)
            throw new NullPointerException();
        for (int i = 0; i < N_CONTRACTS; i++) {
            QDDistributor distributor = distributors.get(i);
            if (distributor != null) {
                // NOTE: We cannot call getXXXSubProvider unless we definitely know that we need them,
                // since calling those methods lazily initializes the corresponding distributor data structures
                if (provider == distributor.getAddedSubscriptionProvider()) {
                    subscriptionChanged(provider, ADD_MESSAGES[i]);
                    // we found provider
                    return;
                }
                if (provider == distributor.getRemovedSubscriptionProvider()) {
                    subscriptionChanged(provider, REMOVE_MESSAGES[i]);
                    // we found provider
                    return;
                }
            }
        }
        throw new replacedertionError("Unknown subscription provider: " + provider);
    }

    protected void subscriptionChanged(SubscriptionProvider provider, MessageType message) {
        addMask(getMessageMask(message));
    }

    private clreplaced SubListener implements RecordListener {

        @Override
        public void recordsAvailable(RecordProvider provider) {
            subscriptionAvailable(provider);
        }
    }
}

19 Source : DistributorAdapter.java
with Mozilla Public License 2.0
from devexperts

// ------------------------- instance methods -------------------------
public QDCollector getCollector(QDContract contract) {
    return collectors[contract.ordinal()];
}

19 Source : AgentAdapter.java
with Mozilla Public License 2.0
from devexperts

/**
 * The <code>AgentAdapter</code> adapts agent side of QD to message API.
 * The agent side of an QD is an aggregation of {@link QDAgent agents} for all its data sources.
 * Thus, the <code>AgentAdapter</code> can be used to represent an outside data consumer
 * in the specific QD.
 *
 * if you are a QD publisher - use this Adapter
 */
public clreplaced AgentAdapter extends MessageAdapter {

    private static final QDContract[] QD_CONTRACTS = QDContract.values();

    private static final int N_CONTRACTS = QD_CONTRACTS.length;

    private static final Iterable<ChannelShapersFactory> CHANNEL_SHAPERS_FACTORIES = Services.createServices(ChannelShapersFactory.clreplaced, null);

    /**
     * The factory for agent side of an QD.
     */
    public static clreplaced Factory extends MessageAdapter.AbstractFactory {

        /**
         * Aggregation period is a single time period that serves as a default aggregation period
         * for all channels, unless something else is explicitly specified.
         */
        private TimePeriod aggregationPeriod = TimePeriod.valueOf(0);

        /**
         * Channels configuration.
         * @see AgentAdapterChannels
         */
        private AgentAdapterChannels channels;

        /**
         * Size of the pool for subscription-handling threads
         * (zero default - does not use separate thread pool for subscription).
         */
        private int subscriptionThreads;

        /**
         * Explicit subscription executor.
         */
        private Executor subscriptionExecutor;

        /**
         * Subscription keep-alive period.
         * <p>If more than zero, unsubscription requests will be delayed for a specified period to amortize
         * fast unsub/sub sequences.
         * <p><b>NOTE:</b> For the moment only zero and unlimited periods are supported.
         */
        private TimePeriod subscriptionKeepAlive = TimePeriod.ZERO;

        public Factory(QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter) {
            super(ticker, stream, history, filter);
        }

        public Factory(QDEndpoint endpoint, SubscriptionFilter filter) {
            super(endpoint, filter);
        }

        public Factory(QDTicker ticker) {
            this(ticker, null, null, null);
        }

        public Factory(QDStream stream) {
            this(null, stream, null, null);
        }

        public Factory(QDHistory history) {
            this(null, null, history, null);
        }

        public Factory(QDCollector collector) {
            this(collector instanceof QDTicker ? (QDTicker) collector : null, collector instanceof QDStream ? (QDStream) collector : null, collector instanceof QDHistory ? (QDHistory) collector : null, null);
            channels = new AgentAdapterChannels("", this);
        }

        public synchronized TimePeriod getAggregationPeriod() {
            return aggregationPeriod;
        }

        @Configurable(description = "default aggregation period for all channels")
        public synchronized void setAggregationPeriod(TimePeriod aggregationPeriod) {
            if (// also throws NPE
            aggregationPeriod.equals(this.aggregationPeriod))
                return;
            if (aggregationPeriod.getTime() < 0)
                throw new IllegalArgumentException("cannot be negative");
            this.aggregationPeriod = aggregationPeriod;
            rebuildChannels();
        }

        public synchronized String getChannels() {
            return channels == null ? "" : channels.toString();
        }

        @Configurable(description = "channels configuration string")
        public synchronized void setChannels(String channels) {
            if (channels == null)
                throw new NullPointerException();
            // Immediately parse agent channels configuration to complain on any problems
            this.channels = new AgentAdapterChannels(channels, this);
        }

        public synchronized int getSubscriptionThreads() {
            return subscriptionThreads;
        }

        @Configurable(description = "size of the pool for subscription-handling threads\n" + "(zero default - does not use separate thread pool for subscription)")
        public synchronized void setSubscriptionThreads(int subscriptionThreads) {
            if (subscriptionThreads == this.subscriptionThreads)
                return;
            if (subscriptionThreads < 0)
                throw new IllegalArgumentException("cannot be negative");
            this.subscriptionThreads = subscriptionThreads;
            rebuildChannels();
        }

        public synchronized Executor getSubscriptionExecutor() {
            return subscriptionExecutor;
        }

        @Configurable(description = "explicit subscription executor")
        public synchronized void setSubscriptionExecutor(Executor subscriptionExecutor) {
            this.subscriptionExecutor = subscriptionExecutor;
            rebuildChannels();
        }

        @Nonnull
        public synchronized TimePeriod getSubscriptionKeepAlive() {
            return subscriptionKeepAlive;
        }

        @Configurable(description = "subscription keep-alive period (0 or 'inf')")
        public synchronized void setSubscriptionKeepAlive(TimePeriod keepAlive) {
            Objects.requireNonNull(keepAlive);
            if (subscriptionKeepAlive.equals(keepAlive))
                return;
            if (!TimePeriod.ZERO.equals(keepAlive) && !TimePeriod.UNLIMITED.equals(keepAlive))
                throw new IllegalArgumentException("Only zero or infinite supported");
            this.subscriptionKeepAlive = keepAlive;
            rebuildChannels();
        }

        synchronized Executor getOrCreateSubscriptionExecutor() {
            if (subscriptionExecutor != null)
                return subscriptionExecutor;
            if (subscriptionThreads > 0)
                subscriptionExecutor = new LoggedThreadPoolExecutor(subscriptionThreads, this + "-Subscription", QDLog.log);
            return subscriptionExecutor;
        }

        @Nonnull
        AgentAdapterChannels getAgentAdapterChannels() {
            AgentAdapterChannels channels;
            synchronized (this) {
                if (this.channels == null)
                    // create default implicit configuration if not set explicitly
                    this.channels = new AgentAdapterChannels("", this);
                channels = this.channels;
            }
            return channels;
        }

        private void rebuildChannels() {
            if (// rebuild agent channels configuration
            channels != null)
                channels = new AgentAdapterChannels(channels.toString(), this);
        }

        @Override
        public MessageAdapter createAdapter(QDStats stats) {
            AgentAdapter adapter = new AgentAdapter(endpoint, getCommonScheme(ticker, stream, history), getFilter(), stats);
            adapter.setAgentFactory(this);
            return adapter;
        }
    }

    // ------------------------- instance fields -------------------------
    private final DataScheme scheme;

    // @NotNull
    private final QDFilter filter;

    private AgentAdapter.Factory factory;

    // current implementation supports only infinite keep-alive period
    private boolean skipRemoveSubscription = false;

    // filters received from remote peer in DESCRIBE PROTOCOL message
    final QDFilter[] peerFilter = new QDFilter[N_CONTRACTS];

    // effectively final, filled by initialize method
    private ChannelShaper[] shapers;

    // effective final, initially all null values, allocated by initialize method, filled (replacedigned) lazily
    private AgentChannel[] channels;

    // ------------------------- constructors -------------------------
    /**
     * Creates new agent adapter for specified endpoints, ticker, stream, history, filter and stats.
     * Any of the endpoint, collectors and/or filter may be {@code null}.
     *
     * The resulting adapter will be {@link #initialize(ChannelShaper[]) initiailized}.
     * It will use equal weight of 1 and no aggregation for all collectors.
     */
    public AgentAdapter(QDEndpoint endpoint, QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter, QDStats stats) {
        super(endpoint, stats);
        this.scheme = getCommonScheme(ticker, stream, history);
        this.filter = QDFilter.fromFilter(filter, scheme);
        ArrayList<ChannelShaper> shapers = new ArrayList<>();
        if (ticker != null)
            shapers.add(newDynamicShaper(ticker));
        if (stream != null)
            shapers.add(newDynamicShaper(stream));
        if (history != null)
            shapers.add(newDynamicShaper(history));
        initialize(shapers.toArray(new ChannelShaper[shapers.size()]));
    }

    /**
     * Creates new agent adapter for specified ticker, stream, history, filter and stats.
     * Any of the collectors and/or filter may be {@code null}.
     *
     * The resulting adapter will be {@link #initialize(ChannelShaper[]) initiailized}.
     * It will use equal weight of 1 and no aggregation for all collectors.
     */
    public AgentAdapter(QDTicker ticker, QDStream stream, QDHistory history, SubscriptionFilter filter, QDStats stats) {
        this(null, ticker, stream, history, filter, stats);
    }

    /**
     * Creates new agent adapter for specified scheme and stats.
     *
     * Adapter created by this constructor must be {@link #initialize(ChannelShaper[]) initialized}
     * with shapers before being used.
     *
     * @param scheme data scheme
     * @param stats stats
     */
    public AgentAdapter(DataScheme scheme, QDStats stats) {
        this(null, scheme, QDFilter.ANYTHING, stats);
    }

    private AgentAdapter(QDEndpoint endpoint, DataScheme scheme, QDFilter filter, QDStats stats) {
        super(endpoint, stats);
        if (scheme == null)
            throw new NullPointerException();
        this.scheme = scheme;
        this.filter = filter;
    }

    private DynamicChannelShaper newDynamicShaper(QDCollector collector) {
        DynamicChannelShaper shaper = new DynamicChannelShaper(collector.getContract(), null, this.filter);
        shaper.setCollector(collector);
        return shaper;
    }

    // ------------------------- instance methods -------------------------
    /**
     * Initializes the adapter with specified channel shapers. This method must be called exactly once
     * before the adapter is used (unless the adapter is created with
     * {@link #AgentAdapter(QDTicker, QDStream, QDHistory, SubscriptionFilter, QDStats)} constructor in which case
     * it ia already initialized).
     * All channels are bound to this agent and cannot be used in other agent.
     *
     * @param shapers shaping configuration for adapter channels
     * @return this agent adapter (in order to allow chained notation)
     */
    public synchronized AgentAdapter initialize(ChannelShaper... shapers) {
        if (this.shapers != null)
            throw new IllegalArgumentException("Already initialized");
        this.shapers = shapers.clone();
        channels = new AgentChannel[shapers.length];
        return this;
    }

    /**
     * This method is used internally by agent adapter to create agent for the corresponding
     * collector, filter, and keyProperties when the corresponding subscription arrives for a first time.
     * This method is called while holding <code>this</code> adapter's lock.
     * This implementation returns <code>collector.createAgent(filter, keyProperties)</code>.
     * This method may be overriden to create agent with other filter, otherwise customize the agent
     * that is being created, or to keep track of created agents.
     *
     * @param collector collector to create agent for
     * @param filter subscription filter for the agent
     * @param keyProperties key properties for stats
     * @return newly created agent
     */
    protected QDAgent createAgent(QDCollector collector, SubscriptionFilter filter, String keyProperties) {
        return createAgentBuilder(collector, filter, keyProperties).build();
    }

    protected QDAgent.Builder createAgentBuilder(QDCollector collector, SubscriptionFilter filter, String keyProperties) {
        return collector.agentBuilder().withFilter(QDFilter.fromFilter(filter, scheme)).withKeyProperties(keyProperties).withOptSet(getRemoteOptSet());
    }

    public String toString() {
        return super.toString() + (filter == QDFilter.ANYTHING ? "" : "[" + filter + "]");
    }

    @Override
    public DataScheme getScheme() {
        return scheme;
    }

    @Override
    public String getSymbol(char[] chars, int offset, int length) {
        QDCollector prevCollector = null;
        for (AgentChannel channel : channels) {
            if (channel == null)
                // not initialized yet (no subscription)
                continue;
            QDCollector collector = channel.shaper.getCollector();
            if (collector == prevCollector || collector == null)
                continue;
            String result = collector.getSymbol(chars, offset, length);
            if (result != null)
                return result;
            prevCollector = collector;
        }
        return null;
    }

    /**
     * @deprecated No need to use this method. It does nothing. Channels are automatically update on change
     * of their parameters.
     */
    public void updateChannel(ChannelShaper shaper) {
    }

    private void setAgentFactory(AgentAdapter.Factory factory) {
        this.factory = factory;
        skipRemoveSubscription = TimePeriod.UNLIMITED.equals(factory.getSubscriptionKeepAlive());
    }

    Factory getAgentFactory() {
        return factory;
    }

    @Override
    public boolean supportsMixedSubscription() {
        // All QDAgents must support mixed subscription
        return true;
    }

    // ========== MessageAdapter Override ==========
    @Override
    protected void processSubscription(SubscriptionIterator iterator, MessageType message) {
        if (!message.isSubscription())
            throw new IllegalArgumentException(message.toString());
        if (!isAlive()) {
            reportIgnoredMessage("Adapter is " + getStatus(), message);
        } else if (!skipRemoveSubscription || !message.isSubscriptionRemove()) {
            RecordSource sub = LegacyAdapter.of(iterator);
            if (skipRemoveSubscription) {
                RecordBuffer buf = skipRemoveSubscription(sub);
                processSubscription(buf, message);
                buf.release();
            } else {
                processSubscription(sub, message);
            }
            LegacyAdapter.release(iterator, sub);
        }
        // silently ignore all remaining data if it was not processed
        SubscriptionConsumer.VOID.processSubscription(iterator);
    }

    private void processSubscription(RecordSource sub, MessageType message) {
        QDContract contract = message.getContract();
        boolean hasContract = false;
        long initialPosition = sub.getPosition();
        for (int i = 0; i < shapers.length; i++) {
            ChannelShaper shaper = shapers[i];
            if (shaper.getContract() != contract)
                continue;
            hasContract = true;
            AgentChannel channel = getOrCreateChannelAt(i);
            sub.setPosition(initialPosition);
            channel.processSubscription(message, sub);
        }
        if (!hasContract)
            reportIgnoredMessage("Contract is not supported", message);
    }

    private RecordBuffer skipRemoveSubscription(RecordSource sub) {
        RecordBuffer buf = RecordBuffer.getInstance(sub.getMode());
        for (RecordCursor cur; (cur = sub.next()) != null; ) {
            if (!EventFlag.REMOVE_SYMBOL.in(cur.getEventFlags()))
                buf.append(cur);
        }
        return buf;
    }

    private AgentChannel getOrCreateChannelAt(int i) {
        AgentChannel channel = channels[i];
        if (channel == null) {
            ChannelShaper shaper = shapers[i];
            channel = new AgentChannel(this, shaper);
            shaper.bind(channel);
            channels[i] = channel;
        }
        return channel;
    }

    @Override
    protected void closeImpl() {
        replacedert Thread.holdsLock(this);
        if (channels != null) {
            for (AgentChannel channel : channels) {
                if (channel != null)
                    channel.close();
            }
        }
    }

    @Override
    public boolean retrieveMessages(MessageVisitor visitor) {
        super.retrieveMessages(visitor);
        long mask = retrieveMask();
        mask = retrieveDescribeProtocolMessage(visitor, mask);
        // note: addMask was previously enclosed into finally block. This could lead to StockOverflow and
        // offers no real protection, since any exception should terminate ongoing connection anyway.
        addMask(mask);
        boolean result = mask != 0;
        result |= retrieveDataMessages(visitor);
        return result;
    }

    @Override
    public void prepareProtocolDescriptor(ProtocolDescriptor desc) {
        super.prepareProtocolDescriptor(desc);
        Map<MessageDescriptor, String> messageTypeFilters = new HashMap<>();
        for (QDContract contract : QD_CONTRACTS) {
            QDFilter combinedFilter = QDFilter.NOTHING;
            for (ChannelShaper shaper : shapers) {
                if (shaper.getContract() == contract) {
                    // compute combined filter for all channels for this contract
                    combinedFilter = CompositeFilters.makeOr(combinedFilter, shaper.getSubscriptionFilter().toStableFilter());
                }
            }
            if (combinedFilter != QDFilter.NOTHING) {
                // prepare message for this contract
                MessageDescriptor addSubscriptionMessage = desc.newMessageDescriptor(MessageType.forAddSubscription(contract));
                desc.addSend(desc.newMessageDescriptor(MessageType.forData(contract)));
                desc.addReceive(addSubscriptionMessage);
                desc.addReceive(desc.newMessageDescriptor(MessageType.forRemoveSubscription(contract)));
                // postpone setting contract filter
                messageTypeFilters.put(addSubscriptionMessage, combinedFilter.toString());
            }
        }
        // now check if filters for all message types are the same.
        HashSet<String> filtersStringSet = new HashSet<>(messageTypeFilters.values());
        if (filtersStringSet.size() == 1) {
            // use common filter property
            String filter = filtersStringSet.iterator().next();
            if (// don't need to set filter for "anything" explicitly
            !filter.equals(QDFilter.ANYTHING.toString()))
                desc.setProperty(ProtocolDescriptor.FILTER_PROPERTY, filter);
        } else {
            // set its own filter for each contract
            messageTypeFilters.entrySet().stream().filter(entry -> !entry.getValue().isEmpty()).forEach(entry -> entry.getKey().setProperty(ProtocolDescriptor.FILTER_PROPERTY, entry.getValue()));
        }
    }

    @Override
    public void processDescribeProtocol(ProtocolDescriptor desc, boolean logDescriptor) {
        super.processDescribeProtocol(desc, logDescriptor);
        if (channels == null)
            return;
        QDFilterFactory filterFactory = CompositeFilters.getFactory(scheme);
        Map<String, QDFilter> filters = new HashMap<>();
        filters.put(null, QDFilter.ANYTHING);
        for (QDContract contract : QD_CONTRACTS) {
            MessageDescriptor md = desc.getReceive(MessageType.forData(contract));
            if (md == null)
                continue;
            String filter = md.getProperty(ProtocolDescriptor.FILTER_PROPERTY);
            if (// null is anyway in filters map (maps to QDFilter.ANYTHING)
            !filters.containsKey(filter))
                try {
                    filters.put(filter, filterFactory.createFilter(filter, QDFilterContext.REMOTE_FILTER));
                } catch (IllegalArgumentException e) {
                    QDLog.log.warn("Cannot parse filter '" + LogUtil.hideCredentials(filter) + "'" + " from " + LogUtil.hideCredentials(getRemoteHostAddress()), e);
                    filters.put(filter, QDFilter.ANYTHING);
                }
            peerFilter[contract.ordinal()] = filters.get(filter);
        }
    }

    @Override
    public boolean isProtocolDescriptorCompatible(ProtocolDescriptor desc) {
        if (shapers == null)
            return true;
        for (QDContract contract : QD_CONTRACTS) {
            boolean hasContract = false;
            for (ChannelShaper shaper : shapers) {
                if (shaper.getContract() != contract)
                    continue;
                hasContract = true;
            }
            if (hasContract && desc.canSend(MessageType.forAddSubscription(contract)) && desc.canReceive(MessageType.forData(contract)))
                return true;
        }
        return false;
    }

    // returns true if more data remains in collectors, false otherwise
    protected boolean retrieveDataMessages(MessageVisitor visitor) {
        if (channels == null)
            return false;
        for (int iterations = channels.length; --iterations >= 0; ) {
            long currentTime = System.currentTimeMillis();
            // how much weight should be distributed to allow channel with data to achieve quota of 1
            double minDistance = Double.POSITIVE_INFINITY;
            // first channel to achieve quota of 1
            AgentChannel dueChannel = null;
            for (AgentChannel channel : channels) {
                if (channel == null)
                    // not initialized yet (no subscription)
                    continue;
                if (channel.hreplacednapshotOrDataForNow(currentTime)) {
                    if (channel.quota >= 1) {
                        minDistance = 0;
                        dueChannel = channel;
                        break;
                    }
                    double distance = (1 - channel.quota) / channel.shaper.getWeight();
                    if (distance < minDistance) {
                        minDistance = distance;
                        dueChannel = channel;
                    }
                }
            }
            if (dueChannel == null)
                // no one has any data
                return false;
            if (minDistance > 0)
                for (AgentChannel channel : channels) {
                    // distribute more quota
                    if (channel == null)
                        // not initialized yet (no subscription)
                        continue;
                    channel.quota += minDistance * channel.shaper.getWeight();
                    if (// can happen for channels which has no data for now
                    channel.quota >= 1)
                        channel.quota = 1;
                }
            dueChannel.quota = 0;
            if (dueChannel.retrieveSnapshotOrData(visitor, currentTime))
                return true;
        }
        return true;
    }

    @Override
    public void reinitConfiguration(AuthSession session) {
        if (session == null) {
            if (hasAuthRealm())
                return;
            if (channels == null)
                initialize(factory.getAgentAdapterChannels().getNewShapers());
            return;
        }
        ChannelShaper[] shapers = null;
        if (CHANNEL_SHAPERS_FACTORIES != null) {
            for (ChannelShapersFactory shapersFactory : CHANNEL_SHAPERS_FACTORIES) {
                shapers = shapersFactory.createChannelShapers(this, session);
                if (shapers != null)
                    break;
            }
        }
        if (shapers == null)
            shapers = BasicChannelShaperFactory.INSTANCE.createChannelShapers(this, session);
        initialize(shapers);
    }

    @Override
    public long nextRetrieveTime(long currentTime) {
        long time = super.nextRetrieveTime(currentTime);
        if (channels != null) {
            for (AgentChannel channel : channels) {
                if (channel == null)
                    // not initialized yet (no subscription)
                    continue;
                time = Math.min(time, channel.nextRetrieveTime(currentTime));
            }
        }
        return time;
    }

    // extension method for SubscriptionAdapter in feed tool
    protected boolean visitData(MessageVisitor visitor, RecordProvider provider, MessageType message) {
        return visitor.visitData(provider, message);
    }
}

19 Source : RecordMode.java
with Mozilla Public License 2.0
from devexperts

// ================= public static methods =================
/**
 * Returns record mode that is used for <b>added subscription</b> of the specified contract.
 * Note, that remove subscription always use {@link #SUBSCRIPTION SUBSCRIPTION} mode.
 * @param contract the contract.
 * @return record mode.
 */
public static RecordMode addedSubscriptionFor(QDContract contract) {
    return contract == QDContract.HISTORY ? HISTORY_SUBSCRIPTION : SUBSCRIPTION;
}

19 Source : VoidAgentBuilder.java
with Mozilla Public License 2.0
from devexperts

clreplaced VoidAgentBuilder extends AbstractAgentBuilder {

    final QDContract contract;

    final DataScheme scheme;

    VoidAgentBuilder(QDContract contract, DataScheme scheme) {
        if (contract == null || scheme == null)
            throw new NullPointerException();
        this.contract = contract;
        this.scheme = scheme;
    }

    @Override
    public QDAgent build() {
        return new VoidAgent(this);
    }
}

19 Source : VoidAgent.java
with Mozilla Public License 2.0
from devexperts

clreplaced VoidAgent extends AbstractAgent implements RecordsContainer {

    private static final int STEP = 2;

    private static final int HISTORY_STEP = 4;

    private static final int VOID_TIME_SUB = 2;

    private static final int ATTACHMENT = 0;

    private final QDContract contract;

    private final DataScheme scheme;

    private final QDFilter filter;

    private volatile PayloadBitsSubMatrix sub;

    VoidAgent(VoidAgentBuilder builder) {
        super(builder.contract, builder);
        this.contract = builder.contract;
        this.scheme = builder.scheme;
        this.filter = builder.getFilter();
    }

    @Override
    public void setRecordListener(RecordListener listener) {
    // nothing to do
    }

    @Override
    public boolean retrieve(RecordSink sink) {
        // no data here
        return false;
    }

    @Override
    public synchronized void addSubscription(RecordSource source) {
        RecordCursor cur;
        while ((cur = source.next()) != null) {
            if (EventFlag.REMOVE_SYMBOL.in(cur.getEventFlags())) {
                // remove
                removeSubInternal(cur);
            } else {
                // add
                if (filter.accept(contract, cur.getRecord(), cur.getCipher(), cur.getSymbol()))
                    addSubInternal(cur);
            }
        }
    }

    @Override
    public synchronized void removeSubscription(RecordSource source) {
        RecordCursor cur;
        while ((cur = source.next()) != null) {
            removeSubInternal(cur);
        }
    }

    @Override
    public synchronized void setSubscription(RecordSource source) {
        // drop old subscription to create it from scratch
        sub = null;
        RecordCursor cur;
        while ((cur = source.next()) != null) {
            addSubInternal(cur);
        }
    }

    @Override
    public void close() {
    // nothing to do here
    }

    @Override
    public void closeAndExamineDataBySubscription(RecordSink sink) {
    // nothing to do here
    }

    @Override
    public QDStats getStats() {
        // never keeps stats
        return QDStats.VOID;
    }

    @Override
    public boolean isSubscribed(DataRecord record, int cipher, String symbol, long time) {
        SubMatrix sub = this.sub;
        if (sub == null)
            return false;
        int key = getKey(sub, cipher, symbol);
        int rid = record.getId();
        int index = sub.getVolatileIndex(key, rid, 0);
        /*
           Potential word-tearing in getLong if subscription time is changed concurrently with this isSub
           invocation, but we cannot really do anything about it.
         */
        return sub.isPayload(index) && (contract != QDContract.HISTORY || time >= sub.getLong(index + VOID_TIME_SUB));
    }

    @Override
    public boolean examineSubscription(RecordSink sink) {
        SubMatrix sub = this.sub;
        return sub != null && new SubSnapshot(sub, VOID_TIME_SUB, contract, QDFilter.ANYTHING, this).retrieveSubscription(sink);
    }

    @Override
    public synchronized int getSubscriptionSize() {
        SubMatrix sub = this.sub;
        return sub == null ? 0 : sub.payloadSize;
    }

    @Override
    public DataRecord getRecord(int rid) {
        return scheme.getRecord(rid);
    }

    private int getRid(DataRecord record) {
        if (record.getScheme() != scheme)
            throw new IllegalArgumentException("Wrong record scheme: " + record);
        return record.getId();
    }

    private int addKey(SubMatrix sub, int cipher, String symbol) {
        if ((cipher & SymbolCodec.VALID_CIPHER) == 0) {
            if (cipher != 0)
                throw new IllegalArgumentException("Reserved cipher");
            return sub.mapper.addKey(symbol);
        }
        return cipher;
    }

    private int getKey(SubMatrix sub, int cipher, String symbol) {
        if ((cipher & SymbolCodec.VALID_CIPHER) == 0) {
            if (cipher != 0)
                throw new IllegalArgumentException("Reserved cipher");
            return sub.mapper.getMapping().getKey(symbol);
        }
        return cipher;
    }

    private void addSubInternal(RecordCursor cur) {
        PayloadBitsSubMatrix sub = getOrCreateSub();
        if (needsRehash(sub))
            sub = rehash(sub);
        int key = addKey(sub, cur.getCipher(), cur.getSymbol());
        int rid = getRid(cur.getRecord());
        int index = sub.addIndex(key, rid);
        sub.markPayload(index);
        if (hasAttachmentStrategy())
            sub.setObj(index, ATTACHMENT, updateAttachment(sub.getObj(index, ATTACHMENT), cur, false));
        if (contract == QDContract.HISTORY)
            sub.setLong(index + VOID_TIME_SUB, cur.getTime());
    }

    private void removeSubInternal(RecordCursor cur) {
        PayloadBitsSubMatrix sub = getOrCreateSub();
        int key = getKey(sub, cur.getCipher(), cur.getSymbol());
        int rid = getRid(cur.getRecord());
        int index = sub.getIndex(key, rid, 0);
        if (index == 0 || !sub.isPayload(index))
            // not subscribed
            return;
        if (hasAttachmentStrategy()) {
            Object attachment = updateAttachment(sub.getObj(index, ATTACHMENT), cur, true);
            sub.setObj(index, ATTACHMENT, attachment);
            if (// don't actually remove, but adjust attachment and return
            attachment != null)
                return;
        }
        sub.clearPayload(index);
    }

    private boolean needsRehash(PayloadBitsSubMatrix sub) {
        return Hashing.needRehash(sub.shift, sub.overallSize, sub.payloadSize, Hashing.MAX_SHIFT);
    }

    private PayloadBitsSubMatrix rehash(PayloadBitsSubMatrix sub) {
        return this.sub = sub.rehash(Hashing.MAX_SHIFT);
    }

    private PayloadBitsSubMatrix getOrCreateSub() {
        PayloadBitsSubMatrix sub = this.sub;
        if (sub != null)
            return sub;
        Mapper mapper = new Mapper(this);
        // at most one per record forever
        mapper.incMaxCounter(scheme.getRecordCount());
        sub = new PayloadBitsSubMatrix(mapper, contract == QDContract.HISTORY ? HISTORY_STEP : STEP, hasAttachmentStrategy() ? 0 : 1, 0, 0, Hashing.MAX_SHIFT);
        this.sub = sub;
        return sub;
    }

    private static clreplaced PayloadBitsSubMatrix extends SubMatrix {

        private final PayloadBits payloadBits;

        private PayloadBitsSubMatrix(Mapper mapper, int step, int objStep, int capacity, int prevMagic, int maxShift) {
            // preplaced payloadOffset == Integer.MAX_VALUE. It should not be used (isPayload is overridden!) and must fail if used
            super(mapper, step, objStep, Integer.MAX_VALUE, capacity, prevMagic, maxShift, QDStats.VOID);
            payloadBits = new PayloadBits(matrix.length, step);
        }

        @Override
        PayloadBitsSubMatrix rehash(int maxShift) {
            PayloadBitsSubMatrix dest = new PayloadBitsSubMatrix(mapper, step, obj_step, payloadSize, magic, maxShift);
            rehashTo(dest);
            return dest;
        }

        @Override
        boolean isPayload(int index) {
            return payloadBits.isPayload(index);
        }

        @Override
        void markPayload(int index) {
            if (payloadBits.markPayload(index))
                updateAddedPayload();
        }

        void clearPayload(int index) {
            if (payloadBits.clearPayload(index)) {
                updateRemovedPayload();
                clearIndexData(index, 2);
            }
        }
    }
}

19 Source : SubSnapshot.java
with Mozilla Public License 2.0
from devexperts

/**
 * Represents weakly-consistent snapshot of subscription for non-globally-synchronized retrieval.
 */
final clreplaced SubSnapshot {

    private final SubMatrix sub;

    private final int timeOffset;

    private final QDContract contract;

    // @NotNull
    private final QDFilter filter;

    private final RecordsContainer records;

    // current state
    private int index;

    /**
     * Constructs snapshot for an agent, including total agent.
     */
    // SYNC: none
    SubSnapshot(Agent agent, QDFilter filter) {
        this(agent.sub, agent == agent.collector.total ? Collector.TIME_TOTAL : Collector.TIME_SUB, agent.collector.getContract(), filter, agent.collector);
    }

    // SYNC: none
    SubSnapshot(SubMatrix sub, int timeOffset, QDContract contract, QDFilter filter, RecordsContainer records) {
        this.sub = sub;
        this.timeOffset = timeOffset;
        this.contract = contract;
        this.filter = filter;
        this.records = records;
        index = sub.matrix.length;
    }

    /**
     * Retrieves a portion of subscription snapshot into the specified subscription visitor.
     * Returns true if some subscription still remains in this snapshot
     * or false if everything was retrieved.
     */
    // SYNC: none
    synchronized boolean retrieveSubscription(RecordSink sink) {
        if (index <= 0)
            return false;
        int nExaminedInBatch = 0;
        while ((index -= sub.step) > 0) {
            /*
               Payload check is racy, but it is ok for our weak-consistency guarantees.
               There is a volatile read of sub in SubSnapshot constructor, thus
               any index that was payload before payload was constructed and remained payload
               during retrieval will be detected as payload here. If the index is in/out of
               payload during retrieval we don't really care what this check returns.
             */
            if (!sub.isSubscribed(index))
                continue;
            /*
               Volatile read of KEY guarantees that (key,rid,time) tuple will be
               read consistently for newly added items, since KEY is initialized via
               setVolatileInt at the end of a new subscription item creation.
             */
            int key = sub.getVolatileInt(index + Collector.KEY);
            if (key == 0)
                // this can happen due to a race in isPayload check
                continue;
            int rid = sub.getInt(index + Collector.RID);
            /*
               Time can change during subscription snapshot retrieval, so there is
               a potential of word-tearing for getLong operation. We cannot do anything
               about it. The only consolation is that time is word-teared if and only if
               subscription is changed after the snapshot is taken, thus distributor will
               record a proper time in its added_subscription set.
             */
            long time = contract == QDContract.HISTORY ? sub.getLong(index + timeOffset) : 0;
            int cipher = key;
            String symbol = null;
            if ((key & SymbolCodec.VALID_CIPHER) == 0) {
                cipher = 0;
                // do not cache mapping to see concurrent mapping rehash
                symbol = sub.getMapping().getSymbolIfPresent(key);
                if (symbol == null)
                    // not found -- was just added, but we don't "see" its mapping (mapping was rehashed, or...)
                    continue;
            }
            DataRecord record = records.getRecord(rid);
            if (!filter.accept(contract, record, cipher, symbol))
                continue;
            if (!sink.hasCapacity()) {
                // step back so that we re-visit this record again later
                index += sub.step;
                break;
            }
            sink.visitRecord(record, cipher, symbol, time);
            nExaminedInBatch++;
            if (nExaminedInBatch >= Collector.EXAMINE_BATCH_SIZE) {
                sink.flush();
                nExaminedInBatch = 0;
            }
        }
        if (nExaminedInBatch > 0)
            sink.flush();
        return index > 0;
    }
}

19 Source : MatrixFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDCollector.Builder<?> collectorBuilder(QDContract contract) {
    return new AbstractCollectorBuilder(contract) {

        @Override
        public QDCollector build() {
            switch(contract) {
                case TICKER:
                    return new Ticker(this);
                case STREAM:
                    return new Stream(this);
                case HISTORY:
                    return new History(this);
                default:
                    throw new IllegalArgumentException();
            }
        }
    };
}

19 Source : MatrixFactory.java
with Mozilla Public License 2.0
from devexperts

@Override
public QDAgent.Builder createVoidAgentBuilder(QDContract contract, DataScheme scheme) {
    return new VoidAgentBuilder(contract, scheme);
}

19 Source : CollectorManagement.java
with Mozilla Public License 2.0
from devexperts

// --- static factory method ---
public static CollectorManagement getInstance(DataScheme scheme, QDContract contract, String keyProperties) {
    return FACTORY == null ? new CollectorManagement(scheme, contract) : FACTORY.getInstance(scheme, contract, keyProperties);
}

19 Source : AbstractCollectorBuilder.java
with Mozilla Public License 2.0
from devexperts

public abstract clreplaced AbstractCollectorBuilder<T extends QDCollector> implements QDCollector.Builder<T> {

    private final QDContract contract;

    private DataScheme scheme;

    private QDStats stats;

    private HistorySubscriptionFilter historyFilter;

    private boolean withEventTimeSequence;

    protected AbstractCollectorBuilder(QDContract contract) {
        this.contract = contract;
    }

    @Override
    public abstract T build();

    @Override
    public QDCollector.Builder<T> copyFrom(QDCollector.Builder<?> other) {
        scheme = other.getScheme();
        stats = other.getStats();
        historyFilter = other.getHistoryFilter();
        withEventTimeSequence = other.hasEventTimeSequence();
        return this;
    }

    @Override
    public final QDContract getContract() {
        return contract;
    }

    @Override
    public final QDCollector.Builder<T> withScheme(DataScheme scheme) {
        this.scheme = scheme;
        return this;
    }

    @Override
    public final DataScheme getScheme() {
        if (scheme == null)
            return QDFactory.getDefaultScheme();
        return scheme;
    }

    @Override
    public final QDCollector.Builder<T> withStats(QDStats stats) {
        this.stats = stats;
        return this;
    }

    @Override
    public final QDStats getStats() {
        if (stats == null)
            stats = QDFactory.createStats(contract.getStatsType(), getScheme());
        return stats;
    }

    @Override
    public final QDCollector.Builder<T> withHistoryFilter(HistorySubscriptionFilter historyFilter) {
        this.historyFilter = historyFilter;
        return this;
    }

    @Override
    public final HistorySubscriptionFilter getHistoryFilter() {
        return historyFilter;
    }

    @Override
    public QDCollector.Builder<T> withEventTimeSequence(boolean value) {
        this.withEventTimeSequence = value;
        return this;
    }

    @Override
    public boolean hasEventTimeSequence() {
        return withEventTimeSequence;
    }
}

19 Source : AbstractCollector.java
with Mozilla Public License 2.0
from devexperts

public abstract clreplaced AbstractCollector implements QDCollector {

    protected final QDContract contract;

    private final QDAgent.Builder agentBuilder;

    private final DistributorBuilder distributorBuilder = new DistributorBuilder();

    private final boolean withEventTimeSequence;

    protected AbstractCollector(Builder<?> builder) {
        this.contract = builder.getContract();
        this.withEventTimeSequence = builder.hasEventTimeSequence();
        this.agentBuilder = new AgentBuilder().withEventTimeSequence(withEventTimeSequence);
    }

    @Override
    public final QDContract getContract() {
        return contract;
    }

    @Override
    public final QDAgent.Builder agentBuilder() {
        return agentBuilder;
    }

    @Override
    public final QDAgent createAgent(SubscriptionFilter filter) {
        return agentBuilder.withFilter(QDFilter.fromFilter(filter, getScheme())).build();
    }

    @Override
    public final QDAgent createAgent(SubscriptionFilter filter, String keyProperties) {
        return agentBuilder.withFilter(QDFilter.fromFilter(filter, getScheme())).withKeyProperties(keyProperties).build();
    }

    @Override
    public final QDDistributor.Builder distributorBuilder() {
        return distributorBuilder;
    }

    @Override
    public final QDDistributor createDistributor(SubscriptionFilter filter) {
        return distributorBuilder.withFilter(QDFilter.fromFilter(filter, getScheme())).build();
    }

    @Override
    public final QDDistributor createDistributor(SubscriptionFilter filter, String keyProperties) {
        return distributorBuilder.withFilter(QDFilter.fromFilter(filter, getScheme())).withKeyProperties(keyProperties).build();
    }

    @Override
    public String getSymbol(char[] chars, int offset, int length) {
        return null;
    }

    @Override
    public final boolean examineData(DataVisitor visitor) {
        return examineData(LegacyAdapter.of(visitor));
    }

    @Override
    public final boolean examineSubscription(SubscriptionVisitor visitor) {
        return examineSubscription(LegacyAdapter.of(visitor));
    }

    @Override
    public boolean examineData(RecordSink sink) {
        return false;
    }

    @Override
    public boolean examineDataBySubscription(RecordSink sink, RecordSource sub) {
        return false;
    }

    @Override
    public void remove(RecordSource source) {
    // do nothing by default
    }

    @Override
    public boolean hasEventTimeSequence() {
        return withEventTimeSequence;
    }

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

    @Override
    public void setStoreEverything(boolean storeEverything) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setStoreEverythingFilter(SubscriptionFilter filter) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void executeLockBoundTask(Executor executor, Runnable task) {
        // no support for cooperation on lock-bound tasks by default in this abstract implementation
        executor.execute(task);
    }

    @Override
    public abstract QDAgent buildAgent(QDAgent.Builder builder);

    @Override
    public abstract QDDistributor buildDistributor(QDDistributor.Builder builder);

    public clreplaced AgentBuilder extends AbstractAgentBuilder {

        @Override
        public QDAgent build() {
            return buildAgent(this);
        }
    }

    public clreplaced DistributorBuilder extends AbstractBuilder<QDDistributor.Builder, DistributorBuilder> implements QDDistributor.Builder {

        @Override
        public QDDistributor build() {
            return buildDistributor(this);
        }

        @Override
        public String toString() {
            return "DistributorBuilder{" + super.toString() + '}';
        }
    }
}

19 Source : DelegateGen.java
with Mozilla Public License 2.0
from devexperts

DelegateGen subContract(QDContract contract) {
    this.subContract = contract;
    return this;
}

18 Source : CollectorManagementImplOneContract.java
with Mozilla Public License 2.0
from devexperts

public static synchronized CollectorManagementImplOneContract getInstance(DataScheme scheme, QDContract contract, String keyProperties) {
    String name = getBeanName(scheme, contract, keyProperties);
    CollectorManagementImplOneContract management = INSTANCES.get(name);
    if (management != null)
        return management;
    management = new CollectorManagementImplOneContract(scheme, contract, keyProperties, name);
    INSTANCES.put(name, management);
    return management;
}

18 Source : SubscriptionAdapter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean isProtocolDescriptorCompatible(ProtocolDescriptor desc) {
    for (QDContract contract : getEndpoint().getContracts()) if (desc.canSend(MessageType.forAddSubscription(contract)))
        return true;
    return false;
}

18 Source : QDEndpoint.java
with Mozilla Public License 2.0
from devexperts

public QDCollector getCollector(QDContract contract) {
    return collectors.get(contract);
}

18 Source : DistributorAdapter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean isProtocolDescriptorCompatible(ProtocolDescriptor desc) {
    for (QDContract contract : QD_CONTRACTS) if (collectors[contract.ordinal()] != null && (desc.canReceive(MessageType.forAddSubscription(contract)) || desc.canSend(MessageType.forData(contract)) || desc.canSend(MessageType.RAW_DATA))) {
        return true;
    }
    return false;
}

18 Source : ChannelShaper.java
with Mozilla Public License 2.0
from devexperts

/**
 * This clreplaced represents configuration of a single data channel within {@link AgentAdapter}.
 * It includes contract, collector, keep rejected flag, subscription filter, data filter, relative weight,
 * and aggregation period.
 * Each channel may specify executor to be used for subscription processing (i.e. filtering) -
 * it is required when subscription filtering is a heavy operation (e.g. requires database access).
 *
 * <p> Channel may change its parameters except for contract, subscription executor, and keep reject flag,
 * to new values anytime.
 * The changes of data filter, weight or aggregation period are immediately effective
 * and do not require re-creation of agent (i.e. no interruption of data stream happens).
 * The changes of collector or subscription filter require re-creation of agent which
 * result with brief data stream interruption. The re-creation of agent will happen
 * upon data or subscription message processing; it can be forced via invocation of
 * {@link AgentAdapter#updateChannel} method.
 */
public clreplaced ChannelShaper implements Cloneable {

    // fixed on creation
    private final QDContract contract;

    // fixed on creation
    private final Executor subscriptionExecutor;

    // fixed on creation
    private final boolean keepRejected;

    // set only once after creation in "bind" method
    private volatile AgentChannel channel;

    private volatile QDCollector collector;

    // non-null
    private volatile QDFilter subscriptionFilter = QDFilter.ANYTHING;

    private volatile RecordFilter dataFilter;

    private volatile int weight = 1;

    private volatile long aggregationPeriod;

    /**
     * Creates new channel shaper with specified contract and subscription executor.
     * This channel shaper does not keep subscription rejected by a filter.
     *
     * @param contract channel contract; may not be {@code null}
     * @param subscriptionExecutor subscription executor; may be {@code null}
     * @throws NullPointerException if {@code contract} is {@code null}
     */
    public ChannelShaper(QDContract contract, Executor subscriptionExecutor) {
        this(contract, subscriptionExecutor, false);
    }

    /**
     * Creates new channel shaper with specified contract, subscription executor,
     * and keep rejected flag.
     *
     * @param contract channel contract; may not be {@code null}
     * @param subscriptionExecutor subscription executor; may be {@code null}
     * @param keepRejected {@code true} when rejected subscription elements shall be kept for future changes of filter.
     * @throws NullPointerException if {@code contract} is {@code null}
     */
    public ChannelShaper(QDContract contract, Executor subscriptionExecutor, boolean keepRejected) {
        if (contract == null)
            throw new NullPointerException();
        this.contract = contract;
        this.subscriptionExecutor = subscriptionExecutor;
        this.keepRejected = keepRejected;
    }

    /**
     * Creates new channel shaper with specified parameters.
     * All initialization parameters except for collector may be {@code null}.
     *
     * @param subscriptionExecutor subscription executor; may be {@code null}
     * @param collector channel collector; may not be {@code null}
     * @param subscriptionFilter subscription filter; may be {@code null}
     * @param dataFilter data filter; may be {@code null}
     * @throws NullPointerException if {@code collector} is {@code null}
     * @deprecated Use {@link #ChannelShaper(QDContract, Executor)} and {@link #setCollector(QDCollector)},
     * {@link #setSubscriptionFilter(QDFilter)}, {@link #setDataFilter(RecordFilter)}
     */
    public ChannelShaper(Executor subscriptionExecutor, QDCollector collector, SubscriptionFilter subscriptionFilter, RecordFilter dataFilter) {
        this(collector.getContract(), subscriptionExecutor);
        setCollector(collector);
        setSubscriptionFilter(subscriptionFilter);
        setDataFilter(dataFilter);
    }

    /**
     * Binds this channel to the specified agent adapter.
     * @param channel agent channel.
     */
    synchronized void bind(AgentChannel channel) {
        if (this.channel != null)
            throw new IllegalStateException("Already bound");
        if (channel == null)
            throw new NullPointerException();
        this.channel = channel;
    }

    /**
     * Closes this channel shaper and releases its resources (stops tracking dynamic filters).
     */
    public void close() {
    }

    @Override
    public ChannelShaper clone() {
        try {
            ChannelShaper clone = (ChannelShaper) super.clone();
            if (clone.channel != null)
                throw new IllegalStateException("Cannot clone bound channel");
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new replacedertionError(e);
        }
    }

    /**
     * Returns contract of the channel.
     * <b>This property is fixed for a given channel.</b>
     *
     * @return channel contract
     */
    public QDContract getContract() {
        return contract;
    }

    /**
     * Returns {@code true} if there is an executor for subscription processing.
     * <b>This property is fixed for a given channel.</b>
     *
     * @return {@code true} if there is an executor for subscription processing.
     */
    public boolean hreplacedubscriptionExecutor() {
        return subscriptionExecutor != null;
    }

    /**
     * Returns executor for subscription processing used by the channel
     * or {@code null} if none specified.
     * <b>This property is fixed for a given channel.</b>
     *
     * @return subscription executor or {@code null}
     */
    public Executor getSubscriptionExecutor() {
        return subscriptionExecutor;
    }

    /**
     * Returns {@code true} when subscription rejected by this channel's filter is kept for
     * the case of future changes of subscription filter.
     * <b>This property is fixed for a given channel.</b>
     */
    public boolean isKeepRejected() {
        return keepRejected;
    }

    /**
     * Returns collector currently used by the channel.
     *
     * @return channel collector or {@code null}
     */
    public final QDCollector getCollector() {
        return collector;
    }

    /**
     * Sets collector for the channel. The contract of collector must match the contract of this channel.
     * The collector may be {@code null} in which case no agent will be created for the channel.
     * Change of collector will trigger re-creation of agent.
     *
     * @param collector channel collector; may be {@code null}
     */
    public void setCollector(QDCollector collector) {
        if (collector != null && collector.getContract() != contract)
            throw new IllegalArgumentException("Wrong contract");
        this.collector = collector;
        reconfigureIfNeeded();
    }

    /**
     * Returns subscription filter currently used by the channel.
     *
     * @return subscription filter currently used by the channel (non-null).
     */
    public final QDFilter getSubscriptionFilter() {
        return subscriptionFilter;
    }

    /**
     * Sets subscription filter for the channel.
     * The subscription filter may be {@code null} in which case all subscription will be accepted.
     * Change of subscription filter will trigger re-creation of agent.
     *
     * @param subscriptionFilter subscription filter; may be {@code null}
     * @deprecated Use {@link #setSubscriptionFilter(QDFilter)}
     *   that accepts non-null {@link QDFilter} instance which replaces legacy {@link SubscriptionFilter}.
     */
    public void setSubscriptionFilter(SubscriptionFilter subscriptionFilter) {
        setSubscriptionFilter(QDFilter.fromFilter(subscriptionFilter, collector == null ? null : collector.getScheme()));
    }

    /**
     * Sets subscription filter for the channel.
     * Use {@link QDFilter#ANYTHING} to accept any subscription.
     * Change of subscription filter will trigger re-creation of agent.
     *
     * @param subscriptionFilter subscription filter;
     *              may be {@code null} for backwards-compatibility (it is replaced with {@link QDFilter#ANYTHING})
     */
    public void setSubscriptionFilter(QDFilter subscriptionFilter) {
        if (subscriptionFilter == null)
            subscriptionFilter = QDFilter.ANYTHING;
        boolean updated = false;
        synchronized (this) {
            if (this.subscriptionFilter != subscriptionFilter) {
                this.subscriptionFilter = subscriptionFilter;
                updated = true;
            }
        }
        if (updated)
            reconfigureIfNeeded();
    }

    /**
     * Returns data filter currently used by the channel.
     *
     * @return data filter or {@code null}
     */
    public RecordFilter getDataFilter() {
        return dataFilter;
    }

    /**
     * Sets data filter for the channel.
     * The data filter may be {@code null} in which case all data will be accepted.
     * Change of data filter is immediate and will not trigger re-creation of agent.
     *
     * @param dataFilter data filter; may be {@code null}
     */
    public void setDataFilter(RecordFilter dataFilter) {
        this.dataFilter = dataFilter;
        reconfigureIfNeeded();
    }

    /**
     * Returns relative weight of this channel data within the adapter for shaping.
     *
     * @return relative weight of this channel data
     */
    public int getWeight() {
        return weight;
    }

    /**
     * Sets relative weight of this channel data within the adapter for shaping.
     * The weight must be between 1 and 100 inclusive.
     * Change of weight is immediate and will not trigger re-creation of agent.
     *
     * @param weight relative weight
     * @throws IllegalArgumentException if weight is less than 1 or greater than 100.
     */
    public void setWeight(int weight) {
        if (weight < 1 || weight > 100)
            throw new IllegalArgumentException("Weight is out of limits: " + weight);
        this.weight = weight;
    // no need to reconfigure on changing weight -- it is not part of configuration, but is used during
    // data retrieval only to compute quotas
    }

    /**
     * Returns aggregation period in milliseconds for this channel data.
     *
     * @return aggregation period in milliseconds
     */
    public long getAggregationPeriod() {
        return aggregationPeriod;
    }

    /**
     * Sets aggregation period for this channel data.
     * The aggregation period must be non-negative and must not exceed 24 hours.
     * Change of aggregation period is immediate and will not trigger re-creation of agent.
     *
     * @param aggregationPeriod in milliseconds
     * @throws IllegalArgumentException if aggregation period is negative or greater than 24 hours.
     */
    public void setAggregationPeriod(long aggregationPeriod) {
        if (aggregationPeriod < 0 || aggregationPeriod > 24 * 3600 * 1000)
            throw new IllegalArgumentException("Aggregation period is out of limits: " + aggregationPeriod);
        this.aggregationPeriod = aggregationPeriod;
        reconfigureIfNeeded();
    }

    private void reconfigureIfNeeded() {
        // atomic read
        AgentChannel channel = this.channel;
        if (channel != null)
            channel.reconfigureIfNeeded();
    }
}

18 Source : ChannelDescription.java
with Mozilla Public License 2.0
from devexperts

/**
 * Description of a single channel.
 * The format is: {@code [<filter>'&']<contract>['@'<aggregationPeriod>]['['<key>'='<value>','...']']}.
 * Filter is replacedumed to include anything by default, and default aggregation period is set
 * with {@code aggregationPeriod}.
 */
public clreplaced ChannelDescription {

    final String filterStr;

    final QDContract contract;

    final TimePeriod aggregationPeriod;

    final List<String> properties = new ArrayList<>();

    final String channel;

    public ChannelDescription(String channel) {
        this.channel = channel;
        channel = QDConfig.parseProperties(channel, properties);
        String[] timeSplit = QDConfig.splitParenthesisedStringAt(channel, '@');
        String filterContract = timeSplit.length == 1 ? channel : timeSplit[0];
        aggregationPeriod = timeSplit.length == 1 ? null : TimePeriod.valueOf(timeSplit[1]);
        int i = filterContract.lastIndexOf('&');
        filterStr = i < 0 ? null : filterContract.substring(0, i);
        String contractStr = i < 0 ? filterContract : filterContract.substring(i + 1);
        try {
            contract = QDContract.valueOf(contractStr.toUpperCase(Locale.US));
        } catch (IllegalArgumentException e) {
            throw new InvalidFormatException("Invalid contract name: " + contractStr, e);
        }
    }

    @Override
    public String toString() {
        return channel;
    }
}

18 Source : AgentAdapter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean isProtocolDescriptorCompatible(ProtocolDescriptor desc) {
    if (shapers == null)
        return true;
    for (QDContract contract : QD_CONTRACTS) {
        boolean hasContract = false;
        for (ChannelShaper shaper : shapers) {
            if (shaper.getContract() != contract)
                continue;
            hasContract = true;
        }
        if (hasContract && desc.canSend(MessageType.forAddSubscription(contract)) && desc.canReceive(MessageType.forData(contract)))
            return true;
    }
    return false;
}

18 Source : SymbolSetFilter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean accept(QDContract contract, DataRecord record, int cipher, String symbol) {
    if (cipher == wildcard)
        return true;
    return negated ^ set.contains(cipher, symbol);
}

18 Source : RecordOnlyFilter.java
with Mozilla Public License 2.0
from devexperts

@Override
public final boolean accept(QDContract contract, DataRecord record, int cipher, String symbol) {
    return acceptRecord(record);
}

18 Source : PatternFilter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean accept(QDContract contract, DataRecord record, int cipher, String symbol) {
    DataScheme scheme = getScheme();
    if (scheme == null)
        // for backwards compatibility
        scheme = record.getScheme();
    if (cipher == scheme.getCodec().getWildcardCipher())
        return true;
    if (// String symbol is specified
    symbol != null)
        return negated ^ acceptString(symbol);
    // Only cipher is specified
    return negated ^ acceptCode(scheme.getCodec().decodeToLong(cipher));
}

18 Source : NotFilter.java
with Mozilla Public License 2.0
from devexperts

@Override
public boolean accept(QDContract contract, DataRecord record, int cipher, String symbol) {
    DataScheme scheme = getScheme();
    if (scheme == null)
        // for backwards compatibility
        scheme = record.getScheme();
    // TODO the below code incorrectly preplacedes wildcard disregarding other criteria like contract or record
    // TODO refactor with explicit split of all filters into individual single criteria filters plus expressions
    if (cipher == scheme.getCodec().getWildcardCipher())
        return true;
    return !delegate.accept(contract, record, cipher, symbol);
}

18 Source : CollectorManagement.java
with Mozilla Public License 2.0
from devexperts

public clreplaced CollectorManagement {

    protected static final Logging log = Logging.getLogging(CollectorManagement.clreplaced);

    private static final CollectorManagementFactory FACTORY = Services.createService(CollectorManagementFactory.clreplaced, null, null);

    public static final int DEFAULT_SUBSCRIPTION_BUCKET = 10000;

    public static final int DEFAULT_DISTRIBUTION_BUCKET = 100000;

    public static final int DEFAULT_INTERLEAVE = 4;

    public static final int DEFAULT_AGENT_BUFFER_SIZE_DEFAULT = // default size of agent buffer, legacy property name
    SystemProperties.getIntProperty("com.devexperts.qd.impl.matrix.Agent.MaxBufferSize", 1000000);

    public static final int DEFAULT_MAX_DISTRIBUTION_SPINS = 8;

    public static final String DEFAULT_BUFFER_OVERFLOW_LOG_INTERVAL = "10s";

    public static final String DEFAULT_LOCK_WAIT_LOG_INTERVAL = "10s";

    public static final String DEFAULT_USE_LOCK_PRIORITY = ".*Data";

    // Note: It has different default in sever-side implementation with monitoring.
    public static final String DEFAULT_USE_LOCK_COUNTERS = "";

    // --- static factory method ---
    public static CollectorManagement getInstance(DataScheme scheme, QDContract contract, String keyProperties) {
        return FACTORY == null ? new CollectorManagement(scheme, contract) : FACTORY.getInstance(scheme, contract, keyProperties);
    }

    // --- instance fields ---
    protected final DataScheme scheme;

    protected final QDContract contract;

    // Maximum number of records per subscription change.
    protected int subscriptionBucket = DEFAULT_SUBSCRIPTION_BUCKET;

    // Maximum number of records per distribution.
    protected int distributionBucket = DEFAULT_DISTRIBUTION_BUCKET;

    // interleaved distributions
    protected int interleave = DEFAULT_INTERLEAVE;

    protected int agentBufferSizeDefault = DEFAULT_AGENT_BUFFER_SIZE_DEFAULT;

    // max number of tryLock spins in retrieveData
    protected int maxDistributionSpins = DEFAULT_MAX_DISTRIBUTION_SPINS;

    // interval between logs about dropped records
    protected TimePeriod bufferOverflowLogInterval = TimePeriod.valueOf(DEFAULT_BUFFER_OVERFLOW_LOG_INTERVAL);

    // interval to wait before logging that wait takes too long
    protected TimePeriod lockWaitLogInterval = TimePeriod.valueOf(DEFAULT_LOCK_WAIT_LOG_INTERVAL);

    protected OperationSet useLockPriority = new OperationSet(DEFAULT_USE_LOCK_PRIORITY);

    // don't do lock counters by default
    protected OperationSet useLockCounters = new OperationSet(DEFAULT_USE_LOCK_COUNTERS);

    // --- instance constructor & methods ---
    protected CollectorManagement(DataScheme scheme, QDContract contract) {
        this.scheme = scheme;
        this.contract = contract;
    }

    public QDContract getContract() {
        return contract;
    }

    public int getSubscriptionBucket() {
        return subscriptionBucket;
    }

    public int getDistributionBucket() {
        return distributionBucket;
    }

    public int getInterleave() {
        if (contract != QDContract.TICKER)
            throw new UnsupportedOperationException("Interleave is not supported");
        return interleave;
    }

    public int getAgentBufferSizeDefault() {
        if (contract == QDContract.TICKER)
            throw new UnsupportedOperationException("AgentBufferSizeDefault is not supported");
        return agentBufferSizeDefault;
    }

    public int getMaxDistributionSpins() {
        return maxDistributionSpins;
    }

    public long getBufferOverflowLogIntervalSeconds() {
        return TimeUnit.MILLISECONDS.toSeconds(bufferOverflowLogInterval.getTime());
    }

    public long getLockWaitLogIntervalNanos() {
        return TimeUnit.MILLISECONDS.toNanos(lockWaitLogInterval.getTime());
    }

    public boolean useLockPriority(CollectorOperation op) {
        return useLockPriority.set.contains(op);
    }

    public boolean useLockCounters(CollectorOperation op) {
        return useLockCounters.set.contains(op);
    }

    // impl overrides
    public CollectorCounters createCounters() {
        return new CollectorCounters();
    }

    public void addCollector(Collector collector) {
    // impl overrides
    }

    public void removeCollector(Collector collector) {
    // impl overrides
    }

    public void setFatalError(Throwable error) {
    // impl overrides
    }

    protected static clreplaced OperationSet {

        final String string;

        final EnumSet<CollectorOperation> set = EnumSet.noneOf(CollectorOperation.clreplaced);

        public OperationSet(String string) {
            this.string = string;
            Pattern pattern = Pattern.compile(string);
            for (CollectorOperation op : CollectorOperation.values()) if (pattern.matcher(op.toString()).matches())
                set.add(op);
        }

        public String toString() {
            return string;
        }
    }
}

18 Source : EventDelegate.java
with Mozilla Public License 2.0
from devexperts

public abstract clreplaced EventDelegate<T extends EventType<?>> {

    protected final DataRecord record;

    protected final QDContract contract;

    protected final boolean sub;

    protected final boolean pub;

    protected final boolean timeSeries;

    protected final boolean wildcard;

    protected final SymbolCodec codec;

    protected final Clreplaced<T> eventType;

    protected final boolean lastingEvent;

    @SuppressWarnings("unchecked")
    protected EventDelegate(DataRecord record, QDContract contract, EnumSet<EventDelegateFlags> flags) {
        this.record = record;
        this.contract = contract;
        this.sub = flags.contains(EventDelegateFlags.SUB);
        this.pub = flags.contains(EventDelegateFlags.PUB);
        this.timeSeries = flags.contains(EventDelegateFlags.TIME_SERIES);
        this.wildcard = flags.contains(EventDelegateFlags.WILDCARD);
        this.codec = record.getScheme().getCodec();
        this.eventType = (Clreplaced<T>) createEvent().getClreplaced();
        boolean timeSeriesEvent = TimeSeriesEvent.clreplaced.isreplacedignableFrom(eventType);
        if (timeSeries && !timeSeriesEvent)
            throw new IllegalArgumentException("Cannot create time series delegate for non time series event " + eventType);
        this.lastingEvent = LastingEvent.clreplaced.isreplacedignableFrom(eventType);
    }

    public final Clreplaced<T> getEventType() {
        return eventType;
    }

    public final DataRecord getRecord() {
        return record;
    }

    public final QDContract getContract() {
        return contract;
    }

    public final boolean isSub() {
        return sub;
    }

    public boolean isPub() {
        return pub;
    }

    public final boolean isTimeSeries() {
        return timeSeries;
    }

    public boolean isWildcard() {
        return wildcard;
    }

    public final boolean isLastingEvent() {
        return lastingEvent;
    }

    public EventDelegateSet<T, ? extends EventDelegate<T>> createDelegateSet() {
        return new EventDelegateSet<>(eventType);
    }

    // Works on string symbols, too, so DelegateSet.convertSymbol call is optional
    public String getQDSymbolByEventSymbol(Object symbol) {
        return getMapping().getQDSymbolByEventSymbol(symbol);
    }

    public Object getEventSymbolByQDSymbol(String qdSymbol) {
        return getMapping().getEventSymbolByQDSymbol(qdSymbol);
    }

    public long getQDTimeByEventTime(long time) {
        return time == Long.MAX_VALUE ? Long.MAX_VALUE : TimeSequenceUtil.getTimeSequenceFromTimeMillis(time);
    }

    public long getEventTimeByQDTime(long time) {
        return time == Long.MAX_VALUE ? Long.MAX_VALUE : TimeSequenceUtil.getTimeMillisFromTimeSequence(time);
    }

    public long getFetchTimeHeuristicByEventSymbolAndFromTime(Object eventSymbol, long fromTime) {
        Timing.Day day = Timing.EST.getByTime(fromTime);
        do {
            // prev day
            day = Timing.EST.getById(day.day_id - 1);
        } while (!day.isTrading());
        // start of previous trading day
        return day.day_start;
    }

    public String getQDSymbolByEvent(T event) {
        return getQDSymbolByEventSymbol(event.getEventSymbol());
    }

    public Object getSubscriptionSymbolByQDSymbolAndTime(String qdSymbol, long time) {
        Object eventSymbol = getEventSymbolByQDSymbol(qdSymbol);
        return timeSeries ? new TimeSeriesSubscriptionSymbol<>(eventSymbol, getEventTimeByQDTime(time)) : eventSymbol;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public T createEvent(Object symbol, RecordCursor cursor) {
        EventType event = createEvent();
        event.setEventSymbol(symbol);
        return getEvent((T) event, cursor);
    }

    public T createEvent(RecordCursor cursor) {
        return createEvent(getEventSymbolByQDSymbol(codec.decode(cursor.getCipher(), cursor.getSymbol())), cursor);
    }

    // ----------------------- must be implemented in subclreplacedes -----------------------
    public abstract RecordMapping getMapping();

    public abstract T createEvent();

    // subclreplacedes override
    public T getEvent(T event, RecordCursor cursor) {
        event.setEventTime(TimeSequenceUtil.getTimeMillisFromTimeSequence(cursor.getEventTimeSequence()));
        return event;
    }

    // ----------------------- must be overridden in publishable subclreplacedes -----------------------
    // subclreplacedes override
    public RecordCursor putEvent(T event, RecordBuffer buf) {
        String symbol = getQDSymbolByEvent(event);
        RecordCursor cursor = buf.add(record, codec.encode(symbol), symbol);
        if (cursor.hasEventTimeSequence())
            cursor.setEventTimeSequence(TimeSequenceUtil.getTimeSequenceFromTimeMillis(event.getEventTime()));
        return cursor;
    }

    @Override
    public String toString() {
        return "EventDelegate{" + "eventType=" + eventType.getName() + ", record=" + record + ", contract=" + contract + ", sub=" + sub + ", pub=" + pub + ", timeSeries=" + timeSeries + ", wildcard=" + wildcard + '}';
    }
}

18 Source : DXEndpointImpl.java
with Mozilla Public License 2.0
from devexperts

public QDCollector getCollector(QDContract contract) {
    return qdEndpoint.getCollector(contract);
}

18 Source : DelegateGen.java
with Mozilla Public License 2.0
from devexperts

/**
 * Generates xxxDelegate clreplacedes for events.
 */
clreplaced DelegateGen {

    private final ClreplacedName clreplacedName;

    private final CodeGenType eventClreplaced;

    private final String eventName;

    private final RecordDesc record;

    private final FactoryImplGen factoryGen;

    private final MappingGen mappingGen;

    private final CodeGenEnvironment env;

    private final List<FieldMapping> fieldMappings = new ArrayList<>();

    private final List<GetPutEventCodeGenerator> codeGenerators = new ArrayList<>();

    private ClreplacedName superDelegateClreplacedName;

    private ClreplacedName innerDelegateClreplacedName;

    private String source;

    private QDContract subContract;

    private boolean publishable;

    DelegateGen(ClreplacedName delegateName, CodeGenType eventClreplaced, RecordDesc record, FactoryImplGen factoryGen, MappingGen mappingGen, CodeGenEnvironment env) {
        this.clreplacedName = delegateName;
        this.eventClreplaced = eventClreplaced;
        this.eventName = eventClreplaced == null ? null : eventClreplaced.getClreplacedName().getSimpleName();
        this.record = record;
        this.factoryGen = factoryGen;
        this.mappingGen = mappingGen;
        this.env = env;
    }

    ClreplacedName getClreplacedName() {
        return clreplacedName;
    }

    Map<QDContract, EnumSet<EventDelegateFlags>> getContractFlags() {
        Map<QDContract, EnumSet<EventDelegateFlags>> result = new EnumMap<>(QDContract.clreplaced);
        boolean lasting = eventClreplaced.isreplacedignableTo(LastingEvent.clreplaced);
        boolean timeSeries = eventClreplaced.isreplacedignableTo(TimeSeriesEvent.clreplaced);
        boolean indexedOnly = !timeSeries && eventClreplaced.isreplacedignableTo(IndexedEvent.clreplaced);
        QDContract primaryContract = subContract != null ? subContract : indexedOnly ? QDContract.HISTORY : lasting || timeSeries ? QDContract.TICKER : QDContract.STREAM;
        EnumSet<EventDelegateFlags> primaryFlags = EnumSet.of(EventDelegateFlags.SUB);
        if (publishable)
            primaryFlags.add(EventDelegateFlags.PUB);
        result.put(primaryContract, primaryFlags);
        if (publishable && primaryContract != QDContract.STREAM)
            result.put(QDContract.STREAM, EnumSet.of(EventDelegateFlags.PUB));
        if (timeSeries && primaryContract != QDContract.HISTORY) {
            EnumSet<EventDelegateFlags> flags = EnumSet.of(EventDelegateFlags.SUB, EventDelegateFlags.TIME_SERIES);
            if (publishable)
                flags.add(EventDelegateFlags.PUB);
            result.put(QDContract.HISTORY, flags);
        }
        // always support wildcard subscription via stream
        if (!result.containsKey(QDContract.STREAM))
            result.put(QDContract.STREAM, EnumSet.noneOf(EventDelegateFlags.clreplaced));
        result.get(QDContract.STREAM).add(EventDelegateFlags.WILDCARD);
        return result;
    }

    DelegateGen suffixes(String suffixesDefault) {
        if (record.regional)
            throw new replacedertionError("Suffixes are not supported for regional records");
        record.suffixesDefault = suffixesDefault;
        return this;
    }

    DelegateGen exchanges(String exchangesDefault, boolean regionalOnly) {
        record.exchangesDefault = exchangesDefault;
        record.regionalOnly = regionalOnly;
        return this;
    }

    DelegateGen inheritDelegateFrom(ClreplacedName superDelegateClreplacedName) {
        this.superDelegateClreplacedName = superDelegateClreplacedName;
        return this;
    }

    DelegateGen innerDelegate(ClreplacedName innerDelegateClreplacedName) {
        this.innerDelegateClreplacedName = innerDelegateClreplacedName;
        return this;
    }

    DelegateGen inheritMappingFrom(ClreplacedName superMappingClreplacedName) {
        mappingGen.inheritMappingFrom(superMappingClreplacedName);
        return this;
    }

    DelegateGen source(String source) {
        this.source = source;
        return this;
    }

    DelegateGen injectGetEventCode(String... code) {
        codeGenerators.add(new GetEventCodeInjection(code));
        return this;
    }

    DelegateGen injectPutEventCode(String... code) {
        codeGenerators.add(new PutEventCodeInjection(code));
        return this;
    }

    DelegateGen replacedign(String property, String value) {
        codeGenerators.add(new Fieldreplacedignment(property, value));
        return this;
    }

    DelegateGen map(String eventPropertyName, String fieldPropertyName, String fieldName, FieldType fieldType) {
        String getterName = Stream.of("get" + eventPropertyName + "AsDouble", "get" + eventPropertyName, "is" + eventPropertyName).filter(name -> eventClreplaced.getMethod(name) != null).findFirst().orElse(null);
        // TODO search for appropriate setter below
        String setterName = getterName == null ? null : getterName.startsWith("get") ? "set" + getterName.substring(3) : getterName.startsWith("is") ? "set" + getterName.substring(2) : null;
        CodeGenType eventPropertyType = getterName != null ? eventClreplaced.getMethod(getterName).getReturnType() : null;
        FieldMapping fieldMapping = new FieldMapping(eventPropertyName, eventPropertyType, new RecordField(fieldPropertyName, eventName, fieldName, fieldType), getterName, setterName);
        fieldMappings.add(fieldMapping);
        codeGenerators.add(fieldMapping);
        factoryGen.addRecordField(record, fieldMapping.field);
        mappingGen.addRecordField(fieldMapping.field);
        return this;
    }

    DelegateGen map(String eventPropertyName, String fieldName, FieldType fieldType) {
        return map(eventPropertyName, eventPropertyName, fieldName, fieldType);
    }

    DelegateGen map(String name, FieldType fieldType) {
        return map(name, name, name, fieldType);
    }

    DelegateGen field(String fieldPropertyName, String fieldName, FieldType fieldType) {
        FieldMapping fieldMapping = new FieldMapping(null, null, new RecordField(fieldPropertyName, eventName, fieldName, fieldType), null, null);
        fieldMappings.add(fieldMapping);
        factoryGen.addRecordField(record, fieldMapping.field);
        mappingGen.addRecordField(fieldMapping.field);
        return this;
    }

    DelegateGen field(String fieldName, FieldType fieldType) {
        return field(AbstractDataField.getDefaultPropertyName(fieldName), fieldName, fieldType);
    }

    DelegateGen phantom(String phantomProperty) {
        if (fieldMappings.isEmpty()) {
            // Phantom record
            record.phantomProperty = phantomProperty;
            mappingGen.phantom = true;
        } else {
            // Phantom field
            RecordField field = lastFieldMapping().field;
            field.conditionalProperty = phantomProperty;
            field.isPhantom = true;
            field.required = false;
            field.enabled = false;
        }
        return this;
    }

    // implies optional
    DelegateGen onlyIf(String conditionalProperty) {
        // Conditional field
        RecordField field = lastFieldMapping().field;
        field.conditionalProperty = conditionalProperty;
        field.isPhantom = false;
        field.required = false;
        field.enabled = false;
        return this;
    }

    DelegateGen internal() {
        lastFieldMapping().internal = true;
        return this;
    }

    DelegateGen optional() {
        lastFieldMapping().field.required = false;
        return this;
    }

    DelegateGen prevOptional() {
        prevFieldMapping().field.required = false;
        return this;
    }

    DelegateGen disabledByDefault() {
        if (lastFieldMapping().field.required)
            throw new IllegalStateException("Only optional fields can be disabled by default");
        lastFieldMapping().field.enabled = false;
        return this;
    }

    DelegateGen alt(String alt) {
        lastFieldMapping().field.alt = alt;
        return this;
    }

    // implies optional
    DelegateGen onlySuffixes(String suffixesProperty, String suffixesDefault) {
        FieldMapping fm = lastFieldMapping();
        if (record.suffixesDefault == null)
            throw new replacedertionError("Record should have suffixes");
        fm.field.onlySuffixesProperty = suffixesProperty;
        fm.field.onlySuffixesDefault = suffixesDefault;
        fm.field.required = false;
        fm.field.enabled = false;
        return this;
    }

    // implies optional
    DelegateGen exceptSuffixes(String suffixes) {
        FieldMapping fm = lastFieldMapping();
        if (record.suffixesDefault == null)
            throw new replacedertionError("Record should have suffixes");
        fm.field.exceptSuffixes = suffixes;
        fm.field.required = false;
        fm.field.enabled = false;
        return this;
    }

    DelegateGen voidForSuffixes(String suffixes) {
        lastFieldMapping().field.voidSuffixes = suffixes;
        return this;
    }

    DelegateGen time(int timeness) {
        lastFieldMapping().setTimeness(timeness);
        return this;
    }

    DelegateGen compositeOnly() {
        lastFieldMapping().field.isCompositeOnly = true;
        return this;
    }

    DelegateGen subContract(QDContract contract) {
        this.subContract = contract;
        return this;
    }

    DelegateGen withPlainEventFlags() {
        injectGetEventCode("event.setEventFlags(cursor.getEventFlags());");
        injectPutEventCode("cursor.setEventFlags(event.getEventFlags());");
        return this;
    }

    DelegateGen publishable() {
        publishable = true;
        return this;
    }

    DelegateGen mapTimeAndSequence() {
        return mapTimeAndSequence("Time", "Sequence");
    }

    DelegateGen mapTimeAndSequence(String timeFieldName, String sequenceFieldName) {
        map("Time", timeFieldName, FieldType.TIME_SECONDS).internal();
        map("Sequence", sequenceFieldName, FieldType.SEQUENCE).internal();
        replacedign("TimeSequence", "(((long) #Time.Seconds#) << 32) | (#Sequence# & 0xFFFFFFFFL)");
        injectPutEventCode("#Time.Seconds=(int) (event.getTimeSequence() >>> 32)#;", "#Sequence=(int) event.getTimeSequence()#;");
        return this;
    }

    DelegateGen mapTimeAndSequenceToIndex() {
        return mapTimeAndSequenceToIndex("Time", "Sequence");
    }

    DelegateGen mapTimeAndSequenceToIndex(String timeFieldName, String sequenceFieldName) {
        map("Time", timeFieldName, FieldType.TIME_SECONDS).time(0).internal();
        map("Sequence", sequenceFieldName, FieldType.SEQUENCE).time(1).internal();
        replacedign("Index", "(((long) #Time.Seconds#) << 32) | (#Sequence# & 0xFFFFFFFFL)");
        injectPutEventCode("#Time.Seconds=(int) (event.getIndex() >>> 32)#;", "#Sequence=(int) event.getIndex()#;");
        return this;
    }

    private FieldMapping lastFieldMapping() {
        return fieldMappings.get(fieldMappings.size() - 1);
    }

    private FieldMapping prevFieldMapping() {
        return fieldMappings.get(fieldMappings.size() - 2);
    }

    void generate() throws IOException {
        if (clreplacedName == null)
            return;
        ClreplacedGen cg = ClreplacedGen.resolve(clreplacedName, "TemplateDelegate.java", env);
        if (superDelegateClreplacedName != null) {
            cg.setVariableValue("SUPER_CLreplaced", superDelegateClreplacedName.getSimpleName() + "<" + eventName + ">");
            cg.addImport(superDelegateClreplacedName);
        } else {
            cg.setVariableValue("SUPER_CLreplaced", "EventDelegate<" + eventName + ">");
            cg.addImport(new ClreplacedName(EventDelegate.clreplaced));
        }
        cg.addImport(eventClreplaced.getClreplacedName());
        cg.addImport(mappingGen.getClreplacedName());
        cg.code("private final " + mappingGen.getClreplacedName().getSimpleName() + " m;");
        if (innerDelegateClreplacedName != null) {
            cg.addImport(innerDelegateClreplacedName);
            cg.code("private final " + innerDelegateClreplacedName.getSimpleName() + " d;");
        }
        generateDelegateConstructorCode(cg);
        generateGetMappingCode(cg);
        generateCreateEventCode(cg);
        generateGetEventCode(cg);
        if (publishable)
            generatePutEventCode(cg);
        if (source != null)
            generateGetSource(cg);
        env.writeSourceFile(clreplacedName, cg.buildSource());
    }

    private void generateDelegateConstructorCode(ClreplacedGen cg) {
        cg.newLine();
        cg.addImport(new ClreplacedName(DataRecord.clreplaced));
        cg.addImport(new ClreplacedName(QDContract.clreplaced));
        cg.addImport(new ClreplacedName(EnumSet.clreplaced));
        cg.addImport(new ClreplacedName(EventDelegateFlags.clreplaced));
        cg.code("public " + clreplacedName.getSimpleName() + "(DataRecord record, QDContract contract, EnumSet<EventDelegateFlags> flags) {");
        cg.indent();
        cg.code("super(record, contract, flags);");
        cg.addImport(mappingGen.getClreplacedName());
        cg.code("m = record.getMapping(" + mappingGen.getClreplacedName().getSimpleName() + ".clreplaced);");
        if (innerDelegateClreplacedName != null)
            cg.code("d = new " + innerDelegateClreplacedName.getSimpleName() + "(record, contract, flags);");
        cg.unindent();
        cg.code("}");
    }

    private void generateGetMappingCode(ClreplacedGen cg) {
        cg.newLine();
        cg.code("@Override");
        cg.code("public " + mappingGen.getClreplacedName().getSimpleName() + " getMapping() {");
        cg.indent();
        cg.code("return m;");
        cg.unindent();
        cg.code("}");
    }

    private void generateGetEventCode(ClreplacedGen cg) {
        cg.newLine();
        cg.code("@Override");
        cg.code("public " + eventName + " getEvent(" + eventName + " event, RecordCursor cursor) {");
        cg.indent();
        if (innerDelegateClreplacedName != null) {
            cg.code("d.getEvent(event, cursor);");
        } else {
            cg.code("super.getEvent(event, cursor);");
        }
        for (GetPutEventCodeGenerator codeGenerator : codeGenerators) {
            codeGenerator.generateGetEventCodePiece(cg);
        }
        cg.code("return event;");
        cg.unindent();
        cg.code("}");
    }

    private void generateCreateEventCode(ClreplacedGen cg) {
        cg.newLine();
        cg.code("@Override");
        cg.code("public " + eventName + " createEvent() {");
        cg.indent();
        cg.code("return new " + eventName + "();");
        cg.unindent();
        cg.code("}");
    }

    private void generatePutEventCode(ClreplacedGen cg) {
        cg.newLine();
        cg.addImport(new ClreplacedName(RecordCursor.clreplaced));
        cg.addImport(new ClreplacedName(RecordBuffer.clreplaced));
        cg.code("@Override");
        cg.code("public RecordCursor putEvent(" + eventName + " event, RecordBuffer buf) {");
        cg.indent();
        if (innerDelegateClreplacedName != null) {
            cg.code("RecordCursor cursor = d.putEvent(event, buf);");
        } else {
            cg.code("RecordCursor cursor = super.putEvent(event, buf);");
        }
        for (GetPutEventCodeGenerator codeGenerator : codeGenerators) {
            codeGenerator.generatePutEventCodePiece(cg);
        }
        cg.code("return cursor;");
        cg.unindent();
        cg.code("}");
    }

    private void generateGetSource(ClreplacedGen cg) {
        cg.newLine();
        cg.addImport(new ClreplacedName(IndexedEventSource.clreplaced));
        cg.code("@Override");
        cg.code("public IndexedEventSource getSource() {");
        cg.indent();
        cg.code("return " + source + ";");
        cg.unindent();
        cg.code("}");
    }

    private String mksubst(String value) {
        while (true) {
            int i = value.indexOf('#');
            if (i < 0)
                break;
            int j = value.indexOf('#', i + 1);
            if (j < 0)
                break;
            String name = value.substring(i + 1, j);
            String replacedign = null;
            int k = name.indexOf('=');
            if (k >= 0) {
                replacedign = name.substring(k + 1);
                name = name.substring(0, k);
            }
            String suffix = "";
            k = name.lastIndexOf('.');
            if (k >= 0) {
                suffix = name.substring(k + 1);
                name = name.substring(0, k);
            }
            FieldMapping m = findMappingByProperty(name);
            String replace = replacedign == null ? "m.get" + m.field.propertyName + suffix + "(cursor)" : "m.set" + m.field.propertyName + suffix + "(cursor, " + replacedign + ")";
            value = value.substring(0, i) + replace + value.substring(j + 1);
        }
        return value;
    }

    private FieldMapping findMappingByProperty(String name) {
        for (FieldMapping mapping : fieldMappings) {
            if (name.equals(mapping.eventPropertyName))
                return mapping;
        }
        throw new IllegalArgumentException("Mapping for field " + name + " is not found");
    }

    private abstract static clreplaced GetPutEventCodeGenerator {

        GetPutEventCodeGenerator() {
        }

        abstract void generateGetEventCodePiece(ClreplacedGen cg);

        abstract void generatePutEventCodePiece(ClreplacedGen cg);
    }

    private clreplaced GetEventCodeInjection extends GetPutEventCodeGenerator {

        final String[] lines;

        GetEventCodeInjection(String... lines) {
            this.lines = lines;
        }

        @Override
        void generateGetEventCodePiece(ClreplacedGen cg) {
            for (String line : lines) {
                cg.code(mksubst(line));
            }
        }

        @Override
        void generatePutEventCodePiece(ClreplacedGen cg) {
        }
    }

    private clreplaced PutEventCodeInjection extends GetPutEventCodeGenerator {

        final String[] lines;

        PutEventCodeInjection(String... lines) {
            this.lines = lines;
        }

        @Override
        void generateGetEventCodePiece(ClreplacedGen cg) {
        }

        @Override
        void generatePutEventCodePiece(ClreplacedGen cg) {
            for (String line : lines) {
                cg.code(mksubst(line));
            }
        }
    }

    private clreplaced Fieldreplacedignment extends GetPutEventCodeGenerator {

        final String property;

        final String value;

        Fieldreplacedignment(String property, String value) {
            this.property = property;
            this.value = value;
        }

        @Override
        void generateGetEventCodePiece(ClreplacedGen cg) {
            cg.code("event.set" + property + "(" + mksubst(value) + ");");
        }

        @Override
        void generatePutEventCodePiece(ClreplacedGen cg) {
        }
    }

    private static clreplaced FieldMapping extends GetPutEventCodeGenerator {

        final String eventPropertyName;

        final CodeGenType eventPropertyType;

        final RecordField field;

        final String getterName;

        final String setterName;

        boolean internal;

        FieldMapping(String eventPropertyName, CodeGenType eventPropertyType, RecordField field, String getterName, String setterName) {
            this.eventPropertyName = eventPropertyName;
            this.eventPropertyType = eventPropertyType;
            this.field = field;
            this.getterName = getterName;
            this.setterName = setterName;
        }

        void setTimeness(int timenessId) {
            if (timenessId < 0 || timenessId > 1)
                throw new IllegalArgumentException();
            SchemeFieldTime time = (timenessId == 0 ? FIRST_TIME_INT_FIELD : SECOND_TIME_INT_FIELD);
            if (field.time != COMMON_FIELD && field.time != time)
                throw new IllegalArgumentException("Timeness mismatches for field \"" + field + "\"");
            field.time = time;
        }

        @Override
        void generateGetEventCodePiece(ClreplacedGen cg) {
            if (internal)
                return;
            FieldType.TypeMapper mapper = field.fieldType.mapper;
            String getter = mapper.generateGetter(eventPropertyType, "m.get" + field.propertyName + "%s(cursor)");
            mapper.configureImports(cg, eventPropertyType);
            cg.code("event." + setterName + "(" + getter + ");");
        }

        @Override
        void generatePutEventCodePiece(ClreplacedGen cg) {
            if (internal)
                return;
            String value = "event." + getterName + "()";
            FieldType.TypeMapper mapper = field.fieldType.mapper;
            mapper.configureImports(cg, eventPropertyType);
            cg.code(mapper.generateSetter(eventPropertyType, "m.set" + field.propertyName + "%s(cursor, %s);", value));
        }
    }
}

17 Source : CollectorManagementImplOneContract.java
with Mozilla Public License 2.0
from devexperts

/**
 * Returns JMX name that is used for collector management.
 */
public static String getBeanName(DataScheme scheme, QDContract contract, String keyProperties) {
    JMXNameBuilder builder = new JMXNameBuilder("com.devexperts.qd.impl.matrix");
    builder.appendKeyProperties(keyProperties);
    builder.append("scheme", CollectorManagementImplAnyContract.getSchemeName(scheme));
    builder.append("c", contract.toString());
    return builder.toString();
}

17 Source : SubscriptionProcessor.java
with Mozilla Public License 2.0
from devexperts

/**
 * This clreplaced is base clreplaced for listening QD for subscription availability and rescheduling its processing using {@link Executor}.
 * Clreplacedes which extends {@code SubscriptionProcessor} listen for subscription coming from QD and process incoming subscription
 * in separate thread or threads.
 *
 * {@code Executor} may be single thread or thread pool executor. One Executor may be shared by different subscription processors.
 * It is guaranteed that new subscription processing handler will not be called until previous has completed its work.
 *
 * {@code SubscriptionProcessor} registers {@link RecordListener} in all {@link RecordProvider} instances when
 * {@link #startProcessing} method is called.
 * Clreplaced client is responsible to call {@link #stopProcessing} when processing is not required any more.
 *
 * This clreplaced is thread-safe and lock-free. Change carefully.
 */
public abstract clreplaced SubscriptionProcessor {

    private static final boolean TRACE_LOG = SubscriptionProcessor.clreplaced.desiredreplacedertionStatus();

    private static final Logging log = Logging.getLogging(SubscriptionProcessor.clreplaced);

    private final Executor executor;

    private final QDContract contract;

    private final SubscriptionHandler addedHandler = new SubscriptionHandler();

    private final SubscriptionHandler removedHandler = new SubscriptionHandler();

    private final AtomicBoolean taskScheduled = new AtomicBoolean(false);

    /**
     * Constructs new subscription processor for the specified executor.
     *
     * @param executor the executor.
     * @param contract the contract for which subscription shall be processed.
     * @throws NullPointerException if executor is null.
     */
    protected SubscriptionProcessor(Executor executor, QDContract contract) {
        if (executor == null)
            throw new NullPointerException("executor is null");
        this.executor = executor;
        this.contract = contract;
    }

    /**
     * Method for processing incoming added subscription from QD.
     * When added subscription is received, {@code SubscriptionProcessor} calls this method in {@code Executor} thread.
     */
    protected abstract void processAddedSubscription(RecordSource source);

    /**
     * Method for processing incoming removed subscription from QD.
     * When removed subscription is received, {@code SubscriptionProcessor} calls this method in {@code Executor} thread.
     */
    protected abstract void processRemovedSubscription(RecordSource source);

    /**
     * Starts subscription processing for the specified {@link QDDistributor}.
     * This method is equivalent to the following code:
     * {@code startProcessing(distributor.getAddedRecordProvider(), distributor.getRemovedRecordProvider())}.
     * This method or {@link #startProcessing(RecordProvider, RecordProvider)} may be called at most once after construction.
     * @throws NullPointerException if distributor is null.
     * @throws IllegalStateException if called multiple times. It is checked weakly to ensure fail-fast error detection
     *     behaviour. There is no strict thread-safe guarantee for this exception to be thrown if this method is called
     *     concurrently from multiple threads.
     */
    public void startProcessing(QDDistributor distributor) {
        startProcessing(distributor.getAddedRecordProvider(), distributor.getRemovedRecordProvider());
    }

    /**
     * Starts subscription processing for the specified added and removed {@link RecordProvider} instances.
     * This method accepts {@code null} for one of the providers.
     * This method or {@link #startProcessing(QDDistributor)} may be called at most once after construction.
     * @throws NullPointerException if both {@link RecordProvider} arguments are {@code null}.
     * @throws IllegalStateException if called multiple times. It is checked weakly to ensure fail-fast error detection
     *     behaviour. There is no strict thread-safe guarantee for this exception to be thrown if this method is called
     *     concurrently from multiple threads.
     */
    public void startProcessing(RecordProvider addedSubscriptionProvider, RecordProvider removedSubscriptionProvider) {
        if (addedSubscriptionProvider == null && removedSubscriptionProvider == null)
            throw new NullPointerException("Both subscription providers are null");
        if (addedHandler.provider != null || removedHandler.provider != null)
            throw new IllegalStateException("startProcessing was already called");
        addedHandler.provider = addedSubscriptionProvider;
        removedHandler.provider = removedSubscriptionProvider;
        addedHandler.setListener(addedHandler);
        removedHandler.setListener(removedHandler);
    }

    /**
     * Stop subscription processing. Unregisters {@link RecordProvider} instances from {@link RecordProvider} instances.
     * Note: client code is responsible for disposing SubscriptionProviders originally preplaceded to SubscriptionProcessor.
     * @throws IllegalStateException if called before {@link #startProcessing(QDDistributor)} or
     *         {@link #startProcessing(RecordProvider, RecordProvider)}.
     */
    public void stopProcessing() {
        if (addedHandler.provider == null && removedHandler.provider == null)
            throw new IllegalStateException("startProcessing was not called");
        addedHandler.setListener(null);
        removedHandler.setListener(null);
    }

    /**
     * Returns true when this SubscriptionProcessor has more subscription available to process or its
     * task is scheduled for processing.
     */
    public boolean hasMoreToProcess() {
        return taskScheduled.get();
    }

    /**
     * This method is called immediately before {@link #hasMoreToProcess()} becomes false.
     */
    protected void signalNoMoreToProcess() {
    }

    // ========== Implementation ==========
    private void rescheduleTask() {
        executor.execute(addedHandler);
    }

    private void scheduleTaskIfNeeded() {
        if (taskScheduled.compareAndSet(false, true))
            rescheduleTask();
    }

    private void executeTask() {
        // Reschedule task if an exception was thrown.
        boolean rescheduleTask = true;
        try {
            // INVARIANT: taskScheduled == true here
            // added subscription is contract-specific
            RecordBuffer buf = RecordBuffer.getInstance(RecordMode.addedSubscriptionFor(contract));
            // retrieve up to buffer capacity only
            buf.setCapacityLimited(true);
            addedHandler.retrieve(buf);
            if (TRACE_LOG)
                log.trace("executeTask added size=" + buf.size());
            if (!buf.isEmpty()) {
                processAddedSubscription(buf);
                buf.clear();
            }
            buf.setMode(RecordMode.SUBSCRIPTION);
            removedHandler.retrieve(buf);
            if (TRACE_LOG)
                log.trace("executeTask removed size=" + buf.size());
            if (!buf.isEmpty())
                processRemovedSubscription(buf);
            buf.release();
            rescheduleTask = addedHandler.available || removedHandler.available;
        } finally {
            if (rescheduleTask)
                rescheduleTask();
            else {
                try {
                    signalNoMoreToProcess();
                } finally {
                    taskScheduled.set(false);
                    // Concurrent recordsAvailable notification might have happened - recheck flag
                    if (addedHandler.available || removedHandler.available)
                        scheduleTaskIfNeeded();
                }
            }
        }
    }

    private final clreplaced SubscriptionHandler implements RecordListener, Runnable {

        RecordProvider provider;

        volatile boolean available;

        SubscriptionHandler() {
        }

        void setListener(RecordListener listener) {
            if (provider != null)
                provider.setRecordListener(listener);
        }

        void retrieve(RecordBuffer buf) {
            if (!available)
                return;
            // Consider subscription is still available if an exception was thrown.
            boolean more = true;
            try {
                available = false;
                more = provider.retrieve(buf);
            } finally {
                if (more)
                    available = true;
            }
        }

        @Override
        public void recordsAvailable(RecordProvider provider) {
            if (TRACE_LOG)
                log.trace("recordsAvailable from " + provider);
            available = true;
            scheduleTaskIfNeeded();
        }

        @Override
        public void run() {
            executeTask();
        }
    }
}

17 Source : QDEndpoint.java
with Mozilla Public License 2.0
from devexperts

/**
 * This method is used only for the endpoint,
 * which was created with {@link #QDEndpoint(String, DataScheme, QDStats, List, boolean, boolean)}. If this endpoint was created by using
 * {@link Builder#build()}, collectors had to be added by {@link Builder#withCollectors(Collection)}.
 * @param collector which to be added to this endpoint
 * @return this endpoint
 */
public QDEndpoint addCollector(QDCollector collector) {
    synchronized (lock) {
        if (collector.getScheme() != scheme)
            throw new IllegalArgumentException("Different scheme in endpoint collector. " + "Found " + collector.getScheme() + ", expected " + scheme);
        if (closed)
            return this;
        QDContract contract = collector.getContract();
        switch(contract) {
            case TICKER:
                if (ticker != null)
                    collectorRedefined(contract);
                ticker = (QDTicker) collector;
                break;
            case STREAM:
                if (stream != null)
                    collectorRedefined(contract);
                stream = (QDStream) collector;
                break;
            case HISTORY:
                if (history != null)
                    collectorRedefined(contract);
                history = (QDHistory) collector;
                break;
            default:
                throw new IllegalArgumentException("Unexpected contract " + contract);
        }
        collectors.put(contract, collector);
    }
    return this;
}

17 Source : AgentAdapter.java
with Mozilla Public License 2.0
from devexperts

private void processSubscription(RecordSource sub, MessageType message) {
    QDContract contract = message.getContract();
    boolean hasContract = false;
    long initialPosition = sub.getPosition();
    for (int i = 0; i < shapers.length; i++) {
        ChannelShaper shaper = shapers[i];
        if (shaper.getContract() != contract)
            continue;
        hasContract = true;
        AgentChannel channel = getOrCreateChannelAt(i);
        sub.setPosition(initialPosition);
        channel.processSubscription(message, sub);
    }
    if (!hasContract)
        reportIgnoredMessage("Contract is not supported", message);
}

17 Source : DXEndpointImpl.java
with Mozilla Public License 2.0
from devexperts

public List<EventDelegate<?>> getDelegateListByContractAndRecord(QDContract contract, DataRecord record) {
    return delegateListsByContractAndRecord.get(contract).getByKey(record);
}

16 Source : IPFSymbolFilter.java
with Mozilla Public License 2.0
from devexperts

@Override
public final boolean accept(QDContract contract, DataRecord record, int cipher, String symbol) {
    // NOte: IPFSymbolFilter is "symbol-only filter" (see QDFilter.Kind.isSymbolOnly), so
    // it must work even when contract and record are null (it cannot be used here)
    if (cipher == wildcard)
        return true;
    if (set.contains(cipher, symbol))
        return true;
    if (symbol == null || symbol.length() < 2 || symbol.charAt(symbol.length() - 1) != '}')
        return false;
    int i = symbol.indexOf('{');
    if (i < 0)
        return false;
    String prefix = symbol.substring(0, i);
    return set.contains(getScheme().getCodec().encode(prefix), prefix);
}

15 Source : MonitoredQDEndpoint.java
with Mozilla Public License 2.0
from devexperts

private void logCollectorCounters() {
    for (QDContract contract : QDContract.values()) {
        QDCollector collector = getCollector(contract);
        if (!(collector instanceof Collector))
            continue;
        CollectorCounters counters = ((Collector) collector).getCountersSinceStart();
        CollectorCounters delta = counters.since(lastCounters.get(contract));
        lastCounters.put(contract, counters);
        String text = delta.textReport().replaceAll("\\r?\\n", "\n    ");
        QDLog.log.info("\b{" + collector.toString() + "} " + text);
    }
}

14 Source : CollectorManagementImplBase.java
with Mozilla Public License 2.0
from devexperts

private void reportSubscriptionImpl(ReportBuilder rb, Collector collector, String recordName, String symbol) {
    QDContract contract = collector.getContract();
    rb.header(nameCollector(collector), ReportBuilder.HEADER_LEVEL_COLLECTOR);
    DataScheme scheme = collector.getScheme();
    boolean allSymbols = "*".equals(symbol);
    boolean allRecords = "*".equals(recordName);
    int cipher = allSymbols ? 0 : scheme.getCodec().encode(symbol);
    DataRecord record = allRecords ? null : scheme.findRecordByName(recordName);
    if (!allRecords && record == null) {
        rb.message("No such record in scheme");
        return;
    }
    ReportSubscriptionSink sink = new ReportSubscriptionSink(rb, contract, cipher, symbol, record, allSymbols, allRecords);
    sink.begin();
    collector.examineSubscription(sink);
    sink.end();
}

13 Source : DistributorAdapter.java
with Mozilla Public License 2.0
from devexperts

@Override
public void prepareProtocolDescriptor(ProtocolDescriptor desc) {
    super.prepareProtocolDescriptor(desc);
    QDFilter stableFilter = CompositeFilters.toStableFilter(this.filter);
    if (stableFilter != QDFilter.ANYTHING)
        desc.setProperty(ProtocolDescriptor.FILTER_PROPERTY, stableFilter.toString());
    for (QDContract contract : QD_CONTRACTS) if (collectors[contract.ordinal()] != null) {
        desc.addSend(desc.newMessageDescriptor(MessageType.forAddSubscription(contract)));
        desc.addSend(desc.newMessageDescriptor(MessageType.forRemoveSubscription(contract)));
        desc.addReceive(desc.newMessageDescriptor(MessageType.forData(contract)));
    }
    desc.addReceive(desc.newMessageDescriptor(MessageType.RAW_DATA));
}

13 Source : DistributorAdapter.java
with Mozilla Public License 2.0
from devexperts

@Override
protected void processData(DataIterator iterator, MessageType message) {
    if (!message.isData())
        throw new IllegalArgumentException(message.toString());
    if (!isAlive()) {
        reportIgnoredMessage("Adapter is " + getStatus(), message);
    } else {
        QDContract contract = message.getContract();
        if (contract != null) {
            QDDistributor distributor = getOrCreateDistributor(contract.ordinal());
            if (distributor == null) {
                reportIgnoredMessage("Contract is not supported", message);
            } else {
                distributor.processData(iterator);
                // processed -- exit from method
                return;
            }
        }
    }
    // silently ignore otherwise
    DataConsumer.VOID.processData(iterator);
}

12 Source : DXEndpointImpl.java
with Mozilla Public License 2.0
from devexperts

@SuppressWarnings({ "unchecked", "rawtypes" })
void registerDelegate(EventDelegate<?> delegate) {
    QDContract contract = delegate.getContract();
    if (qdEndpoint.getCollector(contract) == null)
        return;
    EventDelegateSet delegateSet = delegateSetsByEventType.getByKey(delegate.getEventType());
    if (delegateSet == null)
        delegateSetsByEventType.add(delegateSet = delegate.createDelegateSet());
    try {
        delegateSet.add(delegate);
    } catch (ClreplacedCastException e) {
        throw new IllegalArgumentException("Cannot mix events of incompatible types", e);
    }
    IndexedSet<DataRecord, List<EventDelegate<?>>> lists = delegateListsByContractAndRecord.get(contract);
    List<EventDelegate<?>> delegateList = lists.getByKey(delegate.getRecord());
    if (delegateList == null) {
        delegateList = new ArrayList<>(1);
        delegateList.add(delegate);
        lists.add(delegateList);
    } else
        delegateList.add(delegate);
}

12 Source : DelegateGen.java
with Mozilla Public License 2.0
from devexperts

Map<QDContract, EnumSet<EventDelegateFlags>> getContractFlags() {
    Map<QDContract, EnumSet<EventDelegateFlags>> result = new EnumMap<>(QDContract.clreplaced);
    boolean lasting = eventClreplaced.isreplacedignableTo(LastingEvent.clreplaced);
    boolean timeSeries = eventClreplaced.isreplacedignableTo(TimeSeriesEvent.clreplaced);
    boolean indexedOnly = !timeSeries && eventClreplaced.isreplacedignableTo(IndexedEvent.clreplaced);
    QDContract primaryContract = subContract != null ? subContract : indexedOnly ? QDContract.HISTORY : lasting || timeSeries ? QDContract.TICKER : QDContract.STREAM;
    EnumSet<EventDelegateFlags> primaryFlags = EnumSet.of(EventDelegateFlags.SUB);
    if (publishable)
        primaryFlags.add(EventDelegateFlags.PUB);
    result.put(primaryContract, primaryFlags);
    if (publishable && primaryContract != QDContract.STREAM)
        result.put(QDContract.STREAM, EnumSet.of(EventDelegateFlags.PUB));
    if (timeSeries && primaryContract != QDContract.HISTORY) {
        EnumSet<EventDelegateFlags> flags = EnumSet.of(EventDelegateFlags.SUB, EventDelegateFlags.TIME_SERIES);
        if (publishable)
            flags.add(EventDelegateFlags.PUB);
        result.put(QDContract.HISTORY, flags);
    }
    // always support wildcard subscription via stream
    if (!result.containsKey(QDContract.STREAM))
        result.put(QDContract.STREAM, EnumSet.noneOf(EventDelegateFlags.clreplaced));
    result.get(QDContract.STREAM).add(EventDelegateFlags.WILDCARD);
    return result;
}

10 Source : CollectorManagementImplBase.java
with Mozilla Public License 2.0
from devexperts

private void reportDataImpl(ReportBuilder rb, Collector collector, String recordName, String symbol, boolean boundsOnly) {
    QDContract contract = collector.getContract();
    if (!contract.hreplacednapshotData())
        return;
    rb.header(nameCollector(collector), ReportBuilder.HEADER_LEVEL_COLLECTOR);
    DataScheme scheme = collector.getScheme();
    boolean allSymbols = "*".equals(symbol);
    boolean allRecords = "*".equals(recordName);
    int cipher = allSymbols ? 0 : scheme.getCodec().encode(symbol);
    DataRecord record = allRecords ? null : scheme.findRecordByName(recordName);
    if (!allRecords && record == null) {
        rb.message("No such record in scheme");
        return;
    }
    ReportDataSink sink = new ReportDataSink(rb, contract, record, cipher, symbol, allSymbols, allRecords, boundsOnly);
    sink.begin();
    if (!allRecords && !allSymbols) {
        // fast path for a single record-symbol
        RecordBuffer sub = RecordBuffer.getInstance(RecordMode.SUBSCRIPTION);
        sub.add(record, cipher, symbol);
        collector.examineDataBySubscription(sink, sub);
        sub.release();
    } else {
        // everything else like full data scan (slow path)
        collector.examineData(sink);
    }
    sink.end();
}

10 Source : BigBatchDistributionTest.java
with Mozilla Public License 2.0
from devexperts

private void checkCollector(QDContract contract, boolean forSymbols, boolean sourceAscending, boolean resultAscending) {
    String desc = " in test(" + contract + ", " + forSymbols + ", " + sourceAscending + ", " + resultAscending + ")";
    QDCollector collector = QDFactory.getDefaultFactory().collectorBuilder(contract).withScheme(SCHEME).withHistoryFilter(new HistorySubscriptionFilter() {

        @Override
        public long getMinHistoryTime(DataRecord record, int cipher, String symbol) {
            return Long.MIN_VALUE;
        }

        @Override
        public int getMaxRecordCount(DataRecord record, int cipher, String symbol) {
            return Integer.MAX_VALUE;
        }
    }).build();
    RecordBuffer buffer = new RecordBuffer(RecordMode.DATA);
    QDAgent agent = collector.agentBuilder().build();
    for (int i = 0, n = forSymbols ? SIZE : 1; i < n; i++) {
        buffer.add(RECORD, getCipher(i, forSymbols), null).setTime(Long.MIN_VALUE);
    }
    agent.setSubscription(buffer);
    if (buffer.next() != null)
        fail("leftover subscription in buffer after setSubscription(buffer)" + desc);
    buffer.clear();
    QDDistributor distributor = collector.distributorBuilder().build();
    for (int i = 0; i < SIZE; i++) {
        int idx = sourceAscending ? i : SIZE - 1 - i;
        buffer.add(RECORD, getCipher(idx, forSymbols), null).setTime(getTime(idx));
    }
    distributor.process(buffer);
    if (buffer.next() != null)
        fail("leftover data in buffer after process(buffer)" + desc);
    buffer.clear();
    if (agent.retrieve(buffer))
        fail("leftover data in agent after retrieve(buffer)" + desc);
    for (int i = 0; i < SIZE; i++) {
        int idx = resultAscending ? i : SIZE - 1 - i;
        int cipher = getCipher(idx, forSymbols);
        int time = getTime(idx);
        RecordCursor cursor = buffer.next();
        if (cursor == null)
            fail("not enough data in buffer retrieved from agent for " + idx + desc);
        if (cursor.getCipher() != cipher)
            fail("wrong symbol " + SCHEME.getCodec().decode(cursor.getCipher()) + " instead of " + SCHEME.getCodec().decode(cipher) + " for " + idx + desc);
        if (cursor.getTime() != time)
            fail("wrong time " + cursor.getTime() + " instead of " + time + " for " + idx + desc);
    }
    if (buffer.next() != null)
        fail("leftover data in buffer retrieved from agent" + desc);
}

See More Examples