com.cloudera.hadoop.hdfs.nfs.rpc.RPCServer.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudera.hadoop.hdfs.nfs.rpc.RPCServer.java

Source

/**
 * Copyright 2011 The Apache Software Foundation
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to you 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 com.cloudera.hadoop.hdfs.nfs.rpc;

import static com.cloudera.hadoop.hdfs.nfs.nfs4.Constants.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IOUtils;

import com.cloudera.hadoop.hdfs.nfs.nfs4.MessageBase;
import com.google.common.collect.Maps;
import org.apache.log4j.Logger;

public class RPCServer<REQUEST extends MessageBase, RESPONSE extends MessageBase> extends Thread {

    protected static final Logger LOGGER = Logger.getLogger(RPCServer.class);
    protected RPCHandler<REQUEST, RESPONSE> mHandler;
    protected ConcurrentMap<Socket, ClientWorker<REQUEST, RESPONSE>> mClients = Maps.newConcurrentMap();
    protected int mPort;
    protected ServerSocket mServer;
    protected Configuration mConfiguration;
    protected Map<Integer, MessageBase> mResponseCache = Collections
            .synchronizedMap(new LRUCache<Integer, MessageBase>(500));
    protected Set<Integer> mRequestsInProgress = Collections.synchronizedSet(new HashSet<Integer>());
    protected ExecutorService mExecutor;
    protected Map<String, BlockingQueue<RPCBuffer>> mOutputQueueMap = Maps.newHashMap();

    public RPCServer(RPCHandler<REQUEST, RESPONSE> rpcHandler, Configuration conf, InetAddress address)
            throws Exception {
        this(rpcHandler, conf, address, 0);
    }

    public RPCServer(RPCHandler<REQUEST, RESPONSE> rpcHandler, Configuration conf, InetAddress address, int port)
            throws IOException {
        mExecutor = new ThreadPoolExecutor(10, conf.getInt(RPC_MAX_THREADS, 500), 30, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>());

        mHandler = rpcHandler;
        mConfiguration = conf;
        mPort = port;
        mServer = new ServerSocket(mPort, -1, address);
        // if port is 0, we are supposed to find a port
        // mPort should then be set to the port we found
        mPort = mServer.getLocalPort();
        setName("RPCServer-" + mHandler.getClass().getSimpleName() + "-" + mPort);
    }

    public void run() {
        try {
            mServer.setReuseAddress(true);
            mServer.setPerformancePreferences(0, 1, 0);
            LOGGER.info(mHandler.getClass() + " created server " + mServer + " on " + mPort);

            while (true) {
                Socket client = mServer.accept();
                String name = client.getInetAddress().getCanonicalHostName() + ":" + client.getPort();
                LOGGER.info(mHandler.getClass() + " got client " + name);

                ClientWorker<REQUEST, RESPONSE> worker = new ClientWorker<REQUEST, RESPONSE>(mConfiguration, this,
                        mHandler, client);
                mClients.put(client, worker);
                worker.start();
            }
        } catch (Exception ex) {
            LOGGER.error("Error on handler " + mHandler.getClass(), ex);
        } finally {
            shutdown();
        }
    }

    public void shutdown() {
        // first close clients
        for (Socket client : mClients.keySet()) {
            ClientWorker<REQUEST, RESPONSE> worker = mClients.get(client);
            if (worker != null && worker.isAlive()) {
                worker.shutdown();
            }
            IOUtils.closeSocket(client);
        }
        // then server
        if (mServer != null) {
            try {
                mServer.close();
            } catch (Exception e) {
            }
        }
    }

    public int getPort() {
        return mPort;
    }

    protected BlockingQueue<RPCBuffer> getOutputQueue(String name) {
        synchronized (mOutputQueueMap) {
            if (!mOutputQueueMap.containsKey(name)) {
                mOutputQueueMap.put(name, new LinkedBlockingQueue<RPCBuffer>(1000));
            }
            return mOutputQueueMap.get(name);
        }
    }

    protected Map<Integer, MessageBase> getResponseCache() {
        return mResponseCache;
    }

    public Set<Integer> getRequestsInProgress() {
        return mRequestsInProgress;
    }

    public ConcurrentMap<Socket, ClientWorker<REQUEST, RESPONSE>> getClients() {
        return mClients;
    }

    public ExecutorService getExecutorService() {
        return mExecutor;
    }
}