/**
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package com.github.ambry.server;
import com.github.ambry.network.Request;
import com.github.ambry.network.RequestResponseChannel;
import com.github.ambry.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Request handler class
*/
public class RequestHandler implements Runnable {
private final int id;
private final RequestResponseChannel requestChannel;
private final AmbryRequests requests;
private Logger logger = LoggerFactory.getLogger(getClass());
public RequestHandler(int id, RequestResponseChannel requestChannel, AmbryRequests requests) {
this.id = id;
this.requestChannel = requestChannel;
this.requests = requests;
}
public void run() {
while (true) {
try {
Request req = requestChannel.receiveRequest();
if (req.equals(EmptyRequest.getInstance())) {
logger.debug("Request handler {} received shut down command", id);
return;
}
requests.handleRequests(req);
logger.trace("Request handler {} handling request {}", id, req);
} catch (Throwable e) {
// TODO add metric to track background threads
logger.error("Exception when handling request", e);
// this is bad and we need to shutdown the app
Runtime.getRuntime().halt(1);
}
}
}
public void shutdown() throws InterruptedException {
requestChannel.sendRequest(EmptyRequest.getInstance());
}
}
// Request handler pool. A pool of threads that handle requests
class RequestHandlerPool {
private Thread[] threads = null;
private RequestHandler[] handlers = null;
private Logger logger = LoggerFactory.getLogger(getClass());
public RequestHandlerPool(int numThreads, RequestResponseChannel requestResponseChannel, AmbryRequests requests) {
threads = new Thread[numThreads];
handlers = new RequestHandler[numThreads];
for (int i = 0; i < numThreads; i++) {
handlers[i] = new RequestHandler(i, requestResponseChannel, requests);
threads[i] = Utils.daemonThread("request-handler-" + i, handlers[i]);
threads[i].start();
}
}
public void shutdown() {
try {
logger.info("shutting down");
for (RequestHandler handler : handlers) {
handler.shutdown();
}
for (Thread thread : threads) {
thread.join();
}
logger.info("shut down completely");
} catch (Exception e) {
logger.error("error when shutting down request handler pool {}", e);
}
}
}