blob: d4faa38f4cd5923ed3e95faaf5edd7aff0f8489b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.ignite.yarn;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.ignite.yarn.utils.IgniteYarnUtils;
/**
* Downloads and stores Ignite.
*/
public class IgniteProvider {
/** */
public static final String DOWNLOAD_LINK = "http://tiny.cc/updater/download_community.php";
/** */
private ClusterProperties props;
/** */
private String latestVersion = null;
/** */
private boolean hdfs = false;
/** */
private FileSystem fs;
/**
* @param props Cluster properties.
* @param fs Hadoop file system.
*/
public IgniteProvider(ClusterProperties props, FileSystem fs) {
this.props = props;
this.fs = fs;
}
/**
* @return Latest ignite version.
*/
public Path getIgnite() throws Exception {
File folder = checkDownloadFolder();
if (latestVersion == null) {
List<String> localFiles = findIgnites(folder);
List<String> hdfsFiles = findIgnites(fs, props.igniteReleasesDir());
String localLatestVersion = findLatestVersion(localFiles);
String hdfsLatestVersion = findLatestVersion(hdfsFiles);
if (localLatestVersion != null && hdfsLatestVersion != null) {
if (VersionComparator.INSTANCE.compare(hdfsLatestVersion, localLatestVersion) >= 0) {
latestVersion = hdfsLatestVersion;
hdfs = true;
}
}
else if (localLatestVersion != null)
latestVersion = localLatestVersion;
else if (hdfsLatestVersion != null) {
latestVersion = hdfsLatestVersion;
hdfs = true;
}
}
String newVersion = updateIgnite(latestVersion);
if (latestVersion != null && newVersion.equals(latestVersion)) {
if (hdfs)
return new Path(formatPath(props.igniteReleasesDir(), latestVersion));
else
return IgniteYarnUtils.copyLocalToHdfs(fs, formatPath(props.igniteLocalWorkDir(), latestVersion),
formatPath(props.igniteReleasesDir(), latestVersion));
}
else {
latestVersion = newVersion;
return IgniteYarnUtils.copyLocalToHdfs(fs, formatPath(props.igniteLocalWorkDir(), latestVersion),
formatPath(props.igniteReleasesDir(), latestVersion));
}
}
/**
* @param folder Folder.
* @return Ignite archives.
*/
private List<String> findIgnites(File folder) {
String[] files = folder.list();
List<String> ignites = new ArrayList<>();
if (files != null) {
for (String fileName : files) {
if (fileName.contains("gridgain-professional-") && fileName.endsWith(".zip"))
ignites.add(fileName);
}
}
return ignites;
}
/**
* @param files Files.
* @return latest ignite version.
*/
private String findLatestVersion(List<String> files) {
String latestVersion = null;
if (!files.isEmpty()) {
if (files.size() == 1)
latestVersion = parseVersion(files.get(0));
else
latestVersion = parseVersion(Collections.max(files, VersionComparator.INSTANCE));
}
return latestVersion;
}
/**
* @param fs File system,
* @param folder Folder.
* @return Ignite archives.
*/
private List<String> findIgnites(FileSystem fs, String folder) {
FileStatus[] fileStatuses = null;
try {
fileStatuses = fs.listStatus(new Path(folder));
}
catch (FileNotFoundException ignored) {
// Ignore. Folder doesn't exist.
}
catch (Exception e) {
throw new RuntimeException("Couldnt get list files from hdfs.", e);
}
List<String> ignites = new ArrayList<>();
if (fileStatuses != null) {
for (FileStatus file : fileStatuses) {
String fileName = file.getPath().getName();
if (fileName.contains("gridgain-professional-") && fileName.endsWith(".zip"))
ignites.add(fileName);
}
}
return ignites;
}
/**
* @param version Ignite version.
* @return Ignite.
*/
public Path getIgnite(String version) throws Exception {
checkDownloadFolder();
// Download ignite.
String fileName = downloadIgnite(version);
Path dst = new Path(props.igniteReleasesDir() + File.separator + fileName);
if (!fs.exists(dst))
fs.copyFromLocalFile(new Path(props.igniteLocalWorkDir() + File.separator + fileName), dst);
return dst;
}
/**
* @param folder folder
* @param version version
* @return Path
*/
private static String formatPath(String folder, String version) {
return folder + File.separator + "gridgain-professional-" + version + ".zip";
}
/**
* @param currentVersion The current latest version.
* @return Current version if the current version is latest; new ignite version otherwise.
*/
private String updateIgnite(String currentVersion) {
try {
URL url;
if (currentVersion == null)
url = new URL(DOWNLOAD_LINK);
else
url = new URL(DOWNLOAD_LINK + "?version=" + currentVersion);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
int code = conn.getResponseCode();
if (code == 200) {
String redirectUrl = conn.getURL().toString();
checkDownloadFolder();
FileOutputStream outFile = new FileOutputStream(props.igniteLocalWorkDir() + File.separator
+ fileName(redirectUrl));
outFile.getChannel().transferFrom(Channels.newChannel(conn.getInputStream()), 0, Long.MAX_VALUE);
outFile.close();
return parseVersion(redirectUrl);
}
else if (code == 304)
// This version is latest.
return currentVersion;
else
throw new RuntimeException("Got unexpected response code. Response code: " + code);
}
catch (IOException e) {
throw new RuntimeException("Failed update ignite.", e);
}
}
/**
* @param igniteUrl Url to ignite.
* @return Ignite file name.
*/
private String downloadIgnite(String igniteUrl) {
try {
URL url = new URL(igniteUrl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
int code = conn.getResponseCode();
if (code == 200) {
String fileName = fileName(url.toString());
String filePath = props.igniteLocalWorkDir() + File.separator + fileName;
if (new File(filePath).exists())
return fileName;
FileOutputStream outFile = new FileOutputStream(filePath);
outFile.getChannel().transferFrom(Channels.newChannel(conn.getInputStream()), 0, Long.MAX_VALUE);
outFile.close();
return fileName;
}
else
throw new RuntimeException("Got unexpected response code. Response code: " + code);
}
catch (IOException e) {
throw new RuntimeException("Failed update ignite.", e);
}
}
/**
* @return Download folder.
*/
private File checkDownloadFolder() {
File file = new File(props.igniteLocalWorkDir());
if (!file.exists())
file.mkdirs();
if (!file.exists())
throw new RuntimeException("Couldn't create local directory! Path: " + file.toURI());
return file;
}
/**
* @param url URL.
* @return Ignite version.
*/
private static String parseVersion(String url) {
String[] split = url.split("-");
return split[split.length - 1].replaceAll(".zip", "");
}
/**
* @param url URL.
* @return File name.
*/
private static String fileName(String url) {
String[] split = url.split("/");
return split[split.length - 1];
}
/**
* Ignite version comparator.
*/
public static final class VersionComparator implements Comparator<String> {
/** */
public static final VersionComparator INSTANCE = new VersionComparator();
/** */
private VersionComparator() {
// No-op.
}
/** {@inheritDoc} */
@Override public int compare(String f1, String f2) {
if (f1.equals(f2))
return 0;
String[] ver1 = parseVersion(f1).split("\\.");
String[] ver2 = parseVersion(f2).split("\\.");
if (Integer.valueOf(ver1[0]) >= Integer.valueOf(ver2[0])
&& Integer.valueOf(ver1[1]) >= Integer.valueOf(ver2[1])
&& Integer.valueOf(ver1[2]) >= Integer.valueOf(ver2[2]))
return 1;
else
return -1;
}
}
}