package dgm.streaming.requestmapper; import com.google.common.base.Optional; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * * this represents a repository where channels can be stored by id. * How does it work? * We use channel groups in the background. When: * a channel is registered with an id, and * -> the id is not in the map: * -> create a channel group by that id, add the channel, and be done. * -> the id is in the map: * -> fetch the channel group, and add the channel. * * When a channel with a given id is removed, and * -> the id is in the map: * -> fetch the chanel group, and remove the channel. if the group is now empty: remove the group. * -> the id is not in the map: * -> what can you do? * * @author Ernst Bunders */ public final class ChannelContextImpl implements ChannelContext { private static final Map<String, ChannelGroup> repository = new ConcurrentHashMap<String, ChannelGroup>(); private static final Logger LOGGER = LoggerFactory.getLogger(ChannelContextImpl.class); @Override public Optional<ChannelGroup> getChannelGroup(String id) { if (repository.containsKey(id)) return Optional.of(repository.get(id)); return Optional.absent(); } @Override public ChannelGroup addChannel(String id, Channel channel) { if(!repository.containsKey(id)) { repository.put(id, new DefaultChannelGroup(id)); LOGGER.debug("Adding channel group with id {}", id); } repository.get(id).add(channel); LOGGER.debug("Adding channel with id {} to group with id {}", channel.getId(), id); return repository.get(id); } @Override public void removeChannel(Channel channel) { String key = null; for (Map.Entry<String, ChannelGroup> entry : repository.entrySet()) { if (entry.getValue().contains(channel)) { LOGGER.debug("Removing channel with id {} from channel group with id {}", channel.getId(), entry.getKey()); entry.getValue().remove(channel); if (entry.getValue().size() == 0) { key = entry.getKey(); } } } if (key != null) { LOGGER.debug("Removing channel group with id {} from the context", key); repository.remove(key); } } }