/* * Copyright 2016 higherfrequencytrading.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package net.openhft.chronicle.engine.pubsub; import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.engine.api.pubsub.InvalidSubscriberException; import net.openhft.chronicle.engine.api.pubsub.Reference; import net.openhft.chronicle.engine.api.pubsub.Subscriber; import net.openhft.chronicle.engine.api.pubsub.SubscriptionConsumer; import net.openhft.chronicle.engine.api.tree.RequestContext; import net.openhft.chronicle.engine.query.Filter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.Function; /** * Created by peter on 29/05/15. */ public class MapSimpleSubscription<E> implements SimpleSubscription<E> { private static final Logger LOG = LoggerFactory.getLogger(MapSimpleSubscription.class); private final Set<Subscriber<E>> subscribers = new CopyOnWriteArraySet<>(); private final Reference<E> currentValue; private final Function<Object, E> valueReader; private volatile boolean closed = true; public MapSimpleSubscription(Reference<E> reference, Function<Object, E> valueReader) { this.currentValue = reference; this.valueReader = valueReader; } @Override public void registerSubscriber(@NotNull RequestContext rc, @NotNull Subscriber<E> subscriber, @NotNull Filter<E> filter) { subscribers.add(subscriber); if (rc.bootstrap() != Boolean.FALSE) try { subscriber.onMessage(currentValue.get()); } catch (InvalidSubscriberException e) { subscribers.remove(subscriber); } } @Override public void unregisterSubscriber(@NotNull Subscriber subscriber) { subscribers.remove(subscriber); subscriber.onEndOfSubscription(); } @Override public int keySubscriberCount() { return subscriberCount(); } @Override public int entrySubscriberCount() { return 0; } @Override public int topicSubscriberCount() { return 0; } @Override public int subscriberCount() { return subscribers.size(); } @Override public void notifyMessage(Object e) { try { @Nullable E ee = e instanceof BytesStore ? valueReader.apply(e) : (E) e; SubscriptionConsumer.notifyEachSubscriber(subscribers, s -> s.onMessage(ee)); } catch (ClassCastException e1) { if (LOG.isDebugEnabled()) Jvm.debug().on(getClass(), "Is " + valueReader + " the correct ValueReader?"); throw e1; } } @Override public void close() { if (isClosed()) return; closed = true; for (@NotNull Subscriber<E> subscriber : subscribers) { try { subscriber.onEndOfSubscription(); } catch (Exception e) { Jvm.debug().on(getClass(), e); } } } @Override public boolean isClosed() { return closed; } }