/**
* 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.availability;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cloudera.flume.conf.FlumeConfiguration;
/**
* This interface for algorithm implementations that generate a spec with
* failover lists. Implementations are responsible for maintaining state.
*
* In the current incarnation, given a set of collectors, this calculates an
* ordered list of collectors for a particular agent. The interface is pull only
* -- it calculates information and returns information when requested or
* notified of changes. Other mechanism should be responsible for polling for
* the changes.
*
* This assumes global information and should live on the master.
*/
abstract public class FailoverChainManager {
static final Logger LOG = LoggerFactory.getLogger(FailoverChainManager.class);
public FailoverChainManager() {
}
/**
* Get a list of the names of failover nodes for a particular agent.
*/
abstract public List<String> getFailovers(String agent);
/**
* Add a new collector to the system.
*/
abstract public void addCollector(String s);
/**
* Remove a collector to the system.
*/
abstract public void removeCollector(String s);
/**
* Give an agent name, a spec with '%s' escape sequence in it, and an ordered
* list of failovers, generate a the spec for the sink that implements it.
* This is a spec because we want to essentially translate a user-provided
* spec into a concrete spec that will be sent to the agent..
*/
public static String genAvailableSinkSpec(String spec,
List<String> orderedCollectors) {
StringBuilder sb = new StringBuilder();
for (String c : orderedCollectors) {
sb.append(','); // just assume comma on first -- see format string below
sb.append('"');
sb.append(StringEscapeUtils.escapeJava(c));
sb.append('"');
}
String escapedSpec = StringEscapeUtils.escapeJava(spec);
return "failChain(\"" + escapedSpec + "\"" + sb.toString() + ")";
}
/**
* This uses the instance's state to generate a spec
*/
public String getFailChainSinkSpec(String agent, String spec) {
List<String> orderedCollectors = getFailovers(agent);
// no collectors?
if (orderedCollectors.size() == 0) {
String defaultCollector = FlumeConfiguration.get().getCollectorHost();
LOG.warn("No collectors currently, using default collector host: "
+ defaultCollector);
// fall back to default specified in flume-site.xml
// getFailovers returns unmodifiable so we need to create a new list
orderedCollectors = new ArrayList<String>();
orderedCollectors.add(defaultCollector);
}
return genAvailableSinkSpec(spec, orderedCollectors);
}
}