/* * Copyright © 2015-2016 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.data2.metadata.writer; import co.cask.cdap.api.dataset.Dataset; import co.cask.cdap.api.dataset.DatasetManagementException; import co.cask.cdap.api.dataset.DatasetProperties; import co.cask.cdap.data.runtime.DataSetsModules; import co.cask.cdap.data2.audit.AuditPublisher; import co.cask.cdap.data2.audit.AuditPublishers; import co.cask.cdap.data2.datafabric.dataset.type.DatasetClassLoaderProvider; import co.cask.cdap.data2.dataset2.DatasetFramework; import co.cask.cdap.data2.dataset2.ForwardingDatasetFramework; import co.cask.cdap.data2.metadata.lineage.AccessType; import co.cask.cdap.proto.Id; import com.google.inject.Inject; import com.google.inject.name.Named; import java.io.IOException; import java.util.Map; import javax.annotation.Nullable; /** * {@link DatasetFramework} that also records lineage (program-dataset access) records. */ public class LineageWriterDatasetFramework extends ForwardingDatasetFramework implements ProgramContextAware { private final LineageWriter lineageWriter; private final ProgramContext programContext = new ProgramContext(); private AuditPublisher auditPublisher; @Inject public LineageWriterDatasetFramework( @Named(DataSetsModules.BASIC_DATASET_FRAMEWORK) DatasetFramework datasetFramework, LineageWriter lineageWriter) { super(datasetFramework); this.lineageWriter = lineageWriter; } @SuppressWarnings("unused") @Inject(optional = true) public void setAuditPublisher(AuditPublisher auditPublisher) { this.auditPublisher = auditPublisher; } @Override public void initContext(Id.Run run) { programContext.initContext(run); } @Override public void initContext(Id.Run run, Id.NamespacedId componentId) { programContext.initContext(run, componentId); } @Override public void addInstance(String datasetTypeName, Id.DatasetInstance datasetInstanceId, DatasetProperties props) throws DatasetManagementException, IOException { super.addInstance(datasetTypeName, datasetInstanceId, props); } @Override public void updateInstance(Id.DatasetInstance datasetInstanceId, DatasetProperties props) throws DatasetManagementException, IOException { super.updateInstance(datasetInstanceId, props); } @Override public void deleteInstance(Id.DatasetInstance datasetInstanceId) throws DatasetManagementException, IOException { delegate.deleteInstance(datasetInstanceId); } @Override public void deleteAllInstances(Id.Namespace namespaceId) throws DatasetManagementException, IOException { delegate.deleteAllInstances(namespaceId); } @Override @Nullable public <T extends Dataset> T getDataset(Id.DatasetInstance datasetInstanceId, @Nullable Map<String, String> arguments, @Nullable ClassLoader classLoader, @Nullable Iterable<? extends Id> owners) throws DatasetManagementException, IOException { T dataset = super.getDataset(datasetInstanceId, arguments, classLoader, owners); writeLineage(datasetInstanceId, dataset); return dataset; } @Override @Nullable public <T extends Dataset> T getDataset(Id.DatasetInstance datasetInstanceId, @Nullable Map<String, String> arguments, @Nullable ClassLoader classLoader) throws DatasetManagementException, IOException { T dataset = super.getDataset(datasetInstanceId, arguments, classLoader); writeLineage(datasetInstanceId, dataset); return dataset; } @Override @Nullable public <T extends Dataset> T getDataset(Id.DatasetInstance datasetInstanceId, @Nullable Map<String, String> arguments, @Nullable ClassLoader classLoader, DatasetClassLoaderProvider classLoaderProvider, @Nullable Iterable<? extends Id> owners) throws DatasetManagementException, IOException { T dataset = super.getDataset(datasetInstanceId, arguments, classLoader, classLoaderProvider, owners); writeLineage(datasetInstanceId, dataset); return dataset; } @Nullable @Override public <T extends Dataset> T getDataset(Id.DatasetInstance datasetInstanceId, @Nullable Map<String, String> arguments, @Nullable ClassLoader classLoader, DatasetClassLoaderProvider classLoaderProvider, @Nullable Iterable<? extends Id> owners, AccessType accessType) throws DatasetManagementException, IOException { T dataset = super.getDataset(datasetInstanceId, arguments, classLoader, classLoaderProvider, owners, accessType); writeLineage(datasetInstanceId, dataset, accessType); return dataset; } @Override public void writeLineage(Id.DatasetInstance datasetInstanceId, AccessType accessType) { super.writeLineage(datasetInstanceId, accessType); doWriteLineage(datasetInstanceId, accessType); } private <T extends Dataset> void writeLineage(Id.DatasetInstance datasetInstanceId, @Nullable T dataset) { writeLineage(datasetInstanceId, dataset, AccessType.UNKNOWN); } private <T extends Dataset> void writeLineage(Id.DatasetInstance datasetInstanceId, @Nullable T dataset, AccessType accessType) { if (dataset != null) { doWriteLineage(datasetInstanceId, accessType); } } private void doWriteLineage(Id.DatasetInstance datasetInstanceId, AccessType accessType) { if (programContext.getRun() != null) { lineageWriter.addAccess(programContext.getRun(), datasetInstanceId, accessType, programContext.getComponentId()); AuditPublishers.publishAccess(auditPublisher, datasetInstanceId, accessType, programContext.getRun()); } } }