package com.hadooparchitecturebook.frauddetection;
import com.hadooparchitecturebook.frauddetection.model.Action;
import com.hadooparchitecturebook.frauddetection.model.UserEvent;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONException;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.Executors;
/**
* Created by ted.malaska on 1/18/15.
*/
public class EventReviewServer {
static Logger LOG = Logger.getLogger(EventReviewServer.class);
static EventServerHandler handler;
static Channel channel;
public static EventProcessor eventProcessor;
int portNumber;
Configuration config;
List<String> flumePorts;
boolean useCheckPut;
public EventReviewServer(int portNumber, Configuration config, List<String> flumePorts, boolean useCheckPut) {
this.portNumber = portNumber;
this.config = config;
this.flumePorts = flumePorts;
this.useCheckPut = useCheckPut;
}
public void startServer() throws Exception {
eventProcessor = EventProcessor.initAndStartEventProcess(config, flumePorts, useCheckPut);
handler = new EventServerHandler();
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.receiveBufferSize", 1048576);
bootstrap.setOption("child.sendBufferSize", 1048576);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline();
p.addLast("batch", handler);
return p;
}
});
LOG.info("EventReviewServer: binding to :" + portNumber);
channel = bootstrap.bind(new InetSocketAddress(portNumber));
LOG.info("EventReviewServer: bound to :" + portNumber + " " + channel.isBound() + " " + channel.getLocalAddress());
}
public void closeServer() {
channel.close();
}
public static class EventServerHandler extends SimpleChannelUpstreamHandler {
private long transferredBytes;
public long getTransferredBytes() {
return transferredBytes;
}
public EventServerHandler() {
}
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
System.err.println(e);
}
// Let SimpleChannelHandler call actual event handler methods below.
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Discard received data silently by doing nothing.
//String[] events = ((ChannelBuffer) e.getMessage()).toString().split("\n");
String jsonString = Bytes.toString(((ChannelBuffer) e.getMessage()).array());
try {
LOG.info("EventReviewServer: Get Message: " + jsonString);
UserEvent userEvent = new UserEvent(jsonString);
Action action = eventProcessor.reviewUserEvent(userEvent);
String json = action.getJSONObject().toString();
LOG.info("EventReviewServer: Got Action: " + json);
e.getChannel().write(ChannelBuffers.wrappedBuffer(Bytes.toBytes(json)));
} catch (JSONException e1) {
throw new RuntimeException("Unable to parse JSON:" + jsonString, e1);
} catch (Exception e1) {
throw new RuntimeException("Unable to process JSON:" + jsonString, e1);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
e.getCause().printStackTrace();
e.getChannel().close();
}
}
}