/*
* Copyright MapR Technologies, 2013
*
* 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 com.mapr.franz.simple;
import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
import com.mapr.franz.Server;
import com.mapr.franz.catcher.Client;
import com.mapr.franz.catcher.metrics.Metrics;
import com.mapr.franz.catcher.wire.Catcher;
import com.mapr.franz.server.ProtoLogger;
import com.mapr.franz.stats.History;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.SecureRandom;
import java.util.Enumeration;
import java.util.List;
/**
* The super simple broken server.
*/
public class SimpleCatcherService implements Catcher.CatcherService.BlockingInterface {
private Logger log = LoggerFactory.getLogger(SimpleCatcherService.class);
private static ProtoLogger logger;
private static long serverId = 1;
private final Server us;
private final History recorder;
// TODO implement some sort of statistics that records (a) number of
// clients, (b) transactions per topic, (c) bytes per topic
public SimpleCatcherService(int port, String basePath) throws FileNotFoundException, SocketException {
logger = new ProtoLogger(basePath);
recorder = new History(1, 10, 60, 300)
.logTicks()
.addListener(new History.Listener() {
@Override
public void tick(double t, int interval, int uniqueTopics, int messages) {
try {
logger.write("-metrics-", Metrics.DataPoint.newBuilder()
.setTime(t)
.setInterval(interval)
.setUniqueTopics(uniqueTopics)
.setMessages(messages)
.build().toByteString());
} catch (IOException e) {
log.warn("Error recording metric data point", e);
}
}
});
List<Client.HostPort> addresses = Lists.newArrayList();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ifc = networkInterfaces.nextElement();
if (!ifc.isLoopback()) {
for (InterfaceAddress address : ifc.getInterfaceAddresses()) {
addresses.add(new Client.HostPort(address.getAddress().getHostAddress(), port));
}
}
}
serverId = new SecureRandom().nextLong();
us = new Server(serverId, addresses);
}
@Override
public Catcher.HelloResponse hello(RpcController controller,
Catcher.Hello request) throws ServiceException {
Catcher.HelloResponse.Builder r = Catcher.HelloResponse.newBuilder()
.setServerId(serverId);
r.addCluster(us.getProto());
r.addAllHost(us.getProto().getHostList());
return r.build();
}
@Override
public Catcher.LogMessageResponse log(RpcController controller, Catcher.LogMessage request) throws ServiceException {
try {
String topic = request.getTopic();
ByteString payload = request.getPayload();
logger.write(topic, payload);
recorder.message(topic);
return Catcher.LogMessageResponse.newBuilder()
.setServerId(serverId)
.setSuccessful(true)
.build();
} catch (IOException e) {
StringWriter s = new StringWriter();
PrintWriter pw = new PrintWriter(s);
e.printStackTrace(pw);
pw.close();
return Catcher.LogMessageResponse
.newBuilder()
.setServerId(serverId)
.setSuccessful(false)
.setBackTrace(s.toString())
.build();
}
}
@Override
public Catcher.CloseResponse close(RpcController controller, Catcher.Close request) throws ServiceException {
log.info("Client {} has closed connection", request.getClientId());
return Catcher.CloseResponse.newBuilder()
.setServerId(serverId)
.build();
}
}