/* * Copyright 2010 Outerthought bvba * * 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 org.lilyproject.avro; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.avro.ipc.NettyServer; import org.apache.avro.ipc.Responder; import org.apache.avro.ipc.Server; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.execution.ExecutionHandler; import org.lilyproject.repository.api.RepositoryException; import org.lilyproject.repository.api.RepositoryManager; import org.lilyproject.util.concurrent.CustomThreadFactory; import org.lilyproject.util.concurrent.WaitPolicy; public class AvroServer { private RepositoryManager repositoryManager; private int port; private int maxServerThreads; private ExecutionHandler executionHandler; private ExecutorService executorService; private Server server; public AvroServer(RepositoryManager repositoryManager, int port, int maxServerThreads) { this.repositoryManager = repositoryManager; this.port = port; this.maxServerThreads = maxServerThreads; } @PostConstruct public void start() throws IOException, RepositoryException, InterruptedException { AvroLilyImpl avroLily = new AvroLilyImpl(repositoryManager, repositoryManager.getDefaultRepository().getTypeManager()); Responder responder = new LilySpecificResponder(AvroLily.class, avroLily); ThreadFactory threadFactory = new CustomThreadFactory("avro-exechandler", new ThreadGroup("AvroExecHandler")); if (maxServerThreads == -1) { executorService = Executors.newCachedThreadPool(threadFactory); executionHandler = new ExecutionHandler(executorService); } else { executorService = new ThreadPoolExecutor(maxServerThreads / 3, maxServerThreads, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory, new WaitPolicy()); executionHandler = new ExecutionHandler(executorService); } //server = new HttpServer(responder, port); server = new NettyServer(responder, new InetSocketAddress(port), new NioServerSocketChannelFactory (Executors.newCachedThreadPool(), Executors.newCachedThreadPool()), executionHandler); server.start(); } @PreDestroy public void stop() { // Previously the server.close call was disable for the following reason, just leaving this comment here for // historical reasons: // It would be nice to wait for client threads to end, but since these client threads pass into // HBase client code which is notoriously difficult to interrupt, we skip this step server.close(); // Actual work is now being performed on the threads of the ExecutorService if (executorService != null) { // Interrupt the threads. It would be nicer to wait for them to complete, but I experienced endless // hangs on shutdown, to be investigated later. executorService.shutdownNow(); // executionHandler.releaseExternalResources(); } try { server.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public int getPort() { return server.getPort(); } }