use of co.cask.cdap.api.flow.FlowletDefinition in project cdap by caskdata.
the class ApplicationRegistrationStage method registerDatasets.
// Register dataset usage, based upon the program specifications.
// Note that worker specifications' datasets are not registered upon app deploy because the useDataset of the
// WorkerConfigurer is deprecated. Workers' access to datasets is aimed to be completely dynamic. Other programs are
// moving in this direction.
// Also, SparkSpecifications are the same in that a Spark program's dataset access is completely dynamic.
private void registerDatasets(ApplicationWithPrograms input) {
ApplicationSpecification appSpec = input.getSpecification();
ApplicationId appId = input.getApplicationId();
NamespaceId namespaceId = appId.getParent();
for (FlowSpecification flow : appSpec.getFlows().values()) {
ProgramId programId = appId.flow(flow.getName());
for (FlowletConnection connection : flow.getConnections()) {
if (connection.getSourceType().equals(FlowletConnection.Type.STREAM)) {
usageRegistry.register(programId, namespaceId.stream(connection.getSourceName()));
}
}
for (FlowletDefinition flowlet : flow.getFlowlets().values()) {
for (String dataset : flowlet.getDatasets()) {
usageRegistry.register(programId, namespaceId.dataset(dataset));
}
}
}
for (MapReduceSpecification program : appSpec.getMapReduce().values()) {
ProgramId programId = appId.mr(program.getName());
for (String dataset : program.getDataSets()) {
usageRegistry.register(programId, namespaceId.dataset(dataset));
}
}
for (SparkSpecification sparkSpec : appSpec.getSpark().values()) {
ProgramId programId = appId.spark(sparkSpec.getName());
for (String dataset : sparkSpec.getDatasets()) {
usageRegistry.register(programId, namespaceId.dataset(dataset));
}
}
for (ServiceSpecification serviceSpecification : appSpec.getServices().values()) {
ProgramId programId = appId.service(serviceSpecification.getName());
for (HttpServiceHandlerSpecification handlerSpecification : serviceSpecification.getHandlers().values()) {
for (String dataset : handlerSpecification.getDatasets()) {
usageRegistry.register(programId, namespaceId.dataset(dataset));
}
}
}
}
use of co.cask.cdap.api.flow.FlowletDefinition in project cdap by caskdata.
the class FlowletProgramRunner method run.
@SuppressWarnings("unchecked")
@Override
public ProgramController run(Program program, ProgramOptions options) {
BasicFlowletContext flowletContext = null;
try {
// Extract and verify parameters
String flowletName = options.getName();
int instanceId = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCE_ID, "-1"));
Preconditions.checkArgument(instanceId >= 0, "Missing instance Id");
int instanceCount = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCES, "0"));
Preconditions.checkArgument(instanceCount > 0, "Invalid or missing instance count");
RunId runId = ProgramRunners.getRunId(options);
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType processorType = program.getType();
Preconditions.checkNotNull(processorType, "Missing processor type.");
Preconditions.checkArgument(processorType == ProgramType.FLOW, "Only FLOW process type is supported.");
String processorName = program.getName();
Preconditions.checkNotNull(processorName, "Missing processor name.");
FlowSpecification flowSpec = appSpec.getFlows().get(processorName);
FlowletDefinition flowletDef = flowSpec.getFlowlets().get(flowletName);
Preconditions.checkNotNull(flowletDef, "Definition missing for flowlet \"%s\"", flowletName);
Class<?> clz = Class.forName(flowletDef.getFlowletSpec().getClassName(), true, program.getClassLoader());
Preconditions.checkArgument(Flowlet.class.isAssignableFrom(clz), "%s is not a Flowlet.", clz);
// Setup dataset framework context, if required
ProgramId programId = program.getId();
FlowletId flowletId = programId.flowlet(flowletName);
ProgramRunId run = programId.run(runId);
ProgramContext programContext = new BasicProgramContext(run, flowletId);
if (dsFramework instanceof ProgramContextAware) {
((ProgramContextAware) dsFramework).setContext(programContext);
}
Class<? extends Flowlet> flowletClass = (Class<? extends Flowlet>) clz;
// Creates flowlet context
flowletContext = new BasicFlowletContext(program, options, flowletId, instanceId, instanceCount, flowletDef.getDatasets(), flowletDef.getFlowletSpec(), metricsCollectionService, discoveryServiceClient, txClient, dsFramework, secureStore, secureStoreManager, messageService, cConf);
// Creates tx related objects
DataFabricFacade dataFabricFacade = dataFabricFacadeFactory.create(program, flowletContext.getDatasetCache());
if (dataFabricFacade instanceof ProgramContextAware) {
((ProgramContextAware) dataFabricFacade).setContext(programContext);
}
// Creates QueueSpecification
Table<Node, String, Set<QueueSpecification>> queueSpecs = new SimpleQueueSpecificationGenerator(new ApplicationId(program.getNamespaceId(), program.getApplicationId())).create(flowSpec);
Flowlet flowlet = new InstantiatorFactory(false).get(TypeToken.of(flowletClass)).create();
TypeToken<? extends Flowlet> flowletType = TypeToken.of(flowletClass);
// Set the context classloader to the cdap classloader. It is needed for the DatumWriterFactory be able
// to load cdap classes
Thread.currentThread().setContextClassLoader(FlowletProgramRunner.class.getClassLoader());
// Inject DataSet, OutputEmitter, Metric fields
ImmutableList.Builder<ProducerSupplier> queueProducerSupplierBuilder = ImmutableList.builder();
Reflections.visit(flowlet, flowlet.getClass(), new PropertyFieldSetter(flowletDef.getFlowletSpec().getProperties()), new DataSetFieldSetter(flowletContext), new MetricsFieldSetter(flowletContext.getMetrics()), new OutputEmitterFieldSetter(outputEmitterFactory(flowletContext, flowletName, dataFabricFacade, queueProducerSupplierBuilder, queueSpecs)));
ImmutableList.Builder<ConsumerSupplier<?>> queueConsumerSupplierBuilder = ImmutableList.builder();
Collection<ProcessSpecification<?>> processSpecs = createProcessSpecification(flowletContext, flowletType, processMethodFactory(flowlet), processSpecificationFactory(flowletContext, dataFabricFacade, queueReaderFactory, flowletName, queueSpecs, queueConsumerSupplierBuilder, createSchemaCache(program)), Lists.<ProcessSpecification<?>>newLinkedList());
List<ConsumerSupplier<?>> consumerSuppliers = queueConsumerSupplierBuilder.build();
// Create the flowlet driver
AtomicReference<FlowletProgramController> controllerRef = new AtomicReference<>();
Service serviceHook = createServiceHook(flowletName, consumerSuppliers, controllerRef);
FlowletRuntimeService driver = new FlowletRuntimeService(flowlet, flowletContext, processSpecs, createCallback(flowlet, flowletDef.getFlowletSpec()), dataFabricFacade, serviceHook);
FlowletProgramController controller = new FlowletProgramController(program.getId(), flowletName, flowletContext, driver, queueProducerSupplierBuilder.build(), consumerSuppliers);
controllerRef.set(controller);
LOG.info("Starting flowlet: {}", flowletContext);
driver.start();
LOG.info("Flowlet started: {}", flowletContext);
return controller;
} catch (Exception e) {
// of the flowlet context.
if (flowletContext != null) {
flowletContext.close();
}
throw Throwables.propagate(e);
}
}
use of co.cask.cdap.api.flow.FlowletDefinition in project cdap by caskdata.
the class FlowUtils method getAllConsumerGroups.
/**
* Gets all consumer group configurations for the given queue.
*/
private static Set<ConsumerGroupConfig> getAllConsumerGroups(Program program, FlowSpecification flowSpec, QueueName queueName, Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs) {
Set<ConsumerGroupConfig> groupConfigs = Sets.newHashSet();
SchemaGenerator schemaGenerator = new ReflectionSchemaGenerator();
// Get all the consumers of this queue.
for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
String flowletId = entry.getKey();
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
if (!queueSpec.getQueueName().equals(queueName)) {
continue;
}
try {
// Inspect the flowlet consumer
FlowletDefinition flowletDefinition = entry.getValue();
Class<?> flowletClass = program.getClassLoader().loadClass(flowletDefinition.getFlowletSpec().getClassName());
long groupId = generateConsumerGroupId(program.getId(), flowletId);
addConsumerGroup(queueSpec, flowletClass, groupId, flowletDefinition.getInstances(), schemaGenerator, groupConfigs);
} catch (ClassNotFoundException e) {
// There is no way for not able to load a Flowlet class as it should be verified during deployment.
throw Throwables.propagate(e);
}
}
}
return groupConfigs;
}
use of co.cask.cdap.api.flow.FlowletDefinition in project cdap by caskdata.
the class FlowUtils method configureQueue.
/**
* Configures all queues being used in a flow.
*
* @return A Multimap from flowletId to QueueName where the flowlet is a consumer of.
*/
public static Multimap<String, QueueName> configureQueue(Program program, FlowSpecification flowSpec, final StreamAdmin streamAdmin, QueueAdmin queueAdmin, TransactionExecutorFactory txExecutorFactory) {
// Generate all queues specifications
ApplicationId appId = new ApplicationId(program.getNamespaceId(), program.getApplicationId());
Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs = new SimpleQueueSpecificationGenerator(appId).create(flowSpec);
// For each queue in the flow, gather all consumer groups information
Multimap<QueueName, ConsumerGroupConfig> queueConfigs = HashMultimap.create();
// Loop through each flowlet and generate the map from consumer flowlet id to queue
ImmutableSetMultimap.Builder<String, QueueName> resultBuilder = ImmutableSetMultimap.builder();
for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
String flowletId = entry.getKey();
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
resultBuilder.put(flowletId, queueSpec.getQueueName());
}
}
// For each queue, gather all consumer groups.
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.values())) {
QueueName queueName = queueSpec.getQueueName();
queueConfigs.putAll(queueName, getAllConsumerGroups(program, flowSpec, queueName, queueSpecs));
}
try {
// Configure each stream consumer in the Flow. Also collects all queue configurers.
final List<ConsumerGroupConfigurer> groupConfigurers = Lists.newArrayList();
final Map<StreamId, Map<Long, Integer>> streamConfigurers = Maps.newHashMap();
for (Map.Entry<QueueName, Collection<ConsumerGroupConfig>> entry : queueConfigs.asMap().entrySet()) {
LOG.info("Queue config for {} : {}", entry.getKey(), entry.getValue());
if (entry.getKey().isStream()) {
Map<Long, Integer> configs = Maps.newHashMap();
for (ConsumerGroupConfig config : entry.getValue()) {
configs.put(config.getGroupId(), config.getGroupSize());
}
streamConfigurers.put(entry.getKey().toStreamId(), configs);
} else {
groupConfigurers.add(new ConsumerGroupConfigurer(queueAdmin.getQueueConfigurer(entry.getKey()), entry.getValue()));
}
}
// Configure queue transactionally
try {
Transactions.createTransactionExecutor(txExecutorFactory, groupConfigurers).execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
for (ConsumerGroupConfigurer configurer : groupConfigurers) {
configurer.configure();
}
for (Map.Entry<StreamId, Map<Long, Integer>> entry : streamConfigurers.entrySet()) {
streamAdmin.configureGroups(entry.getKey(), entry.getValue());
}
}
});
} finally {
for (ConsumerGroupConfigurer configurer : groupConfigurers) {
Closeables.closeQuietly(configurer);
}
}
return resultBuilder.build();
} catch (Exception e) {
LOG.error("Failed to configure queues", e);
throw Throwables.propagate(e);
}
}
Aggregations