
prerna.engine.impl.r.RSingleton Maven / Gradle / Ivy
The newest version!
package prerna.engine.impl.r;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Hashtable;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.SystemUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import prerna.util.Constants;
import prerna.util.PortAllocator;
import prerna.util.Utility;
public class RSingleton {
private static final Logger classLogger = LogManager.getLogger(RSingleton.class);
private static RConnection rcon = null;
public static final String R_HOME = "R_HOME";
public static final String R_LIBS = "R_LIBS";
public static final String RSERVE_LOC = "/Rserve/libs/x64/Rserve";
static int port = -1;
static Hashtable portToCon = new Hashtable(); // RServe is not allowing me to inspect the port so I have to do this.. sorry
private RSingleton() {
port = PortAllocator.getInstance().getNextAvailablePort();
}
/**
* Get the connection and build if doesn't exist
* @return
*/
public static RConnection getConnection() {
if(rcon == null) {
int port = PortAllocator.getInstance().getNextAvailablePort();
return getConnection("127.0.0.1", port);
}
return rcon;
}
public static RConnection getConnection(int port) {
return getConnection("127.0.0.1", port);
}
/**
* Get the rconn object as is. This maybe null
* @return
*/
public static RConnection getRCon() {
return rcon;
}
public static void startRServe(int port) {
try {
String rHome = System.getenv(R_HOME);
String rLibs = System.getenv(R_LIBS);
classLogger.info("R_HOME env is is " + rHome);
classLogger.info("R_LIBS env is is " + rLibs);
// If R_HOME / R_LIBS doesn't exist, then check RDF_Map
if(rHome == null || rHome.isEmpty()) {
rHome = Utility.getDIHelperProperty(R_HOME);
}
if(rLibs == null || rLibs.isEmpty()) {
rLibs = Utility.getDIHelperProperty(R_LIBS);
}
// we like to keep our paths unix based
rHome = rHome.replace("\\", "/");
Path rHomePath = Paths.get(rHome);
if (!Files.isDirectory(rHomePath)) {
throw new IllegalArgumentException("rHome does not exist or is not a directory");
}
String rExe = rHome + "/bin/R";
// if we dont have a rLibs, lets assume its in rhome
if(rLibs == null) {
rLibs = rHome + "/library";
} else {
rLibs = rLibs.replace("\\", "/");
}
classLogger.info("R_HOME for the process is " + rHome);
classLogger.info("R_EXE for the process is " + rExe);
ProcessBuilder pb;
if (SystemUtils.IS_OS_WINDOWS) {
pb = new ProcessBuilder(rExe, "CMD", rLibs+RSERVE_LOC, "--vanilla", "--RS-port", port + "");
} else {
pb = new ProcessBuilder(rExe, "CMD", "Rserve", "--vanilla", "--RS-port", port + "");
}
Process process = pb.start();
classLogger.info("Waiting 1 second to allow Rserve to finish starting up...");
try {
process.waitFor(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
classLogger.error(Constants.STACKTRACE, e);
}
classLogger.info("Started RServe process");
} catch (IOException e) {
classLogger.error(Constants.STACKTRACE, e);
}
}
public static void stopRServe() {
stopRServe(port);
}
public static void stopRServe(int port) {
try {
String rHome = System.getenv("R_HOME");
if(rHome == null || rHome.isEmpty()) {
rHome = Utility.getDIHelperProperty(R_HOME);
}
rHome = rHome.replace("\\", "/");
Path rHomePath = Paths.get(rHome);
if (!Files.isDirectory(rHomePath)) {
throw new IllegalArgumentException("rHome does not exist or is not a directory");
}
rHome = rHome + "/bin/R";
classLogger.info("R_HOME for process is " + rHome);
ProcessBuilder pb = new ProcessBuilder("" + rHome + "", "-e", "library(Rserve);library(RSclient);rsc<-RSconnect(port=" + port + ");RSshutdown(rsc)", "--vanilla");
Process process = pb.start();
} catch (IOException e) {
classLogger.error(Constants.STACKTRACE, e);
}
}
public static RConnection getConnection(String host, int port) {
// this basically tries to do the same as get connection with a port
if(portToCon.containsKey(port)) {
rcon = portToCon.get(port);
} else {
classLogger.info("Making a master connection now on port " + port);
try {
rcon = new RConnection(host, port);
portToCon.put(port, rcon);
} catch(Exception ex) {
classLogger.error(Constants.STACKTRACE, ex);
// try to start again and see if that works
startRServe(port);
try {
rcon = new RConnection(host, port);
portToCon.put(port, rcon);
RSingleton.port = port;
} catch (RserveException e) {
classLogger.error(Constants.STACKTRACE, e);
}
}
}
if(rcon == null) {
classLogger.info("Generating master connection on port " + port + " is null");
}
return rcon;
}
/**
* KEEP THIS EVEN THOUGH NOT USED
* INCASE WE WNAT TO EVENTUALLY LOOK AT ALL THE PORTS IN PORT ALLOCATOR
* AND ATTEMPT TO USE THAT IF ITS AN RSERVE
* @param port
* @return
*/
private static boolean isRServe(int port) {
// try to see if this port is already running RServe
boolean isRserve = false;
classLogger.info("Trying to see if port " + port + " is already running Rserve.");
try {
rcon = new RConnection("127.0.0.1", port);
portToCon.put(port, rcon);
classLogger.info("Success! RServe: " + port);
isRserve = true;
} catch (Exception ex) {
// Port isn't open, notify and move on
classLogger.info("Port " + port + " is unavailable.");
}
return isRserve;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy