/* * JLibs: Common Utilities for Java * Copyright (C) 2009 Santhosh Kumar T <santhosh.tekuri@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package jlibs.nio; import java.io.IOException; import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; /** * @author Santhosh Kumar Tekuri */ public class Reactors{ private static List<Reactor> reactors; public static void start() throws IOException{ start(Runtime.getRuntime().availableProcessors()); } public static void start(int count) throws IOException{ if(reactors!=null) throw new UnsupportedOperationException("Reactors already started"); Reactor reactors[] = new Reactor[count]; for(int i=0; i<reactors.length; i++){ reactors[i] = new Reactor(i); reactors[i].start(); } Reactors.reactors = Collections.unmodifiableList(Arrays.asList(reactors)); Management.register(new Management.ReactorMXBean(){ @Override public int getServersCount(){ return Arrays.stream(reactors).mapToInt(Reactor::getServersCount).max().getAsInt(); } @Override public int getAccepted(){ return Arrays.stream(reactors).mapToInt(Reactor::getAccepted).sum(); } @Override public int getConnectionPending(){ return Arrays.stream(reactors).mapToInt(Reactor::getConnectionPending).sum(); } @Override public int getConnected(){ return Arrays.stream(reactors).mapToInt(Reactor::getConnected).sum(); } @Override public int getPooled(){ return Arrays.stream(reactors).mapToInt(reactor -> reactor.connectionPool.count()).sum(); } @Override public Map<String, Integer> getPool(){ try{ Map<String, Integer> map = new HashMap<>(); for(Reactor reactor: reactors){ reactor.invokeAndWait(() -> { Map<String, Integer> pool = reactor.connectionPool.entries.values().stream() .filter(t -> t.count>0) .collect(Collectors.toMap(t -> t.key, t -> t.count)); for(Map.Entry<String, Integer> entry : pool.entrySet()){ Integer count = map.getOrDefault(entry.getKey(), 0); map.put(entry.getKey(), count+entry.getValue()); } }); } return map; }catch(InterruptedException ex){ throw new RuntimeException(ex); } } }, "jlibs.nio:type=Reactors"); } public static List<Reactor> get(){ return reactors; } public static void shutdown(boolean force){ for(Reactor reactor: reactors) reactor.invokeLater(() -> reactor.shutdown(force)); } public static class Pool<T>{ private Deque<T> dqs[]; private Supplier<T> supplier; @SuppressWarnings("unchecked") public Pool(Supplier<T> supplier){ dqs = new Deque[reactors.size()]; for(int i=0; i<dqs.length; i++) dqs[i] = new ArrayDeque<>(); this.supplier = supplier; } public T allocate(){ Deque<T> dq = dqs[Reactor.current().id]; if(dq.isEmpty()) return supplier.get(); else return dq.pop(); } public void free(T item){ Deque<T> dq = dqs[Reactor.current().id]; dq.push(item); } } }