/**
* Licensed to Cloudera, Inc. under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Cloudera, Inc. 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.flume.master;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.avro.ipc.AvroRemoteException;
import org.apache.avro.ipc.HttpServer;
import org.apache.avro.specific.SpecificResponder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cloudera.flume.conf.FlumeConfigData;
import com.cloudera.flume.conf.FlumeConfiguration;
import com.cloudera.flume.conf.avro.AvroFlumeConfigData;
import com.cloudera.flume.conf.avro.CommandStatusAvro;
import com.cloudera.flume.conf.avro.FlumeMasterAdminServerAvro;
import com.cloudera.flume.conf.avro.FlumeMasterCommandAvro;
import com.cloudera.flume.conf.avro.FlumeNodeStatusAvro;
import com.google.common.base.Preconditions;
/**
* Avro implementation of the MasterAdmin server. This is a stub server
* responsible only for listening for requests and function signatures which
* contain Avro-specific types. It delegates all function calls to a
* MasterAdminServer.
*/
public class MasterAdminServerAvro implements FlumeMasterAdminServerAvro,
RPCServer {
// STATIC TYPE CONVERSION METHODS
/**
* Convert from a { @link StatusManager.NodeStatus } object to Avro's { @link
* FlumeNodeStatusAvro }.
*/
public static FlumeNodeStatusAvro statusToAvro(StatusManager.NodeStatus status) {
long time = System.currentTimeMillis();
FlumeNodeStatusAvro out = new FlumeNodeStatusAvro();
out.state = MasterClientServerAvro.stateToAvro(status.state);
out.version = status.version;
out.lastseen = status.lastseen;
out.lastSeenDeltaMillis = time - status.lastseen;
out.host = status.host;
out.physicalNode = status.physicalNode;
return out;
}
/**
* Convert from a { @link FlumeNodeStatusAvro } object to Flume's native { @link
* StatusManager.NodeStatus }.
*/
public static StatusManager.NodeStatus statusFromAvro(
FlumeNodeStatusAvro status) {
return new StatusManager.NodeStatus(MasterClientServerAvro
.stateFromAvro(status.state), status.version, status.lastseen,
status.host.toString(), status.physicalNode.toString());
}
/**
* Convert from a { @link FlumeMasterCommandAvro } object to a { @link Command
* } object.
*/
public static Command commandFromAvro(FlumeMasterCommandAvro cmd) {
String[] args = new String[(int) cmd.arguments.size()];
int index = 0;
for (CharSequence arg : cmd.arguments) {
args[index] = arg.toString();
index++;
}
return new Command(cmd.command.toString(), args);
}
/**
* Convert from a { @link Command } object to a { @link FlumeMasterCommandAvro
* } object.
*/
public static FlumeMasterCommandAvro commandToAvro(Command cmd) {
FlumeMasterCommandAvro out = new FlumeMasterCommandAvro();
out.command = cmd.command;
out.arguments = new ArrayList<CharSequence>();
for (String s : cmd.args) {
out.arguments.add(s);
}
return out;
}
static final Logger LOG = LoggerFactory.getLogger(MasterAdminServerAvro.class);
final int port;
final protected MasterAdminServer delegate;
protected HttpServer server;
public MasterAdminServerAvro(MasterAdminServer delegate) {
Preconditions.checkArgument(delegate != null,
"MasterAdminServer is null in MasterAdminServerAvro!");
this.delegate = delegate;
this.port = FlumeConfiguration.get().getConfigAdminPort();
}
// STUB FUNCTION SIGNATURES
@Override
public Map<CharSequence, AvroFlumeConfigData> getConfigs()
throws AvroRemoteException {
Map<CharSequence, AvroFlumeConfigData> out = new HashMap<CharSequence, AvroFlumeConfigData>();
Map<String, FlumeConfigData> results = this.delegate.getConfigs();
for (String key : results.keySet()) {
AvroFlumeConfigData cfg = MasterClientServerAvro.configToAvro(results
.get(key));
out.put(key, cfg);
}
return out;
}
@Override
public Map<CharSequence, FlumeNodeStatusAvro> getNodeStatuses()
throws AvroRemoteException {
Map<String, StatusManager.NodeStatus> statuses = delegate.getNodeStatuses();
Map<CharSequence, FlumeNodeStatusAvro> ret = new HashMap<CharSequence, FlumeNodeStatusAvro>();
for (Entry<String, StatusManager.NodeStatus> e : statuses.entrySet()) {
ret.put(e.getKey(), statusToAvro(e.getValue()));
}
return ret;
}
@Override
public Map<CharSequence, List<CharSequence>> getMappings(
CharSequence physicalNode) throws AvroRemoteException {
Map<String, List<String>> nativeMappings;
Map<CharSequence, List<CharSequence>> mappings;
nativeMappings = delegate.getMappings(physicalNode.toString());
mappings = new HashMap<CharSequence, List<CharSequence>>();
for (Entry<String, List<String>> entry : nativeMappings.entrySet()) {
ArrayList<CharSequence> values = new ArrayList<CharSequence>(entry
.getValue().size());
for (String value : entry.getValue()) {
values.add(value);
}
mappings.put(entry.getKey(), values);
}
return mappings;
}
@Override
public boolean hasCmdId(long cmdid) throws AvroRemoteException {
return delegate.hasCmdId(cmdid);
}
@Override
public boolean isFailure(long cmdid) throws AvroRemoteException {
return delegate.isFailure(cmdid);
}
@Override
public boolean isSuccess(long cmdid) throws AvroRemoteException {
return delegate.isSuccess(cmdid);
}
@Override
public long submit(FlumeMasterCommandAvro command) throws AvroRemoteException {
return delegate.submit(commandFromAvro(command));
}
// CONTROL FUNCTIONS
@Override
public void serve() throws IOException {
LOG.info(String.format(
"Starting blocking thread pool server for admin server on port %d...",
port));
SpecificResponder res = new SpecificResponder(
FlumeMasterAdminServerAvro.class, this);
this.server = new HttpServer(res, port);
this.server.start();
}
@Override
public void stop() throws IOException {
LOG.info(String.format("Stopping admin server on port %d...", port));
this.server.close();
}
@Override
public CommandStatusAvro getCmdStatus(long cmdid) throws AvroRemoteException {
CommandStatus cmd = delegate.getCommandStatus(cmdid);
Command c = cmd.getCommand();
FlumeMasterCommandAvro fmca = new FlumeMasterCommandAvro();
fmca.command = c.getCommand();
List<CharSequence> l = new ArrayList<CharSequence>();
for (String s : c.getArgs()) {
l.add(s);
}
fmca.arguments = l;
CommandStatusAvro csa = new CommandStatusAvro();
csa.cmdId = cmd.getCmdID();
csa.cmd = fmca;
csa.message = cmd.getMessage();
csa.state = cmd.getState().toString();
return csa;
}
}