/*
* Copyright © 2014 Cask Data, Inc.
*
* 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 co.cask.cdap.internal.app.deploy.pipeline;
import co.cask.cdap.api.app.ApplicationSpecification;
import co.cask.cdap.api.data.stream.StreamBatchReadable;
import co.cask.cdap.api.flow.FlowSpecification;
import co.cask.cdap.api.flow.FlowletConnection;
import co.cask.cdap.api.flow.FlowletDefinition;
import co.cask.cdap.api.mapreduce.MapReduceSpecification;
import co.cask.cdap.api.service.ServiceSpecification;
import co.cask.cdap.api.service.http.HttpServiceHandlerSpecification;
import co.cask.cdap.app.store.Store;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.data2.registry.UsageRegistry;
import co.cask.cdap.pipeline.AbstractStage;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.ProgramType;
import com.google.common.reflect.TypeToken;
import java.net.URI;
/**
*
*/
public class ApplicationRegistrationStage extends AbstractStage<ApplicationWithPrograms> {
private final Store store;
private final UsageRegistry usageRegistry;
public ApplicationRegistrationStage(Store store, UsageRegistry usageRegistry) {
super(TypeToken.of(ApplicationWithPrograms.class));
this.store = store;
this.usageRegistry = usageRegistry;
}
@Override
public void process(ApplicationWithPrograms input) throws Exception {
store.addApplication(input.getId(), input.getSpecification(), input.getLocation());
registerDatasets(input);
emit(input);
}
// 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 app = input.getSpecification();
Id.Application appId = input.getId();
Id.Namespace namespace = appId.getNamespace();
for (FlowSpecification flow : app.getFlows().values()) {
Id.Flow programId = Id.Flow.from(appId, flow.getName());
for (FlowletConnection connection : flow.getConnections()) {
if (connection.getSourceType().equals(FlowletConnection.Type.STREAM)) {
usageRegistry.register(programId, Id.Stream.from(namespace, connection.getSourceName()));
}
}
for (FlowletDefinition flowlet : flow.getFlowlets().values()) {
for (String dataset : flowlet.getDatasets()) {
usageRegistry.register(programId, Id.DatasetInstance.from(namespace, dataset));
}
}
}
for (MapReduceSpecification program : app.getMapReduce().values()) {
Id.Program programId = Id.Program.from(appId, ProgramType.MAPREDUCE, program.getName());
for (String dataset : program.getDataSets()) {
if (!dataset.startsWith(Constants.Stream.URL_PREFIX)) {
usageRegistry.register(programId, Id.DatasetInstance.from(namespace, dataset));
}
}
String inputDatasetName = program.getInputDataSet();
if (inputDatasetName != null && inputDatasetName.startsWith(Constants.Stream.URL_PREFIX)) {
StreamBatchReadable stream = new StreamBatchReadable(URI.create(inputDatasetName));
usageRegistry.register(programId, Id.Stream.from(namespace, stream.getStreamName()));
}
}
for (ServiceSpecification serviceSpecification : app.getServices().values()) {
Id.Service serviceId = Id.Service.from(appId, serviceSpecification.getName());
for (HttpServiceHandlerSpecification handlerSpecification : serviceSpecification.getHandlers().values()) {
for (String dataset : handlerSpecification.getDatasets()) {
usageRegistry.register(serviceId, Id.DatasetInstance.from(namespace, dataset));
}
}
}
}
}