// Copyright 2016 Twitter. All rights reserved.
//
// 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 com.twitter.heron.uploader.localfs;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.logging.Logger;
import com.twitter.heron.common.basics.TypeUtils;
import com.twitter.heron.spi.common.Config;
import com.twitter.heron.spi.common.Context;
import com.twitter.heron.spi.uploader.IUploader;
import com.twitter.heron.spi.uploader.UploaderException;
import com.twitter.heron.spi.utils.UploaderUtils;
public class LocalFileSystemUploader implements IUploader {
private static final Logger LOG = Logger.getLogger(LocalFileSystemUploader.class.getName());
private Config config;
private String destTopologyFile;
private String destTopologyDirectory;
private String topologyPackageLocation;
@Override
public void initialize(Config ipconfig) {
this.config = ipconfig;
this.destTopologyDirectory = LocalFileSystemContext.fileSystemDirectory(config);
// name of the destination file is the same as the base name of the topology package file
String fileName =
UploaderUtils.generateFilename(
Context.topologyName(config), Context.role(config));
this.destTopologyFile = Paths.get(destTopologyDirectory, fileName).toString();
// get the original topology package location
this.topologyPackageLocation = LocalFileSystemContext.topologyPackageFile(config);
}
protected URI getUri(String filename) {
StringBuilder sb = new StringBuilder()
.append("file://")
.append(filename);
return TypeUtils.getURI(sb.toString());
}
/**
* Upload the topology package to the destined location in local file system
*
* @return destination URI of where the topology package has
* been uploaded if successful, or {@code null} if failed.
*/
@Override
public URI uploadPackage() throws UploaderException {
// first, check if the topology package exists
boolean fileExists = new File(topologyPackageLocation).isFile();
if (!fileExists) {
throw new UploaderException(
String.format("Topology package does not exist at '%s'", topologyPackageLocation));
}
// get the directory containing the file
Path filePath = Paths.get(destTopologyFile);
File parentDirectory = filePath.getParent().toFile();
assert parentDirectory != null;
// if the dest directory does not exist, create it.
if (!parentDirectory.exists()) {
LOG.fine(String.format(
"Working directory does not exist. Creating it now at %s", parentDirectory.getPath()));
if (!parentDirectory.mkdirs()) {
throw new UploaderException(
String.format("Failed to create directory for topology package at %s",
parentDirectory.getPath()));
}
}
// if the dest file exists, write a log message
fileExists = new File(filePath.toString()).isFile();
if (fileExists) {
LOG.fine(String.format("Target topology package already exists at '%s'. Overwriting it now",
filePath.toString()));
}
// copy the topology package to target working directory
LOG.fine(String.format("Copying topology package at '%s' to target working directory '%s'",
topologyPackageLocation, filePath.toString()));
Path source = Paths.get(topologyPackageLocation);
try {
CopyOption[] options = new CopyOption[]{StandardCopyOption.REPLACE_EXISTING};
Files.copy(source, filePath, options);
} catch (IOException e) {
throw new UploaderException(
String.format("Unable to copy topology file from '%s' to '%s'",
source, filePath), e);
}
return getUri(destTopologyFile);
}
/**
* Remove the uploaded topology package for cleaning up
*
* @return true, if successful
*/
@Override
public boolean undo() {
LOG.info("Clean uploaded jar");
File file = new File(destTopologyFile);
return file.delete();
}
@Override
public void close() {
}
/**
* Used for unit testing. Get the topology directory where the package
* is uploaded.
*
* @return topology directory
*/
protected String getTopologyDirectory() {
return this.destTopologyDirectory;
}
/**
* Used for unit testing. Get the topology package file
*
* @return topology file
*/
protected String getTopologyFile() {
return this.destTopologyFile;
}
}