/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.server.thrift; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.thrift.server.TThreadedSelectorServer; import org.diqube.listeners.ServingListener; /** * A simple sub-class of {@link TThreadedSelectorServer} that enforces the selectorThreads to get a nice name. * * <p> * Unfortunately, there is no way to get to the AcceptThread - that thread therefore has a generic name. * * @author Bastian Gloeckle */ public class ThriftServer extends TThreadedSelectorServer { private String selectorThreadNameFormat; private List<ServingListener> servingListeners; /** * @param args * See {@link TThreadedSelectorServer#TThreadedSelectorServer(Args)} * @param selectorThreadNameFormat * a {@link String#format(String, Object...)}-compatible format String, to which a unique integer (0, 1, * etc.) will be supplied as the single parameter. This integer will be unique to the built instance of the * ThreadFactory and will be assigned sequentially. For example, {@code "rpc-pool-%d"} will generate thread * names like {@code "rpc-pool-0"}, {@code "rpc-pool-1"}, {@code "rpc-pool-2"}, etc. * @param servingListeners * listeners that should be informed about the state of the server. <code>null</code> possible. */ public ThriftServer(Args args, String selectorThreadNameFormat, List<ServingListener> servingListeners) { super(args); this.selectorThreadNameFormat = selectorThreadNameFormat; this.servingListeners = servingListeners; } @Override protected SelectorThreadLoadBalancer createSelectorThreadLoadBalancer(Collection<? extends SelectorThread> threads) { // It is far from perfect to use this method to set the thread names, but unfortunately, super.selectorThreads is // private and we cannot access it otherwise :( int i = 0; for (Iterator<? extends SelectorThread> it = threads.iterator(); it.hasNext();) it.next().setName(String.format(selectorThreadNameFormat, i++)); return super.createSelectorThreadLoadBalancer(threads); } @Override protected void setServing(boolean serving) { super.setServing(serving); if (servingListeners != null) { if (serving) servingListeners.forEach(l -> l.localServerStartedServing()); else servingListeners.forEach(l -> l.localServerStoppedServing()); } } }