package edu.uw.zookeeper.server; import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; import edu.uw.zookeeper.data.WatchEvent; import edu.uw.zookeeper.protocol.NotificationListener; import edu.uw.zookeeper.protocol.Operation; import edu.uw.zookeeper.protocol.ProtocolResponseMessage; import edu.uw.zookeeper.protocol.proto.IWatcherEvent; import edu.uw.zookeeper.protocol.proto.OpCodeXid; /** * Not thread safe. */ public final class Watches { public static Watches create( Function<Long, ? extends NotificationListener<Operation.ProtocolResponse<IWatcherEvent>>> listeners) { return create(listeners, HashMultimap.<String, Long>create(), HashMultimap.<Long, String>create()); } public static Watches create( Function<Long, ? extends NotificationListener<Operation.ProtocolResponse<IWatcherEvent>>> listeners, SetMultimap<String, Long> byPath, SetMultimap<Long, String> bySession) { return new Watches(listeners, byPath, bySession); } private final SetMultimap<String, Long> byPath; private final SetMultimap<Long, String> bySession; private final Function<Long, ? extends NotificationListener<Operation.ProtocolResponse<IWatcherEvent>>> listeners; private final Logger logger; protected Watches( Function<Long, ? extends NotificationListener<Operation.ProtocolResponse<IWatcherEvent>>> listeners, SetMultimap<String, Long> byPath, SetMultimap<Long, String> bySession) { this.logger = LogManager.getLogger(this); this.byPath = byPath; this.bySession = bySession; this.listeners = listeners; } public SetMultimap<String,Long> byPath() { return byPath; } public SetMultimap<Long, String> bySession() { return bySession; } public void post(final IWatcherEvent event) { if (logger.isDebugEnabled()) { logger.debug("{}", WatchEvent.fromRecord(event)); } final ProtocolResponseMessage<IWatcherEvent> message = ProtocolResponseMessage.of( OpCodeXid.NOTIFICATION.xid(), OpCodeXid.NOTIFICATION_ZXID, event); String path = event.getPath(); for (Long session: byPath.removeAll(path)) { bySession.remove(session, path); NotificationListener<Operation.ProtocolResponse<IWatcherEvent>> listener = listeners.apply(session); if (listener != null) { listener.handleNotification(message); } } } public void put(Long session, String path) { byPath.put(path, session); bySession.put(session, path); } public Set<String> remove(Long session) { Set<String> paths = bySession.removeAll(session); for (String path: paths) { byPath.remove(path, session); } return paths; } @Override public String toString() { return MoreObjects.toStringHelper(this).toString(); } }