chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.common.resources;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.deeplearning4j.config.DL4JSystemProperties;
|
||||
import org.nd4j.common.base.Preconditions;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class DL4JResources {
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link DL4JSystemProperties#DL4J_RESOURCES_DIR_PROPERTY}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String DL4J_RESOURCES_DIR_PROPERTY = DL4JSystemProperties.DL4J_RESOURCES_DIR_PROPERTY;
|
||||
/**
|
||||
* @deprecated Use {@link DL4JSystemProperties#DL4J_RESOURCES_BASE_URL_PROPERTY}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String DL4J_BASE_URL_PROPERTY = DL4JSystemProperties.DL4J_RESOURCES_BASE_URL_PROPERTY;
|
||||
private static final String DL4J_DEFAULT_URL = "https://dl4jdata.blob.core.windows.net/";
|
||||
|
||||
private static File baseDirectory;
|
||||
private static String baseURL;
|
||||
|
||||
static {
|
||||
resetBaseDirectoryLocation();
|
||||
|
||||
String property = System.getProperty(DL4JSystemProperties.DL4J_RESOURCES_BASE_URL_PROPERTY);
|
||||
if(property != null){
|
||||
baseURL = property;
|
||||
} else {
|
||||
baseURL = DL4J_DEFAULT_URL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base download URL for (most) DL4J datasets and models.<br>
|
||||
* This usually doesn't need to be set manually unless there is some issue with the default location
|
||||
* @param baseDownloadURL Base download URL to set. For example, https://dl4jdata.blob.core.windows.net/
|
||||
*/
|
||||
public static void setBaseDownloadURL(@NonNull String baseDownloadURL){
|
||||
baseURL = baseDownloadURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The base URL hosting DL4J datasets and models
|
||||
*/
|
||||
public static String getBaseDownloadURL(){
|
||||
return baseURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL relative to the base URL.<br>
|
||||
* For example, if baseURL is "https://dl4jdata.blob.core.windows.net/", and relativeToBase is "/datasets/iris.dat"
|
||||
* this simply returns "https://dl4jdata.blob.core.windows.net/datasets/iris.dat"
|
||||
*
|
||||
* @param relativeToBase Relative URL
|
||||
* @return URL
|
||||
* @throws MalformedURLException For bad URL
|
||||
*/
|
||||
public static URL getURL(String relativeToBase) throws MalformedURLException {
|
||||
return new URL(getURLString(relativeToBase));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL relative to the base URL as a String.<br>
|
||||
* For example, if baseURL is "https://dl4jdata.blob.core.windows.net/", and relativeToBase is "/datasets/iris.dat"
|
||||
* this simply returns "https://dl4jdata.blob.core.windows.net/datasets/iris.dat"
|
||||
*
|
||||
* @param relativeToBase Relative URL
|
||||
* @return URL
|
||||
* @throws MalformedURLException For bad URL
|
||||
*/
|
||||
public static String getURLString(String relativeToBase) {
|
||||
if(relativeToBase.startsWith("/")){
|
||||
relativeToBase = relativeToBase.substring(1);
|
||||
}
|
||||
return baseURL + relativeToBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to the default directory, or the directory set via the {@link DL4JSystemProperties#DL4J_RESOURCES_DIR_PROPERTY} system property,
|
||||
* org.deeplearning4j.resources.directory
|
||||
*/
|
||||
public static void resetBaseDirectoryLocation(){
|
||||
String property = System.getProperty(DL4JSystemProperties.DL4J_RESOURCES_DIR_PROPERTY);
|
||||
if(property != null){
|
||||
baseDirectory = new File(property);
|
||||
} else {
|
||||
baseDirectory = new File(System.getProperty("user.home"), ".deeplearning4j");
|
||||
}
|
||||
|
||||
if(!baseDirectory.exists()){
|
||||
baseDirectory.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base directory for local storage of files. Default is: {@code new File(System.getProperty("user.home"), ".deeplearning4j")}
|
||||
* @param f Base directory to use for resources
|
||||
*/
|
||||
public static void setBaseDirectory(@NonNull File f){
|
||||
Preconditions.checkState(f.exists() && f.isDirectory(), "Specified base directory does not exist and/or is not a directory: %s", f.getAbsolutePath());
|
||||
baseDirectory = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The base storage directory for DL4J resources
|
||||
*/
|
||||
public static File getBaseDirectory(){
|
||||
return baseDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the storage location for the specified resource type and resource name
|
||||
* @param resourceType Type of resource
|
||||
* @param resourceName Name of the resource
|
||||
* @return The root directory. Creates the directory and any parent directories, if required
|
||||
*/
|
||||
public static File getDirectory(ResourceType resourceType, String resourceName){
|
||||
File f = new File(baseDirectory, resourceType.resourceName());
|
||||
f = new File(f, resourceName);
|
||||
f.mkdirs();
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.common.resources;
|
||||
|
||||
public enum ResourceType {
|
||||
|
||||
DATASET,
|
||||
ZOO_MODEL,
|
||||
RESOURCE;
|
||||
|
||||
public String resourceName(){
|
||||
switch (this){
|
||||
case DATASET:
|
||||
return "data";
|
||||
case ZOO_MODEL:
|
||||
return "models";
|
||||
case RESOURCE:
|
||||
return "resources";
|
||||
default:
|
||||
return this.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.common.util;
|
||||
|
||||
import org.deeplearning4j.config.DL4JSystemProperties;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ND4JFileUtils {
|
||||
|
||||
private ND4JFileUtils(){ }
|
||||
|
||||
/**
|
||||
* Create a temporary file in the location specified by {@link DL4JSystemProperties#DL4J_TEMP_DIR_PROPERTY} if set,
|
||||
* or the default temporary directory (usually specified by java.io.tmpdir system property)
|
||||
* @param prefix Prefix for generating file's name; must be at least 3 characeters
|
||||
* @param suffix Suffix for generating file's name; may be null (".tmp" will be used if null)
|
||||
* @return A temporary file
|
||||
*/
|
||||
public static File createTempFile(String prefix, String suffix) {
|
||||
String p = System.getProperty(DL4JSystemProperties.DL4J_TEMP_DIR_PROPERTY);
|
||||
try {
|
||||
if (p == null || p.isEmpty()) {
|
||||
return File.createTempFile(prefix, suffix);
|
||||
} else {
|
||||
return File.createTempFile(prefix, suffix, new File(p));
|
||||
}
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException("Error creating temporary file", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nd4j.common.base.Preconditions;
|
||||
import org.nd4j.common.config.ND4JClassLoading;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
@Slf4j
|
||||
public class DL4JClassLoading {
|
||||
private static ClassLoader dl4jClassloader = ND4JClassLoading.getNd4jClassloader();
|
||||
|
||||
private DL4JClassLoading() {
|
||||
}
|
||||
|
||||
public static ClassLoader getDl4jClassloader() {
|
||||
return DL4JClassLoading.dl4jClassloader;
|
||||
}
|
||||
|
||||
public static void setDl4jClassloaderFromClass(Class<?> clazz) {
|
||||
setDl4jClassloader(clazz.getClassLoader());
|
||||
}
|
||||
|
||||
public static void setDl4jClassloader(ClassLoader dl4jClassloader) {
|
||||
DL4JClassLoading.dl4jClassloader = dl4jClassloader;
|
||||
log.debug("Global class-loader for DL4J was changed.");
|
||||
}
|
||||
|
||||
public static boolean classPresentOnClasspath(String className) {
|
||||
return classPresentOnClasspath(className, dl4jClassloader);
|
||||
}
|
||||
|
||||
public static boolean classPresentOnClasspath(String className, ClassLoader classLoader) {
|
||||
return loadClassByName(className, false, classLoader) != null;
|
||||
}
|
||||
|
||||
public static <T> Class<T> loadClassByName(String className) {
|
||||
return loadClassByName(className, true, dl4jClassloader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> loadClassByName(String className, boolean initialize, ClassLoader classLoader) {
|
||||
try {
|
||||
return (Class<T>) Class.forName(className, initialize, classLoader);
|
||||
} catch (ClassNotFoundException classNotFoundException) {
|
||||
log.error(String.format("Cannot find class [%s] of provided class-loader.", className));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T createNewInstance(String className) {
|
||||
return createNewInstance(className, Object.class, new Object[0]);//or null;
|
||||
}
|
||||
|
||||
public static <T> T createNewInstance(String className, Object[] args) {
|
||||
|
||||
return createNewInstance(className, Object.class, args);
|
||||
}
|
||||
|
||||
public static <T> T createNewInstance(String className, Class<? super T> superclass) {
|
||||
return createNewInstance(className, superclass, new Class<?>[]{}, new Object[]{});
|
||||
}
|
||||
|
||||
public static <T> T createNewInstance(String className, Class<? super T> superclass, Object[] args) {
|
||||
Class<?>[] parameterTypes = new Class<?>[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object arg = args[i];
|
||||
Objects.requireNonNull(arg);
|
||||
parameterTypes[i] = arg.getClass();
|
||||
}
|
||||
|
||||
return createNewInstance(className, superclass, parameterTypes, args);
|
||||
}
|
||||
|
||||
public static <T> T createNewInstance(
|
||||
String className,
|
||||
Class<? super T> superclass,
|
||||
Class<?>[] parameterTypes,
|
||||
Object [] args) {
|
||||
try {
|
||||
Class<Object> loadedClass = DL4JClassLoading
|
||||
.loadClassByName(className);
|
||||
Preconditions.checkNotNull(loadedClass,"Attempted to load class " + className + " but failed. No class found with this name.");
|
||||
return (T) loadedClass
|
||||
.asSubclass(superclass)
|
||||
.getDeclaredConstructor(parameterTypes)
|
||||
.newInstance(args);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException
|
||||
| NoSuchMethodException instantiationException) {
|
||||
log.error(String.format("Cannot create instance of class '%s'.", className), instantiationException);
|
||||
throw new RuntimeException(instantiationException);
|
||||
}
|
||||
}
|
||||
|
||||
public static <S> ServiceLoader<S> loadService(Class<S> serviceClass) {
|
||||
return loadService(serviceClass, dl4jClassloader);
|
||||
}
|
||||
|
||||
public static <S> ServiceLoader<S> loadService(Class<S> serviceClass, ClassLoader classLoader) {
|
||||
return ServiceLoader.load(serviceClass, classLoader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.config;
|
||||
|
||||
public class DL4JEnvironmentVars {
|
||||
|
||||
private DL4JEnvironmentVars(){ }
|
||||
|
||||
|
||||
/**
|
||||
* Applicability: Module dl4j-spark-parameterserver_2.xx<br>
|
||||
* Usage: A fallback for determining the local IP for a Spark training worker, if other approaches
|
||||
* fail to determine the local IP
|
||||
*/
|
||||
public static final String DL4J_VOID_IP = "DL4J_VOID_IP";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.deeplearning4j.config;
|
||||
|
||||
public class DL4JSystemProperties {
|
||||
|
||||
private DL4JSystemProperties(){ }
|
||||
|
||||
/**
|
||||
* Applicability: DL4J ModelSerializer, ModelGuesser, Keras model import<br>
|
||||
* Description: Specify the local directory where temporary files will be written. If not specified, the default
|
||||
* Java temporary directory (java.io.tmpdir system property) will generally be used.
|
||||
*/
|
||||
public static final String DL4J_TEMP_DIR_PROPERTY = "org.deeplearning4j.tempdir";
|
||||
|
||||
/**
|
||||
* Applicability: Numerous modules, including deeplearning4j-datasets and deeplearning4j-zoo<br>
|
||||
* Description: Used to set the local location for downloaded remote resources such as datasets (like MNIST) and
|
||||
* pretrained models in the model zoo. Default value is set via {@code new File(System.getProperty("user.home"), ".deeplearning4j")}.
|
||||
* Setting this can be useful if the system drive has limited space/performance, a shared location for all users
|
||||
* should be used instead, or if user.home isn't set for some reason.
|
||||
*/
|
||||
public static final String DL4J_RESOURCES_DIR_PROPERTY = "org.deeplearning4j.resources.directory";
|
||||
|
||||
/**
|
||||
* Applicability: Numerous modules, including deeplearning4j-datasets and deeplearning4j-zoo<br>
|
||||
* Description: Used to set the base URL for hosting of resources such as datasets (like MNIST) and pretrained
|
||||
* models in the model zoo. This is provided as a fallback in case the location of these files changes; it
|
||||
* also allows for (in principle) a local mirror of these files.<br>
|
||||
* NOTE: Changing this to a location without the same files and file structure as the DL4J resource hosting is likely
|
||||
* to break external resource dowloading in DL4J!
|
||||
*/
|
||||
public static final String DL4J_RESOURCES_BASE_URL_PROPERTY = "org.deeplearning4j.resources.baseurl";
|
||||
|
||||
/**
|
||||
* Applicability: deeplearning4j-nn<br>
|
||||
* Description: DL4J writes some crash dumps to disk when an OOM exception occurs - this functionality is enabled
|
||||
* by default. This is to help users identify the cause of the OOM - i.e., where native memory is actually consumed.
|
||||
* This system property can be used to disable memory crash reporting.
|
||||
* @see #CRASH_DUMP_OUTPUT_DIRECTORY_PROPERTY For configuring the output directory
|
||||
*/
|
||||
public static final String CRASH_DUMP_ENABLED_PROPERTY = "org.deeplearning4j.crash.reporting.enabled";
|
||||
|
||||
/**
|
||||
* Applicability: deeplearning4j-nn<br>
|
||||
* Description: DL4J writes some crash dumps to disk when an OOM exception occurs - this functionality is enabled
|
||||
* by default. This system property can be use to customize the output directory for memory crash reporting. By default,
|
||||
* the current working directory ({@code System.getProperty("user.dir")} or {@code new File("")}) will be used
|
||||
* @see #CRASH_DUMP_ENABLED_PROPERTY To disable crash dump reporting
|
||||
*/
|
||||
public static final String CRASH_DUMP_OUTPUT_DIRECTORY_PROPERTY = "org.deeplearning4j.crash.reporting.directory";
|
||||
|
||||
/**
|
||||
* Applicability: deeplearning4j-ui<br>
|
||||
* Description: The DL4J training UI (StatsListener + UIServer.getInstance().attach(ss)) will subsample the number
|
||||
* of chart points when a lot of data is present - i.e., only a maximum number of points will be shown on each chart.
|
||||
* This is to reduce the UI bandwidth requirements and client-side rendering cost.
|
||||
* To increase the number of points in charts, set this property to a larger value. Default: 512 values
|
||||
*/
|
||||
public static final String CHART_MAX_POINTS_PROPERTY = "org.deeplearning4j.ui.maxChartPoints";
|
||||
|
||||
|
||||
/**
|
||||
* Applicability: deeplearning4j-vertx (deeplearning4j-ui)<br>
|
||||
* Description: This property sets the port that the UI will be available on. Default port: 9000.
|
||||
* Set to 0 for a random port.
|
||||
*/
|
||||
public static final String UI_SERVER_PORT_PROPERTY = "org.deeplearning4j.ui.port";
|
||||
|
||||
/**
|
||||
* Applicability: dl4j-spark_2.xx - NTPTimeSource class (mainly used in ParameterAveragingTrainingMaster when stats
|
||||
* collection is enabled; not enabled by default)<br>
|
||||
* Description: This sets the NTP (network time protocol) server to be used when collecting stats. Default: 0.pool.ntp.org
|
||||
*/
|
||||
public static final String NTP_SOURCE_SERVER_PROPERTY = "org.deeplearning4j.spark.time.NTPTimeSource.server";
|
||||
|
||||
/**
|
||||
* Applicability: dl4j-spark_2.xx - NTPTimeSource class (mainly used in ParameterAveragingTrainingMaster when stats
|
||||
* collection is enabled; not enabled by default)<br>
|
||||
* Description: This sets the NTP (network time protocol) update frequency in milliseconds. Default: 1800000 (30 minutes)
|
||||
*/
|
||||
public static final String NTP_SOURCE_UPDATE_FREQUENCY_MS_PROPERTY = "org.deeplearning4j.spark.time.NTPTimeSource.frequencyms";
|
||||
|
||||
/**
|
||||
* Applicability: dl4j-spark_2.xx - mainly used in ParameterAveragingTrainingMaster when stats collection is enabled;
|
||||
* not enabled by default<br>
|
||||
* Description: This sets the time source to use for spark stats. Default: {@code org.deeplearning4j.spark.time.NTPTimeSource}
|
||||
*/
|
||||
public static final String TIMESOURCE_CLASSNAME_PROPERTY = "org.deeplearning4j.spark.time.TimeSource";
|
||||
|
||||
|
||||
/**
|
||||
* Applicability: {@code org.deeplearning4j.nn.layers.HelperUtils}
|
||||
* Used in whether to disable the helpers or not.
|
||||
*/
|
||||
public static final String DISABLE_HELPER_PROPERTY = "org.eclipse.deeplearning4j.helpers.disable";
|
||||
public final static String HELPER_DISABLE_DEFAULT_VALUE = "true";
|
||||
|
||||
/**
|
||||
* Applicability: NLP SkipGram and CBOW
|
||||
* modules controlling the max cache size
|
||||
* for on heap parameters such as learning rates and random values.
|
||||
*/
|
||||
public static final String NLP_CACHE_SIZE = "org.eclipse.deeplearning4j.nlp.cachesize";
|
||||
|
||||
/**
|
||||
* Applicability: NLP SkipGram and CBOW
|
||||
* modules controlling the max queue size
|
||||
* for each cache value.
|
||||
*/
|
||||
public static final String NLP_QUEUE_SIZE = "org.eclipse.deeplearning4j.nlp.queuesize";
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.deeplearning4j.omnihub;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class OmnihubConfig {
|
||||
|
||||
public final static String OMNIHUB_HOME = "OMNIHUB_HOME";
|
||||
public final static String OMNIHUB_URL = "OMNIHUB_URL";
|
||||
public static final String DEFAULT_OMNIHUB_URL = "https://raw.githubusercontent.com/KonduitAI/omnihub-zoo/main";
|
||||
|
||||
/**
|
||||
* Return the omnihub hurl defaulting to
|
||||
* {@link #DEFAULT_OMNIHUB_URL}
|
||||
* if the {@link #OMNIHUB_URL} is not specified.
|
||||
* @return
|
||||
*/
|
||||
public static String getOmnihubUrl() {
|
||||
if(System.getenv(OMNIHUB_URL) != null) {
|
||||
return System.getenv(OMNIHUB_URL);
|
||||
} else {
|
||||
return DEFAULT_OMNIHUB_URL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the default omnihub home at $USER/.omnihub or
|
||||
* value of the environment variable {@link #OMNIHUB_HOME} if applicable
|
||||
* @return
|
||||
*/
|
||||
public static File getOmnihubHome() {
|
||||
if(System.getenv(OMNIHUB_HOME) != null) {
|
||||
return new File(OMNIHUB_HOME);
|
||||
} else {
|
||||
return new File(System.getProperty("user.home"),".omnihub");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
public abstract class BaseResource implements DownloadableResource {
|
||||
protected String fileName;
|
||||
protected String archiveFileName;
|
||||
protected String md5Sum;
|
||||
|
||||
|
||||
public BaseResource(String fileName,String md5Sum,String archiveFileName) {
|
||||
this.fileName = fileName;
|
||||
this.archiveFileName = archiveFileName;
|
||||
this.md5Sum = md5Sum;
|
||||
}
|
||||
|
||||
|
||||
public BaseResource(String fileName,String archiveFileName) {
|
||||
this(fileName,"",archiveFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String archiveFileName() {
|
||||
return archiveFileName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CustomResource extends BaseResource {
|
||||
|
||||
private String localCacheDirectory;
|
||||
private String rootUrl;
|
||||
|
||||
public CustomResource(String fileName,String localCacheDirectory, String rootUrl) {
|
||||
this(fileName,"",localCacheDirectory,rootUrl);
|
||||
}
|
||||
|
||||
public CustomResource(String fileName, String archiveFile,String localCacheDirectory, String rootUrl) {
|
||||
super(fileName,archiveFile);
|
||||
this.localCacheDirectory = localCacheDirectory;
|
||||
this.rootUrl = rootUrl;
|
||||
}
|
||||
|
||||
public CustomResource(String fileName, String md5Sum, String archiveFileName, String localCacheDirectory, String rootUrl) {
|
||||
super(fileName, md5Sum, archiveFileName);
|
||||
this.localCacheDirectory = localCacheDirectory;
|
||||
this.rootUrl = rootUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootUrl() {
|
||||
return rootUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheDirectory() {
|
||||
return new File(localCacheDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType resourceType() {
|
||||
return ResourceType.CUSTOM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
public class DataSetResource extends BaseResource {
|
||||
|
||||
|
||||
private String localCacheDirectory;
|
||||
private String rootUrl;
|
||||
|
||||
|
||||
public DataSetResource(String fileName,String localCacheDirectory, String rootUrl) {
|
||||
this(fileName,"",localCacheDirectory,rootUrl);
|
||||
}
|
||||
|
||||
public DataSetResource(String fileName, String archiveFileName,String localCacheDirectory, String rootUrl) {
|
||||
super(fileName,archiveFileName);
|
||||
this.localCacheDirectory = localCacheDirectory;
|
||||
this.rootUrl = rootUrl;
|
||||
}
|
||||
|
||||
public DataSetResource(String fileName, String md5Sum, String archiveFileName, String localCacheDirectory, String rootUrl) {
|
||||
super(fileName, md5Sum, archiveFileName);
|
||||
this.localCacheDirectory = localCacheDirectory;
|
||||
this.rootUrl = rootUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootUrl() {
|
||||
return rootUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheDirectory() {
|
||||
return new File(localCacheDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType resourceType() {
|
||||
return ResourceType.DATASET;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import org.deeplearning4j.common.resources.DL4JResources;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Dl4jZooResource extends BaseResource {
|
||||
|
||||
private String modelName;
|
||||
|
||||
|
||||
public Dl4jZooResource(String fileName,String archiveName,String modelName) {
|
||||
super(fileName,archiveName);
|
||||
this.modelName = modelName;
|
||||
}
|
||||
|
||||
public Dl4jZooResource(String fileName,String modelName) {
|
||||
this(fileName,"",modelName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootUrl() {
|
||||
return DL4JResources.getBaseDownloadURL() + "/models";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheDirectory() {
|
||||
File rootCacheDir = DL4JResources.getDirectory(org.deeplearning4j.common.resources.ResourceType.ZOO_MODEL, modelName);
|
||||
return rootCacheDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType resourceType() {
|
||||
return ResourceType.LEGACY_ZOO;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
/**
|
||||
* Top level namespace for handling downloaded resources.
|
||||
* Contains utility classes for working with different resources.
|
||||
*/
|
||||
public class DownloadResources {
|
||||
|
||||
/**
|
||||
* Create a {@link CustomResource}
|
||||
* @param fileName the name of the file to download
|
||||
* @param localCacheDirectory the cache directory to store it
|
||||
* @param rootUrl the root url of the download
|
||||
* @return the created {@link CustomResource}
|
||||
*/
|
||||
public static CustomResource createCustomResource(String fileName,String localCacheDirectory,String rootUrl) {
|
||||
return new CustomResource(fileName,localCacheDirectory,rootUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a legacy dl4j zoo model
|
||||
* @param fileName the file name of the model to download
|
||||
* @param modelName the name of the model to download
|
||||
* @return
|
||||
*/
|
||||
public static Dl4jZooResource createLegacyZooResource(String fileName,String modelName) {
|
||||
return new Dl4jZooResource(fileName,modelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link DataSetResource}
|
||||
* @param fileName the name of the file to download
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource createDatasetResource(String fileName,String localCacheDirectory,String rootUrl) {
|
||||
return new DataSetResource(fileName,localCacheDirectory,rootUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link OmniHubResource} from the given file
|
||||
* @param fileName the name of the file to download
|
||||
* @return the created resource
|
||||
*/
|
||||
public static OmniHubResource createOmnihubResource(String fileName) {
|
||||
return new OmniHubResource(fileName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.nd4j.common.resources.Downloader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* A downloadable resource represents a resource
|
||||
* that is downloadable and cached in a specified
|
||||
* directory. This will usually be in the user's home directory
|
||||
* under a hidden dot directory.
|
||||
*/
|
||||
public interface DownloadableResource {
|
||||
|
||||
|
||||
/**
|
||||
* The name of the file to be downloaded
|
||||
* or if an archive, the naem of the extracted file
|
||||
* @return
|
||||
*/
|
||||
String fileName();
|
||||
|
||||
/**
|
||||
* The name of the archive file to be downloaded
|
||||
* @return
|
||||
*/
|
||||
String archiveFileName();
|
||||
|
||||
|
||||
/**
|
||||
* The root url to the resource.
|
||||
* This is going to be the directory name of
|
||||
* where the file lives.
|
||||
* @return
|
||||
*/
|
||||
String rootUrl();
|
||||
|
||||
/**
|
||||
* The storage location representing the directory cache
|
||||
* @return
|
||||
*/
|
||||
File localCacheDirectory();
|
||||
|
||||
/**
|
||||
* The local path to the file. This will usually be
|
||||
* {@link #localCacheDirectory()} + {@link #fileName()}
|
||||
* @return
|
||||
*/
|
||||
default File localPath() {
|
||||
return new File(localCacheDirectory(),fileName());
|
||||
}
|
||||
/**
|
||||
* Md5sum of the file.
|
||||
* Used for verification maybe empty
|
||||
* to avoid running verification.
|
||||
* @return
|
||||
*/
|
||||
default String md5Sum() {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
default void download(boolean archive,int retries,int connectionTimeout,int readTimeout) {
|
||||
if(archive) {
|
||||
localCacheDirectory().mkdirs();
|
||||
Downloader.downloadAndExtract(archiveFileName(),
|
||||
URI.create(rootUrl() + "/" + archiveFileName()).toURL(),
|
||||
new File(localCacheDirectory(),archiveFileName()),
|
||||
localPath(),
|
||||
md5Sum(),
|
||||
retries, connectionTimeout,
|
||||
readTimeout);
|
||||
} else {
|
||||
Downloader.download(fileName(),
|
||||
URI.create(rootUrl() + "/" + fileName()).toURL(),
|
||||
localPath(),
|
||||
md5Sum(),
|
||||
retries,
|
||||
connectionTimeout,
|
||||
readTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the resource type for this resource
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ResourceType resourceType();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default boolean existsLocally() {
|
||||
return localPath().exists();
|
||||
}
|
||||
|
||||
default void delete() throws IOException {
|
||||
if(localPath().isDirectory())
|
||||
FileUtils.deleteDirectory(localPath());
|
||||
else
|
||||
FileUtils.forceDelete(localPath());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import org.deeplearning4j.omnihub.OmnihubConfig;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class OmniHubResource extends BaseResource {
|
||||
|
||||
|
||||
public OmniHubResource(String fileName) {
|
||||
super(fileName,"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootUrl() {
|
||||
return OmnihubConfig.getOmnihubUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheDirectory() {
|
||||
return OmnihubConfig.getOmnihubHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType resourceType() {
|
||||
return ResourceType.OMNIHUB;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import org.deeplearning4j.common.resources.DL4JResources;
|
||||
import org.deeplearning4j.common.resources.ResourceType;
|
||||
import org.eclipse.deeplearning4j.resources.utils.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.eclipse.deeplearning4j.resources.utils.EMnistResourceConstants.*;
|
||||
import static org.eclipse.deeplearning4j.resources.utils.MnistResourceConstants.*;
|
||||
|
||||
/**
|
||||
* Top level class for leveraging pre curated datasets
|
||||
* The pattern of usage for a default directory is:
|
||||
*
|
||||
* DataSetResource resource = ResourceDataSets.(..);
|
||||
* For specifying a directory, for download it's:
|
||||
* DataSetResource customDirResource = ResourceDataSets(yourCustomDirPath);
|
||||
*
|
||||
* A user can then specify a resource download with:
|
||||
* resource.download(..);
|
||||
*
|
||||
* A user won't normally use this class directly. It's common underlying
|
||||
* tooling for the pre existing dataset iterators such as
|
||||
* the MNISTDataSetIterator,EMnistDataSetIterator,LFWDataSetIterator
|
||||
* as well as the BaseImageLoader
|
||||
*
|
||||
* @author Adam Gibson
|
||||
*/
|
||||
public class ResourceDataSets {
|
||||
|
||||
private static File topLevelResourceDir = new File(System.getProperty("user.home"),".dl4jresources");
|
||||
|
||||
|
||||
// --- Test files ---
|
||||
|
||||
|
||||
/**
|
||||
* The default top level directory for storing data
|
||||
* @return
|
||||
*/
|
||||
public static File topLevelResourceDir() {
|
||||
return topLevelResourceDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the top level directory. If intended for use, this should be set
|
||||
* before using any datasets or other resources.
|
||||
* @param topLevelResourceDir the new directory to use
|
||||
*/
|
||||
public static void setTopLevelResourceDir(File topLevelResourceDir) {
|
||||
ResourceDataSets.topLevelResourceDir = topLevelResourceDir;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Download the training file for emnist mapping
|
||||
* @param set the set to download
|
||||
* @return the resource representing the subset
|
||||
*/
|
||||
public static DataSetResource emnistMappingTrain(EMnistSet set) {
|
||||
return emnistMapping(set,DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The input mapping for the test set
|
||||
* @param set
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistMappingTest(EMnistSet set) {
|
||||
return emnistMapping(set,DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The input mapping for the training set
|
||||
* @param set the emnist subset to use
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistMappingTrain(EMnistSet set, File topLevelDir) {
|
||||
return emnistMapping(set,topLevelDir,true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The input label mapping for the test set
|
||||
* @param set the subset of emnist to use
|
||||
* @param topLevelDir the custom top level directory
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistMappingTest(EMnistSet set, File topLevelDir) {
|
||||
return emnistMapping(set,topLevelDir,false);
|
||||
}
|
||||
|
||||
|
||||
private static DataSetResource emnistMapping(EMnistSet set,File topLevelDir,boolean train) {
|
||||
return new DataSetResource(
|
||||
EMnistResourceConstants.getMappingFileName(set,train),
|
||||
"",
|
||||
null,
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString("datasets/emnist")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param set
|
||||
* @param topLevelDir
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistLabelsTrain(EMnistSet set, File topLevelDir) {
|
||||
return emnistLabels(set,topLevelDir,true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The emnist test labels
|
||||
* @param set the emnist subset to download
|
||||
* @param topLevelDir the top level directory to use
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistLabelsTest(EMnistSet set, File topLevelDir) {
|
||||
return emnistLabels(set,topLevelDir,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist train labels
|
||||
* @param set the emnist subset to download
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistLabelsTrain(EMnistSet set) {
|
||||
return emnistLabels(set,DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist test labels
|
||||
* @param set the emnist subset to download
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistLabelsTest(EMnistSet set) {
|
||||
return emnistLabels(set,DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),false);
|
||||
}
|
||||
|
||||
|
||||
private static DataSetResource emnistLabels(EMnistSet set,File topLevelDir,boolean train) {
|
||||
return new DataSetResource(
|
||||
getLabelsFileNameUnzipped(set,train),
|
||||
train ? EMnistResourceConstants.getTrainingFileLabelsMD5(set) : EMnistResourceConstants.getTestFileLabelsMD5(set),
|
||||
EMnistResourceConstants.getLabelsFileName(set,train),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString("datasets/emnist")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist train labels
|
||||
* @param set the emnist subset to download
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistTrain(EMnistSet set,File topLevelDir) {
|
||||
return emnist(set,topLevelDir,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist test labels
|
||||
* @param set the emnist subset to download
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistTest(EMnistSet set,File topLevelDir) {
|
||||
return emnist(set,topLevelDir,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist test labels
|
||||
* @param set the emnist subset to download
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistTrain(EMnistSet set) {
|
||||
return emnist(set, DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emnist test labels
|
||||
* @param set the emnist subset to download
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource emnistTest(EMnistSet set) {
|
||||
return emnist(set,DL4JResources.getDirectory(ResourceType.DATASET, "EMNIST"),false);
|
||||
}
|
||||
|
||||
|
||||
private static DataSetResource emnist(EMnistSet set,File topLevelDir,boolean train) {
|
||||
return new DataSetResource(
|
||||
EMnistResourceConstants.getImagesFileNameUnzipped(set,train),
|
||||
train ? EMnistResourceConstants.getTrainingFilesMD5(set) : EMnistResourceConstants.getTestFilesMD5(set),
|
||||
EMnistResourceConstants.getImagesFileName(set,train),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString("datasets/emnist")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The mnist training set
|
||||
* @param topLevelDir the top level directory ot use
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTrain(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
MnistResourceConstants.getMNISTTrainingFilesFilename_unzipped(),
|
||||
MnistResourceConstants.getMNISTTrainingFilesMD5(),
|
||||
MnistResourceConstants.getMNISTTrainingFilesFilename(),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString(MnistResourceConstants.MNIST_ROOT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The mnist training input data with a default directory of:
|
||||
* {@link DL4JResources#getBaseDirectory()}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTrain() {
|
||||
return mnistTrain(DL4JResources.getBaseDirectory());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The mnist test images
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTest(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
MnistResourceConstants.getTestFilesFilename_unzipped(),
|
||||
MnistResourceConstants.getTestFilesMD5(),
|
||||
MnistResourceConstants.getTestFilesFilename(),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString(MnistResourceConstants.MNIST_ROOT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The mnist test set input with a top level directory of:
|
||||
* {@link DL4JResources#getBaseDirectory()}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTest() {
|
||||
return mnistTest(DL4JResources.getBaseDirectory());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The mnist training labels
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTrainLabels(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
MnistResourceConstants.getMNISTTrainingFileLabelsFilename_unzipped(),
|
||||
MnistResourceConstants.getMNISTTrainingFileLabelsMD5(),
|
||||
MnistResourceConstants.getMNISTTrainingFileLabelsFilename(),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString(MnistResourceConstants.MNIST_ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* The mnist train labels with a top level directory of:
|
||||
* {@link DL4JResources#getBaseDirectory()}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTrainLabels() {
|
||||
return mnistTrainLabels(DL4JResources.getBaseDirectory());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The mnist test labels
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTestLabels(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
MnistResourceConstants.getTestFileLabelsFilename_unzipped(),
|
||||
MnistResourceConstants.getTestFileLabelsMD5(),
|
||||
MnistResourceConstants.getTestFileLabelsFilename(),
|
||||
topLevelDir.getAbsolutePath(),
|
||||
DL4JResources.getURLString(MnistResourceConstants.MNIST_ROOT)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The mnist test set labels with a top level directory of:
|
||||
* {@link DL4JResources#getBaseDirectory}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource mnistTestLabels() {
|
||||
return mnistTestLabels(DL4JResources.getBaseDirectory());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Labels for the LFW full dataset
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwFullLabels(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
LFWResourceConstants.LFW_LABEL_FILE,
|
||||
topLevelDir.getAbsolutePath(),
|
||||
LFWResourceConstants.LFW_ROOT_URL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Input images for the LFW full dataset
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwFullData(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
LFWResourceConstants.LFW_FULL_DIR,
|
||||
LFWResourceConstants.LFW_DATA_URL,
|
||||
topLevelDir.getAbsolutePath(),
|
||||
LFWResourceConstants.LFW_ROOT_URL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Input images for the LFW smaller dataset
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwSubData(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
LFWResourceConstants.LFW_SUB_DIR,
|
||||
LFWResourceConstants.LFW_SUBSET_URL,
|
||||
topLevelDir.getAbsolutePath(),
|
||||
LFWResourceConstants.LFW_ROOT_URL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The cifar10 dataset
|
||||
* @param topLevelDir the top level directory to download to
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource cifar10(File topLevelDir) {
|
||||
return new DataSetResource(
|
||||
CifarResourceConstants.CIFAR_DEFAULT_DIR.getAbsolutePath(),
|
||||
CifarResourceConstants.CIFAR_ARCHIVE_FILE,
|
||||
topLevelDir.getAbsolutePath(),
|
||||
CifarResourceConstants.CIFAR_ROOT_URL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Input labels for the LFW full dataset
|
||||
* with a top level directory of:
|
||||
* {@link LFWResourceConstants#LFW_FULL_DIR}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwFullLabels() {
|
||||
return lfwFullLabels(new File(topLevelResourceDir, LFWResourceConstants.LFW_FULL_DIR));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Input images for the LFW full dataset
|
||||
* with a top level directory of:
|
||||
* {@link LFWResourceConstants#LFW_FULL_DIR}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwFullData() {
|
||||
return lfwFullData(new File(topLevelResourceDir, LFWResourceConstants.LFW_FULL_DIR));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Input images for the LFW smaller dataset
|
||||
* with a top level directory of:
|
||||
* {@link LFWResourceConstants#LFW_SUB_DIR}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource lfwSubData() {
|
||||
return lfwSubData(new File(topLevelResourceDir, LFWResourceConstants.LFW_SUB_DIR));
|
||||
}
|
||||
|
||||
/**
|
||||
* The cifar 10 dataset with a default directory of:
|
||||
* {@link CifarResourceConstants#CIFAR_DEFAULT_DIR}
|
||||
* @return
|
||||
*/
|
||||
public static DataSetResource cifar10() {
|
||||
return cifar10(CifarResourceConstants.CIFAR_DEFAULT_DIR);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ResourceDirectory {
|
||||
|
||||
public final static String DEFAULT_PATH = new File(System.getProperty("user.home"),".dl4jresources").getAbsolutePath();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
public enum ResourceType {
|
||||
LEGACY_ZOO,
|
||||
OMNIHUB,
|
||||
STRUMPF,
|
||||
DATASET,
|
||||
CUSTOM
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources;
|
||||
|
||||
import org.nd4j.common.resources.strumpf.StrumpfResolver;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class StrumpfResource extends BaseResource {
|
||||
private StrumpfResolver resolver = new StrumpfResolver();
|
||||
|
||||
public StrumpfResource(String fileName) {
|
||||
super(fileName,"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootUrl() {
|
||||
return "resolver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheDirectory() {
|
||||
return resolver.localCacheRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType resourceType() {
|
||||
return ResourceType.STRUMPF;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources.utils;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.eclipse.deeplearning4j.resources.ResourceDataSets;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CifarResourceConstants {
|
||||
public static final String CIFAR_ROOT_URL = "https://www.cs.toronto.edu/~kriz";
|
||||
public final static String CIFAR_ARCHIVE_FILE = "cifar-10-binary.tar.gz";
|
||||
public final static File CIFAR_DEFAULT_DIR = new File(ResourceDataSets.topLevelResourceDir(),
|
||||
FilenameUtils.concat("cifar", "cifar-10-batches-bin"));
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources.utils;
|
||||
|
||||
import org.deeplearning4j.common.resources.DL4JResources;
|
||||
|
||||
public class EMnistResourceConstants {
|
||||
|
||||
public static String getTrainingFilesURL(EMnistSet ds) {
|
||||
return DL4JResources.getURLString("datasets/emnist/" + getImagesFileName(ds, true));
|
||||
}
|
||||
|
||||
public static String getTrainingFilesMD5(EMnistSet ds) {
|
||||
switch (ds) {
|
||||
case COMPLETE:
|
||||
//byclass-train-images
|
||||
return "712dda0bd6f00690f32236ae4325c377";
|
||||
case MERGE:
|
||||
//bymerge-train-images
|
||||
return "4a792d4df261d7e1ba27979573bf53f3";
|
||||
case BALANCED:
|
||||
//balanced-train-images
|
||||
return "4041b0d6f15785d3fa35263901b5496b";
|
||||
case LETTERS:
|
||||
//letters-train-images
|
||||
return "8795078f199c478165fe18db82625747";
|
||||
case DIGITS:
|
||||
//digits-train-images
|
||||
return "d2662ecdc47895a6bbfce25de9e9a677";
|
||||
case MNIST:
|
||||
//mnist-train-images
|
||||
return "3663598a39195d030895b6304abb5065";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown DataSet: " + ds);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTrainingFilesFilename(EMnistSet ds) {
|
||||
return getImagesFileName(ds, true);
|
||||
}
|
||||
|
||||
public static String getTrainingFilesFilename_unzipped(EMnistSet ds) {
|
||||
return getImagesFileNameUnzipped(ds, true);
|
||||
}
|
||||
|
||||
public static String getTrainingFileLabelsURL(EMnistSet ds) {
|
||||
return DL4JResources.getURLString("datasets/emnist/" + getLabelsFileName(ds, true));
|
||||
}
|
||||
|
||||
public static String getTrainingFileLabelsMD5(EMnistSet ds) {
|
||||
switch (ds) {
|
||||
case COMPLETE:
|
||||
//byclass-train-labels
|
||||
return "ee299a3ee5faf5c31e9406763eae7e43";
|
||||
case MERGE:
|
||||
//bymerge-train-labels
|
||||
return "491be69ef99e1ab1f5b7f9ccc908bb26";
|
||||
case BALANCED:
|
||||
//balanced-train-labels
|
||||
return "7a35cc7b2b7ee7671eddf028570fbd20";
|
||||
case LETTERS:
|
||||
//letters-train-labels
|
||||
return "c16de4f1848ddcdddd39ab65d2a7be52";
|
||||
case DIGITS:
|
||||
//digits-train-labels
|
||||
return "2223fcfee618ac9c89ef20b6e48bcf9e";
|
||||
case MNIST:
|
||||
//mnist-train-labels
|
||||
return "6c092f03c9bb63e678f80f8bc605fe37";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown DataSet: " + ds);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTrainingFileLabelsFilename(EMnistSet ds) {
|
||||
return getLabelsFileName(ds, true);
|
||||
}
|
||||
|
||||
public static String getTrainingFileLabelsFilename_unzipped(EMnistSet ds) {
|
||||
return getLabelsFileNameUnzipped(ds, true);
|
||||
}
|
||||
|
||||
|
||||
// --- Test files ---
|
||||
|
||||
public static String getTestFilesURL(EMnistSet ds) {
|
||||
return DL4JResources.getURLString("datasets/emnist/" + getImagesFileName(ds, false));
|
||||
}
|
||||
|
||||
public static String getTestFilesMD5(EMnistSet ds) {
|
||||
switch (ds) {
|
||||
case COMPLETE:
|
||||
//byclass-test-images
|
||||
return "1435209e34070a9002867a9ab50160d7";
|
||||
case MERGE:
|
||||
//bymerge-test-images
|
||||
return "8eb5d34c91f1759a55831c37ec2a283f";
|
||||
case BALANCED:
|
||||
//balanced-test-images
|
||||
return "6818d20fe2ce1880476f747bbc80b22b";
|
||||
case LETTERS:
|
||||
//letters-test-images
|
||||
return "382093a19703f68edac6d01b8dfdfcad";
|
||||
case DIGITS:
|
||||
//digits-test-images
|
||||
return "a159b8b3bd6ab4ed4793c1cb71a2f5cc";
|
||||
case MNIST:
|
||||
//mnist-test-images
|
||||
return "fb51b6430fc4dd67deaada1bf25d4524";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown DataSet: " + ds);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTestFilesFilename(EMnistSet ds) {
|
||||
return getImagesFileName(ds, false);
|
||||
}
|
||||
|
||||
public static String getTestFilesFilename_unzipped(EMnistSet ds) {
|
||||
return getImagesFileNameUnzipped(ds, false);
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsURL(EMnistSet ds) {
|
||||
return DL4JResources.getURLString("datasets/emnist/" + getLabelsFileName(ds, false));
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsMD5(EMnistSet ds) {
|
||||
switch (ds) {
|
||||
case COMPLETE:
|
||||
//byclass-test-labels
|
||||
return "7a0f934bd176c798ecba96b36fda6657";
|
||||
case MERGE:
|
||||
//bymerge-test-labels
|
||||
return "c13f4cd5211cdba1b8fa992dae2be992";
|
||||
case BALANCED:
|
||||
//balanced-test-labels
|
||||
return "acd3694070dcbf620e36670519d4b32f";
|
||||
case LETTERS:
|
||||
//letters-test-labels
|
||||
return "d4108920cd86601ec7689a97f2de7f59";
|
||||
case DIGITS:
|
||||
//digits-test-labels
|
||||
return "8afde66ea51d865689083ba6bb779fac";
|
||||
case MNIST:
|
||||
//mnist-test-labels
|
||||
return "ae7f6be798a9a5d5f2bd32e078a402dd";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown DataSet: " + ds);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsFilename(EMnistSet ds) {
|
||||
return getLabelsFileName(ds, false);
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsFilename_unzipped(EMnistSet ds) {
|
||||
return getLabelsFileNameUnzipped(ds, false);
|
||||
}
|
||||
|
||||
|
||||
public static String getImagesFileName(EMnistSet ds, boolean train) {
|
||||
return "emnist-" + name(ds) + "-" + (train ? "train" : "test") + "-images-idx3-ubyte.gz";
|
||||
}
|
||||
|
||||
public static String getImagesFileNameUnzipped(EMnistSet ds, boolean train) {
|
||||
return "emnist-" + name(ds) + "-" + (train ? "train" : "test") + "-images-idx3-ubyte";
|
||||
}
|
||||
|
||||
public static String getLabelsFileName(EMnistSet ds, boolean train) {
|
||||
return "emnist-" + name(ds) + "-" + (train ? "train" : "test") + "-labels-idx1-ubyte.gz";
|
||||
}
|
||||
|
||||
public static String getLabelsFileNameUnzipped(EMnistSet ds, boolean train) {
|
||||
return "emnist-" + name(ds) + "-" + (train ? "train" : "test") + "-labels-idx1-ubyte";
|
||||
}
|
||||
|
||||
public static String getMappingFileName(EMnistSet ds, boolean train) {
|
||||
return "emnist-" + name(ds) + "-mapping.txt";
|
||||
}
|
||||
|
||||
public static String name(EMnistSet ds) {
|
||||
switch (ds) {
|
||||
case COMPLETE:
|
||||
return "byclass";
|
||||
case MERGE:
|
||||
return "bymerge";
|
||||
case BALANCED:
|
||||
return "balanced";
|
||||
case LETTERS:
|
||||
return "letters";
|
||||
case DIGITS:
|
||||
return "digits";
|
||||
case MNIST:
|
||||
return "mnist";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown DataSet: " + ds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources.utils;
|
||||
|
||||
/**
|
||||
* EMNIST dataset has multiple different subsets
|
||||
*/
|
||||
public enum EMnistSet {
|
||||
COMPLETE, MERGE, BALANCED, LETTERS, DIGITS, MNIST
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources.utils;
|
||||
|
||||
public class LFWResourceConstants {
|
||||
|
||||
|
||||
public final static String LFW_ROOT_URL = "http://vis-www.cs.umass.edu/lfw";
|
||||
public final static String LFW_DATA_URL = "lfw.tgz";
|
||||
public final static String LFW_LABEL_URL = "lfw-names.txt";
|
||||
public final static String LFW_SUBSET_URL = "lfw-a.tgz";
|
||||
public final static String LFW_FULL_DIR = "lfw";
|
||||
public final static String LFW_SUB_DIR = "lfw-a";
|
||||
public final static String LFW_LABEL_FILE = "lfw-names.txt";
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package org.eclipse.deeplearning4j.resources.utils;
|
||||
|
||||
import org.deeplearning4j.common.resources.DL4JResources;
|
||||
|
||||
public class MnistResourceConstants {
|
||||
|
||||
public static final String TRAINING_FILES_URL_RELATIVE = "datasets/mnist/train-images-idx3-ubyte.gz";
|
||||
public static final String TRAINING_FILES_MD_5 = "f68b3c2dcbeaaa9fbdd348bbdeb94873";
|
||||
public static final String TRAINING_FILES_FILENAME = "train-images-idx3-ubyte.gz";
|
||||
public static final String TRAINING_FILES_FILENAME_UNZIPPED = "train-images-idx3-ubyte";
|
||||
public static final String TRAINING_FILE_LABELS_URL_RELATIVE = "datasets/mnist/train-labels-idx1-ubyte.gz";
|
||||
public static final String TRAINING_FILE_LABELS_MD_5 = "d53e105ee54ea40749a09fcbcd1e9432";
|
||||
public static final String TRAINING_FILE_LABELS_FILENAME = "train-labels-idx1-ubyte.gz";
|
||||
public static final String TRAINING_FILE_LABELS_FILENAME_UNZIPPED = "train-labels-idx1-ubyte";
|
||||
//Test data:
|
||||
public static final String TEST_FILES_URL_RELATIVE = "datasets/mnist/t10k-images-idx3-ubyte.gz";
|
||||
public static final String TEST_FILES_MD_5 = "9fb629c4189551a2d022fa330f9573f3";
|
||||
public static final String TEST_FILES_FILENAME = "t10k-images-idx3-ubyte.gz";
|
||||
public static final String TEST_FILES_FILENAME_UNZIPPED = "t10k-images-idx3-ubyte";
|
||||
public static final String TEST_FILE_LABELS_URL_RELATIVE = "datasets/mnist/t10k-labels-idx1-ubyte.gz";
|
||||
public static final String TEST_FILE_LABELS_MD_5 = "ec29112dd5afa0611ce80d1b7f02629c";
|
||||
public static final String TEST_FILE_LABELS_FILENAME = "t10k-labels-idx1-ubyte.gz";
|
||||
public static final String TEST_FILE_LABELS_FILENAME_UNZIPPED = "t10k-labels-idx1-ubyte";
|
||||
|
||||
public final static String MNIST_ROOT = "datasets/mnist";
|
||||
|
||||
// --- Train files ---
|
||||
public static String getMNISTTrainingFilesURL() {
|
||||
return DL4JResources.getURLString(TRAINING_FILES_URL_RELATIVE);
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFilesMD5() {
|
||||
return TRAINING_FILES_MD_5;
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFilesFilename() {
|
||||
return TRAINING_FILES_FILENAME;
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFilesFilename_unzipped() {
|
||||
return TRAINING_FILES_FILENAME_UNZIPPED;
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFileLabelsURL() {
|
||||
return DL4JResources.getURLString(TRAINING_FILE_LABELS_URL_RELATIVE);
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFileLabelsMD5() {
|
||||
return TRAINING_FILE_LABELS_MD_5;
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFileLabelsFilename() {
|
||||
return TRAINING_FILE_LABELS_FILENAME;
|
||||
}
|
||||
|
||||
public static String getMNISTTrainingFileLabelsFilename_unzipped() {
|
||||
return TRAINING_FILE_LABELS_FILENAME_UNZIPPED;
|
||||
}
|
||||
|
||||
public static String getTestFilesURL() {
|
||||
return DL4JResources.getURLString(TEST_FILES_URL_RELATIVE);
|
||||
}
|
||||
|
||||
public static String getTestFilesMD5() {
|
||||
return TEST_FILES_MD_5;
|
||||
}
|
||||
|
||||
public static String getTestFilesFilename() {
|
||||
return TEST_FILES_FILENAME;
|
||||
}
|
||||
|
||||
public static String getTestFilesFilename_unzipped() {
|
||||
return TEST_FILES_FILENAME_UNZIPPED;
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsURL() {
|
||||
return DL4JResources.getURLString(TEST_FILE_LABELS_URL_RELATIVE);
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsMD5() {
|
||||
return TEST_FILE_LABELS_MD_5;
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsFilename() {
|
||||
return TEST_FILE_LABELS_FILENAME;
|
||||
}
|
||||
|
||||
public static String getTestFileLabelsFilename_unzipped() {
|
||||
return TEST_FILE_LABELS_FILENAME_UNZIPPED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.nd4j.common.resources;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.nd4j.common.util.ArchiveUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.channels.FileLockInterruptionException;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
|
||||
@Slf4j
|
||||
public class Downloader {
|
||||
/**
|
||||
* Default connection timeout in milliseconds when using {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
*/
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
/**
|
||||
* Default read timeout in milliseconds when using {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
*/
|
||||
public static final int DEFAULT_READ_TIMEOUT = 60000;
|
||||
|
||||
private Downloader(){ }
|
||||
|
||||
/**
|
||||
* As per {@link #download(String, URL, File, String, int, int, int)} with the connection and read timeouts
|
||||
* set to their default values - {@link #DEFAULT_CONNECTION_TIMEOUT} and {@link #DEFAULT_READ_TIMEOUT} respectively
|
||||
*/
|
||||
public static void download(String name, URL url, File f, String targetMD5, int maxTries) throws IOException {
|
||||
download(name, url, f, targetMD5, maxTries, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the specified URL to the specified file, and verify that the target MD5 matches
|
||||
*
|
||||
* @param name Name (mainly for providing useful exceptions)
|
||||
* @param url URL to download
|
||||
* @param f Destination file
|
||||
* @param targetMD5 Expected MD5 for file
|
||||
* @param maxTries Maximum number of download attempts before failing and throwing an exception
|
||||
* @param connectionTimeout connection timeout in milliseconds, as used by {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
* @param readTimeout read timeout in milliseconds, as used by {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
* @throws IOException If an error occurs during downloading
|
||||
*/
|
||||
public static void download(String name, URL url, File f, String targetMD5, int maxTries, int connectionTimeout, int readTimeout) throws IOException {
|
||||
download(name, url, f, targetMD5, maxTries, 0, connectionTimeout, readTimeout);
|
||||
}
|
||||
|
||||
private static void download(String name, URL url, File f, String targetMD5, int maxTries, int attempt, int connectionTimeout, int readTimeout) throws IOException {
|
||||
doOrWait(f.getParentFile(), () -> {
|
||||
boolean isCorrectFile = f.exists() && f.isFile() && checkMD5OfFile(targetMD5, f);
|
||||
if (attempt < maxTries) {
|
||||
if(!isCorrectFile) {
|
||||
FileUtils.copyURLToFile(url, f, connectionTimeout, readTimeout);
|
||||
if (!checkMD5OfFile(targetMD5, f)) {
|
||||
f.delete();
|
||||
download(name, url, f, targetMD5, maxTries, attempt + 1, connectionTimeout, readTimeout);
|
||||
}
|
||||
}
|
||||
} else if (!isCorrectFile) {
|
||||
//Too many attempts
|
||||
throw new IOException("Could not download " + name + " from " + url + "\n properly despite trying " + maxTries
|
||||
+ " times, check your connection.");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* As per {@link #downloadAndExtract(String, URL, File, File, String, int, int, int)} with the connection and read timeouts
|
||||
* * set to their default values - {@link #DEFAULT_CONNECTION_TIMEOUT} and {@link #DEFAULT_READ_TIMEOUT} respectively
|
||||
*/
|
||||
public static void downloadAndExtract(String name, URL url, File f, File extractToDir, String targetMD5, int maxTries) throws IOException {
|
||||
downloadAndExtract(name, url, f, extractToDir, targetMD5, maxTries, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the specified URL to the specified file, verify that the MD5 matches, and then extract it to the specified directory.<br>
|
||||
* Note that the file must be an archive, with the correct file extension: .zip, .jar, .tar.gz, .tgz or .gz
|
||||
*
|
||||
* @param name Name (mainly for providing useful exceptions)
|
||||
* @param url URL to download
|
||||
* @param f Destination file
|
||||
* @param extractToDir Destination directory to extract all files
|
||||
* @param targetMD5 Expected MD5 for file
|
||||
* @param maxTries Maximum number of download attempts before failing and throwing an exception
|
||||
* @param connectionTimeout connection timeout in milliseconds, as used by {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
* @param readTimeout read timeout in milliseconds, as used by {@link FileUtils#copyURLToFile(URL, File, int, int)}
|
||||
* @throws IOException If an error occurs during downloading
|
||||
*/
|
||||
public static void downloadAndExtract(String name, URL url, File f, File extractToDir, String targetMD5, int maxTries,
|
||||
int connectionTimeout, int readTimeout) throws IOException {
|
||||
downloadAndExtract(0, maxTries, name, url, f, extractToDir, targetMD5, connectionTimeout, readTimeout);
|
||||
}
|
||||
|
||||
private static void downloadAndExtract(int attempt, int maxTries, String name, URL url, File f, File extractToDir,
|
||||
String targetMD5, int connectionTimeout, int readTimeout) throws IOException {
|
||||
doOrWait(f.getParentFile(), () -> {
|
||||
boolean isCorrectFile = f.exists() && f.isFile() && checkMD5OfFile(targetMD5, f);
|
||||
if (attempt < maxTries) {
|
||||
if(!isCorrectFile) {
|
||||
FileUtils.copyURLToFile(url, f, connectionTimeout, readTimeout);
|
||||
if (!checkMD5OfFile(targetMD5, f)) {
|
||||
f.delete();
|
||||
downloadAndExtract(attempt + 1, maxTries, name, url, f, extractToDir, targetMD5, connectionTimeout, readTimeout);
|
||||
}
|
||||
}
|
||||
// try extracting
|
||||
try{
|
||||
ArchiveUtils.unzipFileTo(f.getAbsolutePath(), extractToDir.getAbsolutePath(), false);
|
||||
} catch (Throwable t){
|
||||
log.warn("Error extracting {} files from file {} - retrying...", name, f.getAbsolutePath(), t);
|
||||
f.delete();
|
||||
downloadAndExtract(attempt + 1, maxTries, name, url, f, extractToDir, targetMD5, connectionTimeout, readTimeout);
|
||||
}
|
||||
} else if (!isCorrectFile) {
|
||||
//Too many attempts
|
||||
throw new IOException("Could not download and extract " + name + " from " + url.getPath() + "\n properly despite trying " + maxTries
|
||||
+ " times, check your connection. File info:" + "\nTarget MD5: " + targetMD5
|
||||
+ "\nHash matches: " + checkMD5OfFile(targetMD5, f) + "\nIs valid file: " + f.isFile());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the input file is corrupted by
|
||||
* verifying the target md5 hash.
|
||||
* If corrupted, file is deleted
|
||||
* @param inputFile the input file to check
|
||||
* @param targetmd5 the target md5 to test
|
||||
* @throws IOException
|
||||
*/
|
||||
public static boolean deleteIfCorrupted(File inputFile,String targetmd5) throws IOException {
|
||||
if(!checkMD5OfFile(targetmd5, inputFile)) {
|
||||
inputFile.delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the MD5 of the specified file
|
||||
* @param targetMD5 Expected MD5
|
||||
* @param file File to check
|
||||
* @return True if MD5 matches, false otherwise
|
||||
*/
|
||||
public static boolean checkMD5OfFile(String targetMD5, File file) throws IOException {
|
||||
if(!file.exists())
|
||||
return false;
|
||||
|
||||
if(targetMD5.isEmpty())
|
||||
return true;
|
||||
|
||||
InputStream in = FileUtils.openInputStream(file);
|
||||
String trueMd5 = DigestUtils.md5Hex(in);
|
||||
IOUtils.closeQuietly(in);
|
||||
return (targetMD5.equals(trueMd5));
|
||||
}
|
||||
|
||||
private static void doOrWait(File flagDir, IOCallable block) throws IOException {
|
||||
boolean waitForFinish = false;
|
||||
if(flagDir.exists()){
|
||||
final File lockFile = flagDir.toPath().resolve("inProgress.lock").toFile();
|
||||
RandomAccessFile flag = new RandomAccessFile(lockFile, "rw");
|
||||
while(true) try {
|
||||
final FileChannel channel = flag.getChannel();
|
||||
try (FileLock lock = channel.lock()) {
|
||||
if(!waitForFinish) block.call();
|
||||
} finally {
|
||||
lockFile.delete();
|
||||
}
|
||||
return;
|
||||
}catch(OverlappingFileLockException | FileLockInterruptionException e){
|
||||
// file is locked, someone else is already doing the work we want to do.
|
||||
// just wait until it is finished, there should be no need to actually do anything
|
||||
// once we can acquire that lock
|
||||
try {
|
||||
log.debug("Waiting to acquire download lock in dir {}", flagDir.getPath());
|
||||
waitForFinish = true;
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {
|
||||
// noop, we retry to acquire that lock
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new IOException("Target directory "+flagDir.getPath()+" must exist!");
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface IOCallable {
|
||||
void call() throws IOException;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.nd4j.common.resources;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface Resolver {
|
||||
|
||||
/**
|
||||
* Priority of this resolver. 0 is highest priority (check first), larger values are lower priority (check last)
|
||||
*/
|
||||
int priority();
|
||||
|
||||
/**
|
||||
* Determine if the specified file resource can be resolved by {@link #asFile(String)} and {@link #asStream(String)}
|
||||
*
|
||||
* @param resourcePath Path of the resource to be resolved
|
||||
* @return True if this resolver is able to resolve the resource file - i.e., whether it is a valid path and exists
|
||||
*/
|
||||
boolean exists(String resourcePath);
|
||||
|
||||
/**
|
||||
* Determine if the specified directory resource can be resolved by {@link #copyDirectory(String, File)}
|
||||
*
|
||||
* @param dirPath Path of the directory resource to be resolved
|
||||
* @return True if this resolver is able to resolve the directory - i.e., whether it is a valid path and exists
|
||||
*/
|
||||
boolean directoryExists(String dirPath);
|
||||
|
||||
/**
|
||||
* Get the specified resources as a standard local file.
|
||||
* Note that the resource must exist as determined by {@link #exists(String)}
|
||||
*
|
||||
* @param resourcePath Path of the resource.
|
||||
* @return The local file version of the resource
|
||||
*/
|
||||
File asFile(String resourcePath);
|
||||
|
||||
/**
|
||||
* Get the specified resources as an input stream.
|
||||
* Note that the resource must exist as determined by {@link #exists(String)}
|
||||
*
|
||||
* @param resourcePath Path of the resource.
|
||||
* @return The resource as an input stream
|
||||
*/
|
||||
InputStream asStream(String resourcePath);
|
||||
|
||||
/**
|
||||
* Copy the directory resource (recursively) to the specified destination directory
|
||||
*
|
||||
* @param dirPath Path of the resource directory to resolve
|
||||
* @param destinationDir Where the files should be copied to
|
||||
*/
|
||||
void copyDirectory(String dirPath, File destinationDir);
|
||||
|
||||
/**
|
||||
* @return True if the resolver has a local cache directory, as returned by {@link #localCacheRoot()}
|
||||
*/
|
||||
boolean hasLocalCache();
|
||||
|
||||
/**
|
||||
* @return Root directory of the local cache, or null if {@link #hasLocalCache()} returns false
|
||||
*/
|
||||
File localCacheRoot();
|
||||
|
||||
/**
|
||||
* Normalize the path that may be a resource reference.
|
||||
* For example: "someDir/myFile.zip.resource_reference" --> "someDir/myFile.zip"
|
||||
* Returns null if the file cannot be resolved.
|
||||
* If the file is not a reference, the original path is returned
|
||||
*/
|
||||
String normalizePath(String path);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.nd4j.common.resources;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nd4j.common.config.ND4JClassLoading;
|
||||
import org.nd4j.common.resources.strumpf.StrumpfResolver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
public class Resources {
|
||||
private static Resources INSTANCE = new Resources();
|
||||
|
||||
protected final List<Resolver> resolvers;
|
||||
|
||||
protected Resources() {
|
||||
ServiceLoader<Resolver> loader = ND4JClassLoading.loadService(Resolver.class);
|
||||
|
||||
resolvers = new ArrayList<>();
|
||||
resolvers.add(new StrumpfResolver());
|
||||
for (Resolver resolver : loader) {
|
||||
resolvers.add(resolver);
|
||||
}
|
||||
|
||||
//Sort resolvers by priority: check resolvers with lower numbers first
|
||||
Collections.sort(resolvers, Comparator.comparingInt(Resolver::priority));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified resource exists (can be resolved by any method) hence can be loaded by {@link #asFile(String)}
|
||||
* or {@link #asStream(String)}
|
||||
*
|
||||
* @param resourcePath Path of the resource to be resolved
|
||||
* @return Whether the resource can be resolved or not
|
||||
*/
|
||||
public static boolean exists(@NonNull String resourcePath) {
|
||||
return INSTANCE.resourceExists(resourcePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified resource as a local file.
|
||||
* If it cannot be found (i.e., {@link #exists(String)} returns false) this method will throw an exception.
|
||||
*
|
||||
* @param resourcePath Path of the resource to get
|
||||
* @return Resource file
|
||||
*/
|
||||
public static File asFile(@NonNull String resourcePath) {
|
||||
return INSTANCE.getAsFile(resourcePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified resource as an input stream.<br>
|
||||
* If it cannot be found (i.e., {@link #exists(String)} returns false) this method will throw an exception.
|
||||
*
|
||||
* @param resourcePath Path of the resource to get
|
||||
* @return Resource stream
|
||||
*/
|
||||
public static InputStream asStream(@NonNull String resourcePath) {
|
||||
return INSTANCE.getAsStream(resourcePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the specified directory (path) to the specified destination directory, resolving any resources in the process
|
||||
*
|
||||
* @param directoryPath Directory to copy contents of
|
||||
* @param destinationDir Destination
|
||||
*/
|
||||
public static void copyDirectory(@NonNull String directoryPath, @NonNull File destinationDir) {
|
||||
INSTANCE.copyDir(directoryPath, destinationDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the path that may be a resource reference.
|
||||
* For example: "someDir/myFile.zip.resource_reference" --> "someDir/myFile.zip"
|
||||
* Returns null if the file cannot be resolved.
|
||||
* If the file is not a reference, the original path is returned
|
||||
*/
|
||||
public static String normalizePath(String path){
|
||||
return INSTANCE.normalize(path);
|
||||
}
|
||||
|
||||
protected boolean resourceExists(String resourcePath) {
|
||||
for (Resolver r : resolvers) {
|
||||
if (r.exists(resourcePath))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected File getAsFile(String resourcePath) {
|
||||
for (Resolver r : resolvers) {
|
||||
if (r.exists(resourcePath)) {
|
||||
return r.asFile(resourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve resource (not found): none of " + resolvers.size() +
|
||||
" resolvers can resolve resource \"" + resourcePath + "\" - available resolvers: " + resolvers.toString());
|
||||
}
|
||||
|
||||
public InputStream getAsStream(String resourcePath) {
|
||||
for (Resolver r : resolvers) {
|
||||
if (r.exists(resourcePath)) {
|
||||
log.debug("Resolved resource with resolver " + r.getClass().getName() + " for path " + resourcePath);
|
||||
return r.asStream(resourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve resource (not found): none of " + resolvers.size() +
|
||||
" resolvers can resolve resource \"" + resourcePath + "\" - available resolvers: " + resolvers.toString());
|
||||
}
|
||||
|
||||
public void copyDir(String directoryPath, File destinationDir) {
|
||||
for (Resolver r : resolvers) {
|
||||
if (r.directoryExists(directoryPath)) {
|
||||
r.copyDirectory(directoryPath, destinationDir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String normalize(String path){
|
||||
for(Resolver r : resolvers){
|
||||
path = r.normalizePath(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.nd4j.common.resources.strumpf;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.nd4j.common.base.Preconditions;
|
||||
import org.nd4j.common.config.ND4JSystemProperties;
|
||||
import org.nd4j.shade.guava.io.Files;
|
||||
import org.nd4j.shade.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.nd4j.shade.jackson.databind.DeserializationFeature;
|
||||
import org.nd4j.shade.jackson.databind.MapperFeature;
|
||||
import org.nd4j.shade.jackson.databind.ObjectMapper;
|
||||
import org.nd4j.shade.jackson.databind.SerializationFeature;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
@JsonIgnoreProperties("filePath")
|
||||
@Slf4j
|
||||
public class ResourceFile {
|
||||
/**
|
||||
* Default value for resource downloading connection timeout - see {@link ND4JSystemProperties#RESOURCES_CONNECTION_TIMEOUT}
|
||||
*/
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000; //Timeout for connections to be established
|
||||
/**
|
||||
* Default value for resource downloading read timeout - see {@link ND4JSystemProperties#RESOURCES_READ_TIMEOUT}
|
||||
*/
|
||||
public static final int DEFAULT_READ_TIMEOUT = 60000; //Timeout for amount of time between connection established and data is available
|
||||
protected static final String PATH_KEY = "full_remote_path";
|
||||
protected static final String HASH = "_hash";
|
||||
protected static final String COMPRESSED_HASH = "_compressed_hash";
|
||||
|
||||
protected static final int MAX_DOWNLOAD_ATTEMPTS = 3;
|
||||
|
||||
public static final ObjectMapper MAPPER = newMapper();
|
||||
|
||||
//Note: Field naming to match Strumpf JSON format
|
||||
protected int current_version;
|
||||
protected Map<String, String> v1;
|
||||
|
||||
//Not in JSON:
|
||||
protected String filePath;
|
||||
|
||||
public static ResourceFile fromFile(String path) {
|
||||
return fromFile(new File(path));
|
||||
}
|
||||
|
||||
public static ResourceFile fromFile(File file) {
|
||||
String s;
|
||||
try {
|
||||
s = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
|
||||
ResourceFile rf = MAPPER.readValue(s, ResourceFile.class);
|
||||
rf.setFilePath(file.getPath());
|
||||
return rf;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String relativePath() {
|
||||
String hashKey = null;
|
||||
for (String key : v1.keySet()) {
|
||||
if (key.endsWith(HASH) && !key.endsWith(COMPRESSED_HASH)) {
|
||||
hashKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hashKey == null) {
|
||||
throw new IllegalStateException("Could not find <filename>_hash in resource reference file: " + filePath);
|
||||
}
|
||||
|
||||
String relativePath = hashKey.substring(0, hashKey.length() - 5); //-5 to remove "_hash" suffix
|
||||
return relativePath.replaceAll("\\\\", "/");
|
||||
}
|
||||
|
||||
public boolean localFileExistsAndValid(File cacheRootDir) {
|
||||
|
||||
File file = getLocalFile(cacheRootDir);
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//File exists... but is it valid?
|
||||
String sha256Property = relativePath() + HASH;
|
||||
String expSha256 = v1.get(sha256Property);
|
||||
|
||||
Preconditions.checkState(expSha256 != null, "Expected JSON property %s was not found in resource reference file %s", sha256Property, filePath);
|
||||
|
||||
String actualSha256 = sha256(file);
|
||||
if (!expSha256.equals(actualSha256)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local file - or where it *would* be if it has been downloaded. If it does not exist, it will not be downloaded here
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected File getLocalFile(File cacheRootDir) {
|
||||
String relativePath = relativePath();
|
||||
|
||||
//For resolving local files with different versions, we want paths like:
|
||||
// ".../dir/filename.txt__v1/filename.txt"
|
||||
// ".../dir/filename.txt__v2/filename.txt"
|
||||
//This is to support multiple versions of files simultaneously... for example, different projects needing different
|
||||
// versions, or supporting old versions of resource files etc
|
||||
|
||||
int lastSlash = Math.max(relativePath.lastIndexOf('/'), relativePath.lastIndexOf('\\'));
|
||||
String filename;
|
||||
if (lastSlash < 0) {
|
||||
filename = relativePath;
|
||||
} else {
|
||||
filename = relativePath.substring(lastSlash + 1);
|
||||
}
|
||||
|
||||
File parentDir = new File(cacheRootDir, relativePath + "__v" + current_version);
|
||||
File file = new File(parentDir, filename);
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local file - downloading and caching if required
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public File localFile(File cacheRootDir) {
|
||||
if (localFileExistsAndValid(cacheRootDir)) {
|
||||
return getLocalFile(cacheRootDir);
|
||||
}
|
||||
|
||||
//Need to download and extract...
|
||||
String remotePath = v1.get(PATH_KEY);
|
||||
Preconditions.checkState(remotePath != null, "No remote path was found in resource reference file %s", filePath);
|
||||
File f = getLocalFile(cacheRootDir);
|
||||
|
||||
File tempDir = Files.createTempDir();
|
||||
File tempFile = new File(tempDir, FilenameUtils.getName(remotePath));
|
||||
|
||||
String sha256PropertyCompressed = relativePath() + COMPRESSED_HASH;
|
||||
|
||||
String sha256Compressed = v1.get(sha256PropertyCompressed);
|
||||
Preconditions.checkState(sha256Compressed != null, "Expected JSON property %s was not found in resource reference file %s", sha256PropertyCompressed, filePath);
|
||||
|
||||
String sha256Property = relativePath() + HASH;
|
||||
String sha256Uncompressed = v1.get(sha256Property);
|
||||
|
||||
String connTimeoutStr = System.getProperty(ND4JSystemProperties.RESOURCES_CONNECTION_TIMEOUT);
|
||||
String readTimeoutStr = System.getProperty(ND4JSystemProperties.RESOURCES_READ_TIMEOUT);
|
||||
boolean validCTimeout = connTimeoutStr != null && connTimeoutStr.matches("\\d+");
|
||||
boolean validRTimeout = readTimeoutStr != null && readTimeoutStr.matches("\\d+");
|
||||
|
||||
int connectTimeout = validCTimeout ? Integer.parseInt(connTimeoutStr) : DEFAULT_CONNECTION_TIMEOUT;
|
||||
int readTimeout = validRTimeout ? Integer.parseInt(readTimeoutStr) : DEFAULT_READ_TIMEOUT;
|
||||
|
||||
try {
|
||||
boolean correctHash = false;
|
||||
for (int tryCount = 0; tryCount < MAX_DOWNLOAD_ATTEMPTS; tryCount++) {
|
||||
try {
|
||||
if (tempFile.exists())
|
||||
tempFile.delete();
|
||||
log.info("Downloading remote resource {} to {}", remotePath, tempFile);
|
||||
FileUtils.copyURLToFile(new URL(remotePath), tempFile, connectTimeout, readTimeout);
|
||||
//Now: check if downloaded archive hash is OK
|
||||
String hash = sha256(tempFile);
|
||||
correctHash = sha256Compressed.equals(hash);
|
||||
if (!correctHash) {
|
||||
log.warn("Download of file {} failed: expected hash {} vs. actual hash {}", remotePath, sha256Compressed, hash);
|
||||
continue;
|
||||
}
|
||||
log.info("Downloaded {} to temporary file {}", remotePath, tempFile);
|
||||
break;
|
||||
} catch (Throwable t) {
|
||||
if (tryCount == MAX_DOWNLOAD_ATTEMPTS - 1) {
|
||||
throw new RuntimeException("Error downloading test resource: " + remotePath, t);
|
||||
}
|
||||
log.warn("Error downloading test resource, retrying... {}", remotePath, t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!correctHash) {
|
||||
throw new RuntimeException("Could not successfully download with correct hash file after " + MAX_DOWNLOAD_ATTEMPTS +
|
||||
" attempts: " + remotePath);
|
||||
}
|
||||
|
||||
//Now, extract:
|
||||
f.getParentFile().mkdirs();
|
||||
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
|
||||
InputStream is = new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(tempFile)))) {
|
||||
IOUtils.copy(is, os);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error extracting resource file", e);
|
||||
}
|
||||
log.info("Extracted {} to {}", tempFile, f);
|
||||
|
||||
//Check extracted file hash:
|
||||
String extractedHash = sha256(f);
|
||||
if (!extractedHash.equals(sha256Uncompressed)) {
|
||||
throw new RuntimeException("Extracted file hash does not match expected hash: " + remotePath +
|
||||
" -> " + f.getAbsolutePath() + " - expected has " + sha256Uncompressed + ", actual hash " + extractedHash);
|
||||
}
|
||||
|
||||
} finally {
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static String sha256(File f) {
|
||||
try (InputStream is = new BufferedInputStream(new FileInputStream(f))) {
|
||||
return DigestUtils.sha256Hex(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error when hashing file: " + f.getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final ObjectMapper newMapper() {
|
||||
ObjectMapper ret = new ObjectMapper();
|
||||
ret.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
ret.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
ret.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
|
||||
ret.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package org.nd4j.common.resources.strumpf;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.nd4j.common.config.ND4JEnvironmentVars;
|
||||
import org.nd4j.common.config.ND4JSystemProperties;
|
||||
import org.nd4j.common.io.ClassPathResource;
|
||||
import org.nd4j.common.resources.Resolver;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class StrumpfResolver implements Resolver {
|
||||
public static final String DEFAULT_CACHE_DIR = new File(System.getProperty("user.home"), ".cache/nd4j/test_resources").getAbsolutePath();
|
||||
public static final String REF = ".resource_reference";
|
||||
|
||||
protected final List<String> localResourceDirs;
|
||||
protected final File cacheDir;
|
||||
|
||||
public StrumpfResolver() {
|
||||
|
||||
String localDirs = System.getProperty(ND4JSystemProperties.RESOURCES_LOCAL_DIRS, null);
|
||||
|
||||
if (localDirs != null && !localDirs.isEmpty()) {
|
||||
String[] split = localDirs.split(",");
|
||||
localResourceDirs = Arrays.asList(split);
|
||||
} else {
|
||||
localResourceDirs = null;
|
||||
}
|
||||
|
||||
String cd = System.getenv(ND4JEnvironmentVars.ND4J_RESOURCES_CACHE_DIR);
|
||||
if(cd == null || cd.isEmpty()) {
|
||||
cd = System.getProperty(ND4JSystemProperties.RESOURCES_CACHE_DIR, DEFAULT_CACHE_DIR);
|
||||
}
|
||||
cacheDir = new File(cd);
|
||||
cacheDir.mkdirs();
|
||||
}
|
||||
|
||||
public int priority() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(@NonNull String resourcePath) {
|
||||
//First: check local dirs (if any exist)
|
||||
if (localResourceDirs != null && !localResourceDirs.isEmpty()) {
|
||||
for (String s : localResourceDirs) {
|
||||
//Check for standard file:
|
||||
File f1 = new File(s, resourcePath);
|
||||
if (f1.exists() && f1.isFile()) {
|
||||
//OK - found actual file
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check for reference file:
|
||||
File f2 = new File(s, resourcePath + REF);
|
||||
if (f2.exists() && f2.isFile()) {
|
||||
//OK - found resource reference
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Second: Check classpath
|
||||
ClassPathResource cpr = new ClassPathResource(resourcePath + REF);
|
||||
if (cpr.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cpr = new ClassPathResource(resourcePath);
|
||||
if (cpr.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean directoryExists(String dirPath) {
|
||||
//First: check local dirs (if any)
|
||||
if (localResourceDirs != null && !localResourceDirs.isEmpty()) {
|
||||
for (String s : localResourceDirs) {
|
||||
File f1 = new File(s, dirPath);
|
||||
if (f1.exists() && f1.isDirectory()) {
|
||||
//OK - found directory
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Second: Check classpath
|
||||
ClassPathResource cpr = new ClassPathResource(dirPath);
|
||||
if (cpr.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File asFile(String resourcePath) {
|
||||
assertExists(resourcePath);
|
||||
|
||||
if (localResourceDirs != null && !localResourceDirs.isEmpty()) {
|
||||
for (String s : localResourceDirs) {
|
||||
File f1 = new File(s, resourcePath);
|
||||
if (f1.exists() && f1.isFile()) {
|
||||
//OK - found actual file
|
||||
return f1;
|
||||
}
|
||||
|
||||
//Check for reference file:
|
||||
File f2 = new File(s, resourcePath + REF);
|
||||
if (f2.exists() && f2.isFile()) {
|
||||
//OK - found resource reference. Need to download to local cache... and/or validate what we have in cache
|
||||
ResourceFile rf = ResourceFile.fromFile(s);
|
||||
return rf.localFile(cacheDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Second: Check classpath for references (and actual file)
|
||||
ClassPathResource cpr = new ClassPathResource(resourcePath + REF);
|
||||
if (cpr.exists()) {
|
||||
ResourceFile rf;
|
||||
try {
|
||||
rf = ResourceFile.fromFile(cpr.getFile());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return rf.localFile(cacheDir);
|
||||
}
|
||||
|
||||
cpr = new ClassPathResource(resourcePath);
|
||||
if (cpr.exists()) {
|
||||
try {
|
||||
return cpr.getFile();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not find resource file that should exist: " + resourcePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream asStream(String resourcePath) {
|
||||
File f = asFile(resourcePath);
|
||||
log.debug("Resolved resource " + resourcePath + " as file at absolute path " + f.getAbsolutePath());
|
||||
try {
|
||||
return new BufferedInputStream(new FileInputStream(f));
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Error reading file for resource: \"" + resourcePath + "\" resolved to \"" + f + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyDirectory(String dirPath, File destinationDir) {
|
||||
//First: check local resource dir
|
||||
boolean resolved = false;
|
||||
if (localResourceDirs != null && !localResourceDirs.isEmpty()) {
|
||||
for (String s : localResourceDirs) {
|
||||
File f1 = new File(s, dirPath);
|
||||
try {
|
||||
FileUtils.copyDirectory(f1, destinationDir);
|
||||
resolved = true;
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Second: Check classpath
|
||||
if (!resolved) {
|
||||
ClassPathResource cpr = new ClassPathResource(dirPath);
|
||||
if (cpr.exists()) {
|
||||
try {
|
||||
cpr.copyDirectory(destinationDir);
|
||||
resolved = true;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolved) {
|
||||
throw new RuntimeException("Unable to find resource directory for path: " + dirPath);
|
||||
}
|
||||
|
||||
//Finally, scan directory (recursively) and replace any resource files with actual files...
|
||||
final List<Path> toResolve = new ArrayList<>();
|
||||
try {
|
||||
Files.walkFileTree(destinationDir.toPath(), new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (file.toString().endsWith(REF)) {
|
||||
toResolve.add(file);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (toResolve.size() > 0) {
|
||||
for (Path p : toResolve) {
|
||||
File localFile = ResourceFile.fromFile(p.toFile()).localFile(cacheDir);
|
||||
String newPath = p.toFile().getAbsolutePath();
|
||||
newPath = newPath.substring(0, newPath.length() - REF.length());
|
||||
File destination = new File(newPath);
|
||||
try {
|
||||
FileUtils.copyFile(localFile, destination);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
FileUtils.forceDelete(p.toFile());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error deleting temporary reference file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLocalCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File localCacheRoot() {
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String normalizePath(@NonNull String path) {
|
||||
if(path.endsWith(REF)){
|
||||
return path.substring(0, path.length()-REF.length());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
protected void assertExists(String resourcePath) {
|
||||
if (!exists(resourcePath)) {
|
||||
throw new IllegalStateException("Could not find resource with path \"" + resourcePath + "\" in local directories (" +
|
||||
localResourceDirs + ") or in classpath");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user