Migrate from ant to gradle

This commit is contained in:
Laurent Clouet
2019-08-10 22:09:32 +02:00
parent 9f1f509bb6
commit 3230807a7d
75 changed files with 317 additions and 80 deletions

View File

@@ -1,806 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadLocalRandom;
import com.sheepit.client.Error.ServerCode;
import com.sheepit.client.Error.Type;
import com.sheepit.client.exception.FermeException;
import com.sheepit.client.exception.FermeExceptionBadResponseFromServer;
import com.sheepit.client.exception.FermeExceptionNoRendererAvailable;
import com.sheepit.client.exception.FermeExceptionNoRightToRender;
import com.sheepit.client.exception.FermeExceptionNoSession;
import com.sheepit.client.exception.FermeExceptionNoSpaceLeftOnDevice;
import com.sheepit.client.exception.FermeExceptionServerInMaintenance;
import com.sheepit.client.exception.FermeExceptionServerOverloaded;
import com.sheepit.client.exception.FermeExceptionSessionDisabled;
import com.sheepit.client.exception.FermeServerDown;
import com.sheepit.client.os.OS;
import lombok.Data;
@Data
public class Client {
private Gui gui;
private Server server;
private Configuration configuration;
private Log log;
private Job renderingJob;
private Job previousJob;
private BlockingQueue<Job> jobsToValidate;
private boolean isValidatingJob;
private long startTime;
private boolean disableErrorSending;
private boolean running;
private boolean suspended;
private int maxDownloadFileAttempts = 5;
public Client(Gui gui_, Configuration configuration, String url_) {
this.configuration = configuration;
this.server = new Server(url_, this.configuration, this);
this.log = Log.getInstance(this.configuration);
this.gui = gui_;
this.renderingJob = null;
this.previousJob = null;
this.jobsToValidate = new ArrayBlockingQueue<Job>(1024);
this.isValidatingJob = false;
this.disableErrorSending = false;
this.running = false;
this.suspended = false;
}
public String toString() {
return String.format("Client (configuration %s, server %s)", this.configuration, this.server);
}
public int run() {
if (this.configuration.checkOSisSupported() == false) {
this.gui.error(Error.humanString(Error.Type.OS_NOT_SUPPORTED));
return -3;
}
if (this.configuration.checkCPUisSupported() == false) {
this.gui.error(Error.humanString(Error.Type.CPU_NOT_SUPPORTED));
return -4;
}
this.running = true;
int step;
try {
step = this.log.newCheckPoint();
this.gui.status("Starting");
this.configuration.cleanWorkingDirectory();
Error.Type ret;
ret = this.server.getConfiguration();
if (ret != Error.Type.OK) {
this.gui.error(Error.humanString(ret));
if (ret != Error.Type.AUTHENTICATION_FAILED) {
Log.printCheckPoint(step);
}
return -1;
}
this.startTime = new Date().getTime();
this.server.start(); // for staying alive
// create a thread which will send the frame
Runnable runnable_sender = new Runnable() {
public void run() {
senderLoop();
}
};
Thread thread_sender = new Thread(runnable_sender);
thread_sender.start();
while (this.running == true) {
this.renderingJob = null;
synchronized (this) {
while (this.suspended) {
wait();
}
}
step = this.log.newCheckPoint();
try {
Calendar next_request = this.nextJobRequest();
if (next_request != null) {
// wait
Date now = new Date();
this.gui.status(String.format("Waiting until %tR before requesting job", next_request));
long wait = next_request.getTimeInMillis() - now.getTime();
if (wait < 0) {
// it means the client has to wait until the next day
wait += 24*3600*1000;
}
try {
Thread.sleep(wait);
}
catch (InterruptedException e3) {
}
catch (IllegalArgumentException e3) {
this.log.error("Client::run sleepA failed " + e3);
}
}
this.gui.status("Requesting Job");
this.renderingJob = this.server.requestJob();
}
catch (FermeExceptionNoRightToRender e) {
this.gui.error("User does not have enough right to render scene");
return -2;
}
catch (FermeExceptionSessionDisabled e) {
this.gui.error(Error.humanString(Error.Type.SESSION_DISABLED));
// should wait forever to actually display the message to the user
while (true) {
try {
Thread.sleep(100000);
}
catch (InterruptedException e1) {
}
}
}
catch (FermeExceptionNoRendererAvailable e) {
this.gui.error(Error.humanString(Error.Type.RENDERER_NOT_AVAILABLE));
// should wait forever to actually display the message to the user
while (true) {
try {
Thread.sleep(100000);
}
catch (InterruptedException e1) {
}
}
}
catch (FermeExceptionNoSession e) {
this.log.debug("User has no session need to re-authenticate");
ret = this.server.getConfiguration();
if (ret != Error.Type.OK) {
this.renderingJob = null;
}
else {
this.startTime = new Date().getTime(); // reset start session time because the server did it
try {
Calendar next_request = this.nextJobRequest();
if (next_request != null) {
// wait
Date now = new Date();
this.gui.status(String.format("Waiting until %tR before requesting job", next_request));
try {
Thread.sleep(next_request.getTimeInMillis() - now.getTime());
}
catch (InterruptedException e3) {
}
catch (IllegalArgumentException e3) {
this.log.error("Client::run sleepB failed " + e3);
}
}
this.gui.status("Requesting Job");
this.renderingJob = this.server.requestJob();
}
catch (FermeException e1) {
this.renderingJob = null;
}
}
}
catch (FermeServerDown e) {
int wait = ThreadLocalRandom.current().nextInt(10, 30 + 1); // max is exclusive
int time_sleep = 1000 * 60 * wait;
this.gui.status(String.format("Can not connect to server. Please check your connectivity. Will retry in %s minutes", wait));
try {
Thread.sleep(time_sleep);
}
catch (InterruptedException e1) {
return -3;
}
continue; // go back to ask job
}
catch (FermeExceptionServerOverloaded e) {
int wait = ThreadLocalRandom.current().nextInt(10, 30 + 1); // max is exclusive
int time_sleep = 1000 * 60 * wait;
this.gui.status(String.format("Server is overloaded and cannot give frame to render. Will retry in %s minutes", wait));
try {
Thread.sleep(time_sleep);
}
catch (InterruptedException e1) {
return -3;
}
continue; // go back to ask job
}
catch (FermeExceptionServerInMaintenance e) {
int wait = ThreadLocalRandom.current().nextInt(20, 30 + 1); // max is exclusive
int time_sleep = 1000 * 60 * wait;
this.gui.status(String.format("Server is in maintenance and cannot give frame to render. Will retry in %s minutes", wait));
try {
Thread.sleep(time_sleep);
}
catch (InterruptedException e1) {
return -3;
}
continue; // go back to ask job
}
catch (FermeExceptionBadResponseFromServer e) {
int wait = ThreadLocalRandom.current().nextInt(15, 30 + 1); // max is exclusive
int time_sleep = 1000 * 60 * wait;
this.gui.status(String.format("Bad answer from server. Will retry in %s minutes", wait));
try {
Thread.sleep(time_sleep);
}
catch (InterruptedException e1) {
return -3;
}
continue; // go back to ask job
}
catch (FermeException e) {
this.gui.error("Client::run exception requestJob (1) " + e.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Client::run exception " + e + " stacktrace: " + sw.toString());
this.sendError(step);
continue;
}
if (this.renderingJob == null) { // no job
int wait = ThreadLocalRandom.current().nextInt(10, 30 + 1); // max is exclusive
int time_sleep = 1000 * 60 * wait;
Date wakeup_time = new Date(new Date().getTime() + time_sleep);
this.gui.status(String.format("No job available. Sleeping for %d minutes (will wake up at %tR)", wait, wakeup_time));
this.gui.displayStats(new Stats());
this.suspended = true;
int time_slept = 0;
while (time_slept < time_sleep && this.running == true) {
try {
Thread.sleep(250);
}
catch (InterruptedException e) {
return -3;
}
time_slept += 250;
}
this.suspended = false;
continue; // go back to ask job
}
this.log.debug("Got work to do id: " + this.renderingJob.getId() + " frame: " + this.renderingJob.getFrameNumber());
ret = this.work(this.renderingJob);
if (ret == Error.Type.RENDERER_KILLED) {
this.log.removeCheckPoint(step);
continue;
}
if (ret == Error.Type.NO_SPACE_LEFT_ON_DEVICE) {
Job frame_to_reset = this.renderingJob; // copy it because the sendError will take ~5min to execute
this.renderingJob = null;
this.gui.error(Error.humanString(ret));
this.sendError(step, frame_to_reset, ret);
this.log.removeCheckPoint(step);
return -50;
}
if (ret != Error.Type.OK) {
Job frame_to_reset = this.renderingJob; // copy it because the sendError will take ~5min to execute
this.renderingJob = null;
this.gui.error(Error.humanString(ret));
this.sendError(step, frame_to_reset, ret);
this.log.removeCheckPoint(step);
continue;
}
if (this.renderingJob.isSynchronousUpload() == false) { // power or compute_method job, need to upload right away
ret = confirmJob(this.renderingJob);
if (ret != Error.Type.OK) {
gui.error("Client::run problem with confirmJob (returned " + ret + ")");
sendError(step);
}
else {
gui.AddFrameRendered();
}
}
else {
this.jobsToValidate.add(this.renderingJob);
this.renderingJob = null;
}
while (this.shouldWaitBeforeRender() == true) {
try {
Thread.sleep(4000); // wait a little bit
}
catch (InterruptedException e3) {
}
}
this.log.removeCheckPoint(step);
}
// not running but maybe still sending frame
while (this.jobsToValidate.isEmpty() == false) {
try {
Thread.sleep(2300); // wait a little bit
}
catch (InterruptedException e3) {
}
}
}
catch (Exception e1) {
// no exception should be raised in the actual launcher (applet or standalone)
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e1.printStackTrace(pw);
this.log.debug("Client::run exception(D) " + e1 + " stacktrace: " + sw.toString());
return -99; // the this.stop will be done after the return of this.run()
}
this.gui.stop();
return 0;
}
public synchronized int stop() {
this.running = false;
this.disableErrorSending = true;
if (this.renderingJob != null) {
if (this.renderingJob.getProcessRender().getProcess() != null) {
this.renderingJob.setAskForRendererKill(true);
OS.getOS().kill(this.renderingJob.getProcessRender().getProcess());
}
}
// this.configuration.workingDirectory.delete();
this.configuration.removeWorkingDirectory();
if (this.server == null) {
return 0;
}
try {
this.server.HTTPRequest(this.server.getPage("logout"));
}
catch (IOException e) {
// nothing to do: if the logout failed that's ok
}
this.server.interrupt();
try {
this.server.join();
}
catch (InterruptedException e) {
}
this.server = null;
return 0;
}
public void suspend() {
suspended = true;
}
public synchronized void resume() {
suspended = false;
notify();
}
public void askForStop() {
this.log.debug("Client::askForStop");
this.running = false;
}
public void cancelStop() {
this.log.debug("Client::cancelStop");
this.running = true;
}
public int senderLoop() {
int step = log.newCheckPoint();
Error.Type ret;
while (true) {
Job job_to_send;
try {
job_to_send = jobsToValidate.take();
this.log.debug("will validate " + job_to_send);
//gui.status("Sending frame");
ret = confirmJob(job_to_send);
if (ret != Error.Type.OK) {
this.gui.error(Error.humanString(ret));
this.log.debug("Client::senderLoop confirm failed, ret: " + ret);
sendError(step);
}
else {
gui.AddFrameRendered();
}
}
catch (InterruptedException e) {
}
}
}
protected void sendError(int step_) {
this.sendError(step_, null, null);
}
protected void sendError(int step_, Job job_to_reset_, Error.Type error) {
if (this.disableErrorSending) {
this.log.debug("Error sending is disabled, do not send log");
return;
}
this.log.debug("Sending error to server (type: " + error + ")");
try {
File temp_file = File.createTempFile("farm_", "");
temp_file.createNewFile();
temp_file.deleteOnExit();
FileOutputStream writer = new FileOutputStream(temp_file);
ArrayList<String> logs = this.log.getForCheckPoint(step_);
for (String line : logs) {
writer.write(line.getBytes());
writer.write('\n');
}
writer.close();
String args = "?type=" + (error == null ? "" : error.getValue());
if (job_to_reset_ != null) {
args += "&frame=" + job_to_reset_.getFrameNumber() + "&job=" + job_to_reset_.getId() + "&render_time=" + job_to_reset_.getProcessRender().getDuration() + "&memoryused=" + job_to_reset_.getProcessRender().getMemoryUsed();
if (job_to_reset_.getExtras() != null && job_to_reset_.getExtras().isEmpty() == false) {
args += "&extras=" + job_to_reset_.getExtras();
}
}
this.server.HTTPSendFile(this.server.getPage("error") + args, temp_file.getAbsolutePath());
temp_file.delete();
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Client::sendError Exception " + e + " stacktrace: " + sw.toString());
// no exception should be raised to actual launcher (applet or standalone)
}
if (error != null && (error == Error.Type.RENDERER_CRASHED || error == Error.Type.RENDERER_KILLED_BY_USER || error == Error.Type.RENDERER_KILLED_BY_SERVER)) {
// do nothing, we can ask for a job right away
}
else {
try {
Thread.sleep(300000); // sleeping for 5min
}
catch (InterruptedException e) {
}
}
}
/**
*
* @return the date of the next request, or null if there is not delay (null <=> now)
*/
public Calendar nextJobRequest() {
if (this.configuration.getRequestTime() == null) {
return null;
}
else {
Calendar next = null;
Calendar now = Calendar.getInstance();
for (Pair<Calendar, Calendar> interval : this.configuration.getRequestTime()) {
Calendar start = (Calendar) now.clone();
Calendar end = (Calendar) now.clone();
start.set(Calendar.SECOND, 00);
start.set(Calendar.MINUTE, interval.first.get(Calendar.MINUTE));
start.set(Calendar.HOUR_OF_DAY, interval.first.get(Calendar.HOUR_OF_DAY));
end.set(Calendar.SECOND, 59);
end.set(Calendar.MINUTE, interval.second.get(Calendar.MINUTE));
end.set(Calendar.HOUR_OF_DAY, interval.second.get(Calendar.HOUR_OF_DAY));
if (start.before(now) && now.before(end)) {
return null;
}
if (next == null || (start.before(next) && start.after(now))) {
next = start;
}
}
return next;
}
}
public Error.Type work(final Job ajob) {
int ret;
gui.setRenderingProjectName(ajob.getName());
try {
ret = this.downloadExecutable(ajob);
if (ret != 0) {
gui.setRenderingProjectName("");
this.log.error("Client::work problem with downloadExecutable (ret " + ret + ")");
return Error.Type.DOWNLOAD_FILE;
}
ret = this.downloadSceneFile(ajob);
if (ret != 0) {
gui.setRenderingProjectName("");
this.log.error("Client::work problem with downloadSceneFile (ret " + ret + ")");
return Error.Type.DOWNLOAD_FILE;
}
ret = this.prepareWorkingDirectory(ajob); // decompress renderer and scene archives
if (ret != 0) {
gui.setRenderingProjectName("");
this.log.error("Client::work problem with this.prepareWorkingDirectory (ret " + ret + ")");
return Error.Type.CAN_NOT_CREATE_DIRECTORY;
}
}
catch (FermeExceptionNoSpaceLeftOnDevice e) {
gui.setRenderingProjectName("");
return Error.Type.NO_SPACE_LEFT_ON_DEVICE;
}
File scene_file = new File(ajob.getScenePath());
File renderer_file = new File(ajob.getRendererPath());
if (scene_file.exists() == false) {
gui.setRenderingProjectName("");
this.log.error("Client::work job preparation failed (scene file '" + scene_file.getAbsolutePath() + "' does not exist), cleaning directory in hope to recover");
this.configuration.cleanWorkingDirectory();
return Error.Type.MISSING_SCENE;
}
if (renderer_file.exists() == false) {
gui.setRenderingProjectName("");
this.log.error("Client::work job preparation failed (renderer file '" + renderer_file.getAbsolutePath() + "' does not exist), cleaning directory in hope to recover");
this.configuration.cleanWorkingDirectory();
return Error.Type.MISSING_RENDERER;
}
Observer removeSceneDirectoryOnceRenderHasStartedObserver = new Observer() {
@Override public void update(Observable observable, Object o) {
removeSceneDirectory(ajob);
}
};
Error.Type err = ajob.render(removeSceneDirectoryOnceRenderHasStartedObserver);
gui.setRenderingProjectName("");
gui.setRemainingTime("");
gui.setRenderingTime("");
gui.setComputeMethod("");
if (err != Error.Type.OK) {
this.log.error("Client::work problem with runRenderer (ret " + err + ")");
if (err == Error.Type.RENDERER_CRASHED_PYTHON_ERROR) {
this.log.error("Client::work failed with python error, cleaning directory in hope to recover");
this.configuration.cleanWorkingDirectory();
}
return err;
}
removeSceneDirectory(ajob);
return Error.Type.OK;
}
protected int downloadSceneFile(Job ajob_) throws FermeExceptionNoSpaceLeftOnDevice {
return this.downloadFile(ajob_, ajob_.getSceneArchivePath(), ajob_.getSceneMD5(), String.format("%s?type=job&job=%s", this.server.getPage("download-archive"), ajob_.getId()), "project");
}
protected int downloadExecutable(Job ajob) throws FermeExceptionNoSpaceLeftOnDevice {
return this.downloadFile(ajob, ajob.getRendererArchivePath(), ajob.getRendererMD5(), String.format("%s?type=binary&job=%s", this.server.getPage("download-archive"), ajob.getId()), "renderer");
}
private int downloadFile(Job ajob, String local_path, String md5_server, String url, String download_type) throws FermeExceptionNoSpaceLeftOnDevice {
File local_path_file = new File(local_path);
String update_ui = "Downloading " + download_type + " %s %%";
if (local_path_file.exists() == true) {
this.gui.status("Reusing cached " + download_type);
return 0;
}
this.gui.status("Downloading " + download_type);
// must download the archive
int ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui);
boolean md5_check = this.checkFile(ajob, local_path, md5_server);
int attempts = 1;
while ((ret != 0 || md5_check == false) && attempts < this.maxDownloadFileAttempts) {
if (ret != 0) {
this.gui.error("Client::downloadFile problem with Server.HTTPGetFile returned " + ret);
this.log.debug("Client::downloadFile problem with Server.HTTPGetFile (return: " + ret + ") removing local file (path: " + local_path + ")");
}
else if (md5_check == false) {
this.gui.error("Client::downloadFile problem with Client::checkFile mismatch on md5");
this.log.debug("Client::downloadFile problem with Client::checkFile mismatch on md5, removing local file (path: " + local_path + ")");
}
local_path_file.delete();
this.log.debug("Client::downloadFile failed, let's try again (" + (attempts + 1) + "/" + this.maxDownloadFileAttempts + ") ...");
ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui);
md5_check = this.checkFile(ajob, local_path, md5_server);
attempts++;
if ((ret != 0 || md5_check == false) && attempts >= this.maxDownloadFileAttempts) {
this.log.debug("Client::downloadFile failed after " + this.maxDownloadFileAttempts + " attempts, removing local file (path: " + local_path + "), stopping...");
local_path_file.delete();
return -9;
}
}
return 0;
}
private boolean checkFile(Job ajob, String local_path, String md5_server) {
File local_path_file = new File(local_path);
if (local_path_file.exists() == false) {
this.log.error("Client::checkFile cannot check md5 on a nonexistent file (path: " + local_path + ")");
return false;
}
String md5_local = Utils.md5(local_path);
if (md5_local.equals(md5_server) == false) {
this.log.error("Client::checkFile mismatch on md5 local: '" + md5_local + "' server: '" + md5_server + "' (local size: " + new File(local_path).length() + ")");
return false;
}
return true;
}
protected void removeSceneDirectory(Job ajob) {
Utils.delete(new File(ajob.getSceneDirectory()));
}
protected int prepareWorkingDirectory(Job ajob) throws FermeExceptionNoSpaceLeftOnDevice {
int ret;
String renderer_archive = ajob.getRendererArchivePath();
String renderer_path = ajob.getRendererDirectory();
File renderer_path_file = new File(renderer_path);
if (renderer_path_file.exists()) {
// Directory already exists -> do nothing
}
else {
this.gui.status("Extracting renderer");
// we create the directory
renderer_path_file.mkdir();
// unzip the archive
ret = Utils.unzipFileIntoDirectory(renderer_archive, renderer_path, null, log);
if (ret != 0) {
this.log.error("Client::prepareWorkingDirectory, error(1) with Utils.unzipFileIntoDirectory(" + renderer_archive + ", " + renderer_path + ") returned " + ret);
this.gui.error("Client::prepareWorkingDirectory, error with Utils.unzipFileIntoDirectory of the renderer (returned " + ret + ")");
return -1;
}
try {
File f = new File(ajob.getRendererPath());
f.setExecutable(true);
}
catch (SecurityException e) {
}
}
String scene_archive = ajob.getSceneArchivePath();
String scene_path = ajob.getSceneDirectory();
File scene_path_file = new File(scene_path);
if (scene_path_file.exists()) {
// Directory already exists -> do nothing
}
else {
this.gui.status("Extracting project");
// we create the directory
scene_path_file.mkdir();
// unzip the archive
ret = Utils.unzipFileIntoDirectory(scene_archive, scene_path, ajob.getPassword(), log);
if (ret != 0) {
this.log.error("Client::prepareWorkingDirectory, error(2) with Utils.unzipFileIntoDirectory(" + scene_archive + ", " + scene_path + ") returned " + ret);
this.gui.error("Client::prepareWorkingDirectory, error with Utils.unzipFileIntoDirectory of the scene (returned " + ret + ")");
return -2;
}
}
return 0;
}
protected Error.Type confirmJob(Job ajob) {
String extras_config = "";
RenderProcess process = ajob.getProcessRender();
if (process != null && process.getCoresUsed() > 0) {
extras_config = "&cores=" + process.getCoresUsed();
}
String url_real = String.format("%s?job=%s&frame=%s&rendertime=%d&memoryused=%s&extras=%s%s", this.server.getPage("validate-job"), ajob.getId(), ajob.getFrameNumber(), ajob.getProcessRender().getDuration(), ajob.getProcessRender().getMemoryUsed(), ajob.getExtras(), extras_config);
this.isValidatingJob = true;
int nb_try = 1;
int max_try = 3;
ServerCode ret = ServerCode.UNKNOWN;
while (nb_try < max_try && ret != ServerCode.OK) {
ret = this.server.HTTPSendFile(url_real, ajob.getOutputImagePath());
switch (ret) {
case OK:
// no issue, exit the loop
nb_try = max_try;
break;
case JOB_VALIDATION_ERROR_SESSION_DISABLED:
case JOB_VALIDATION_ERROR_BROKEN_MACHINE:
return Type.SESSION_DISABLED;
case JOB_VALIDATION_ERROR_MISSING_PARAMETER:
// no point to retry the request
return Error.Type.UNKNOWN;
default:
// do nothing, try to do a request on the next loop
break;
}
nb_try++;
if (ret != ServerCode.OK && nb_try < max_try) {
try {
this.log.debug("Sleep for 32s before trying to re-upload the frame");
Thread.sleep(32000);
}
catch (InterruptedException e) {
return Error.Type.UNKNOWN;
}
}
}
this.isValidatingJob = false;
// we can remove the frame file
File frame = new File(ajob.getOutputImagePath());
frame.delete();
ajob.setOutputImagePath(null);
this.isValidatingJob = false;
this.previousJob = ajob;
return Error.Type.OK;
}
protected boolean shouldWaitBeforeRender() {
int concurrent_job = this.jobsToValidate.size();
if (this.isValidatingJob) {
concurrent_job++;
}
return (concurrent_job >= this.configuration.getMaxUploadingJob());
}
}

View File

@@ -1,306 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import com.sheepit.client.hardware.cpu.CPU;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.os.OS;
import lombok.Data;
@Data
public class Configuration {
public enum ComputeType {
CPU_GPU, CPU, GPU
} // accept job for ...
private String configFilePath;
private File workingDirectory;
private File storageDirectory; // for permanent storage (binary archive)
private boolean userHasSpecifiedACacheDir;
private String static_exeDirName;
private String login;
private String password;
private String proxy;
private int maxUploadingJob;
private int nbCores;
private long maxMemory; // max memory allowed for render
private int maxRenderTime; // max render time per frame allowed
private int priority;
private ComputeType computeMethod;
private GPUDevice GPUDevice;
private boolean detectGPUs;
private boolean printLog;
private List<Pair<Calendar, Calendar>> requestTime;
private String extras;
private boolean autoSignIn;
private String UIType;
private int tileSize;
private String hostname;
public Configuration(File cache_dir_, String login_, String password_) {
this.configFilePath = null;
this.login = login_;
this.password = password_;
this.proxy = null;
this.hostname = this.getDefaultHostname();
this.static_exeDirName = "exe";
this.maxUploadingJob = 1;
this.nbCores = -1; // ie not set
this.maxMemory = -1; // ie not set
this.maxRenderTime = -1; // ie not set
this.priority = 19; // default lowest
this.computeMethod = null;
this.GPUDevice = null;
this.userHasSpecifiedACacheDir = false;
this.detectGPUs = true;
this.workingDirectory = null;
this.storageDirectory = null;
this.setCacheDir(cache_dir_);
this.printLog = false;
this.requestTime = null;
this.extras = "";
this.autoSignIn = false;
this.UIType = null;
this.tileSize = -1; // ie not set
}
public String toString() {
return String.format("Configuration (workingDirectory '%s')", this.workingDirectory.getAbsolutePath());
}
public void setUsePriority(int priority) {
if (priority > 19)
priority = 19;
if (priority < -19)
priority = -19;
this.priority = priority;
}
public int computeMethodToInt() {
return this.computeMethod.ordinal();
}
public void setCacheDir(File cache_dir_) {
removeWorkingDirectory();
if (cache_dir_ == null) {
this.userHasSpecifiedACacheDir = false;
try {
this.workingDirectory = File.createTempFile("farm_", "");
this.workingDirectory.createNewFile(); // hoho...
this.workingDirectory.delete(); // hoho
this.workingDirectory.mkdir();
this.workingDirectory.deleteOnExit();
// since there is no working directory and the client will be working in the system temp directory,
// we can also set up a 'permanent' directory for immutable files (like renderer binary)
this.storageDirectory = new File(this.workingDirectory.getParent() + File.separator + "sheepit_binary_cache");
this.storageDirectory.mkdir();
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
this.userHasSpecifiedACacheDir = true;
this.workingDirectory = new File(cache_dir_.getAbsolutePath() + File.separator + "sheepit");
this.storageDirectory = new File(cache_dir_.getAbsolutePath() + File.separator + "sheepit_binary_cache");
this.workingDirectory.mkdirs();
this.storageDirectory.mkdirs();
}
}
public void setStorageDir(File dir) {
if (dir != null) {
if (dir.exists() == false) {
dir.mkdir();
}
this.storageDirectory = dir;
}
}
public File getStorageDir() {
if (this.storageDirectory == null) {
return this.workingDirectory;
}
else {
return this.storageDirectory;
}
}
public File getCacheDirForSettings() {
if (this.userHasSpecifiedACacheDir == false) {
return null;
}
else {
// when the user have a cache directory a "sheepit" and "sheepit_binary_cache" is be automaticaly added
return this.workingDirectory.getParentFile();
}
}
public String getDefaultHostname() {
try {
return InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e) {
return "";
}
}
public void cleanWorkingDirectory() {
this.cleanDirectory(this.workingDirectory);
this.cleanDirectory(this.storageDirectory);
}
public boolean cleanDirectory(File dir) {
if (dir == null) {
return false;
}
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
Utils.delete(file);
}
else {
try {
String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase();
String name = file.getName().substring(0, file.getName().length() - 1 * extension.length());
if (extension.equals(".zip")) {
// check if the md5 of the file is ok
String md5_local = Utils.md5(file.getAbsolutePath());
if (md5_local.equals(name) == false) {
file.delete();
}
// TODO: remove old one
}
else {
file.delete();
}
}
catch (StringIndexOutOfBoundsException e) { // because the file does not have an . in his path
file.delete();
}
}
}
}
return true;
}
public void removeWorkingDirectory() {
if (this.userHasSpecifiedACacheDir) {
this.cleanWorkingDirectory();
}
else {
Utils.delete(this.workingDirectory);
}
}
public List<File> getLocalCacheFiles() {
List<File> files_local = new LinkedList<File>();
List<File> files = new LinkedList<File>();
if (this.workingDirectory != null) {
File[] filesInDirectory = this.workingDirectory.listFiles();
if (filesInDirectory != null) {
files.addAll(Arrays.asList(filesInDirectory));
}
}
if (this.storageDirectory != null) {
File[] filesInDirectory = this.storageDirectory.listFiles();
if (filesInDirectory != null) {
files.addAll(Arrays.asList(filesInDirectory));
}
}
for (File file : files) {
if (file.isFile()) {
try {
String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase();
String name = file.getName().substring(0, file.getName().length() - 1 * extension.length());
if (extension.equals(".zip")) {
// check if the md5 of the file is ok
String md5_local = Utils.md5(file.getAbsolutePath());
if (md5_local.equals(name)) {
files_local.add(file);
}
}
}
catch (StringIndexOutOfBoundsException e) { // because the file does not have an . his path
}
}
}
return files_local;
}
public String getJarVersion() {
String versionPath = "/VERSION";
InputStream versionStream = Client.class.getResourceAsStream(versionPath);
if (versionStream == null) {
System.err.println("Configuration::getJarVersion Failed to get version file");
return "5.0.0";
}
try {
InputStreamReader reader = new InputStreamReader(versionStream);
BufferedReader in = new BufferedReader(reader);
String version = in.readLine();
return version;
}
catch (IOException ex) {
System.err.println("Configuration::getJarVersion error while reading manifest file (" + versionPath + "): " + ex.getMessage());
return "5.0.0";
}
}
public boolean checkOSisSupported() {
return OS.getOS() != null;
}
public boolean checkCPUisSupported() {
OS os = OS.getOS();
if (os != null) {
CPU cpu = os.getCPU();
return cpu != null && cpu.haveData();
}
return false;
}
}

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
public class Error {
public enum Type {
// id have to be kept synchronised with the server side.
OK(0),
UNKNOWN(99),
WRONG_CONFIGURATION(1),
AUTHENTICATION_FAILED(2),
TOO_OLD_CLIENT(3),
SESSION_DISABLED(4),
RENDERER_NOT_AVAILABLE(5),
MISSING_RENDERER(6),
MISSING_SCENE(7),
NOOUTPUTFILE(8),
DOWNLOAD_FILE(9),
CAN_NOT_CREATE_DIRECTORY(10),
NETWORK_ISSUE(11),
RENDERER_CRASHED(12),
RENDERER_CRASHED_PYTHON_ERROR(24),
RENDERER_OUT_OF_VIDEO_MEMORY(13),
RENDERER_OUT_OF_MEMORY(21),
RENDERER_KILLED(14),
RENDERER_KILLED_BY_USER(20),
RENDERER_KILLED_BY_USER_OVER_TIME(23),
RENDERER_KILLED_BY_SERVER(22),
RENDERER_MISSING_LIBRARIES(15),
FAILED_TO_EXECUTE(16),
OS_NOT_SUPPORTED(17),
CPU_NOT_SUPPORTED(18),
GPU_NOT_SUPPORTED(19),
// internal error handling
NO_SPACE_LEFT_ON_DEVICE(100),
ERROR_BAD_RESPONSE(101),
;
private final int id;
private Type(int id) {
this.id = id;
}
public int getValue() {
return id;
}
}
public enum ServerCode {
OK(0),
UNKNOWN(999),
CONFIGURATION_ERROR_NO_CLIENT_VERSION_GIVEN(100),
CONFIGURATION_ERROR_CLIENT_TOO_OLD(101),
CONFIGURATION_ERROR_AUTH_FAILED(102),
CONFIGURATION_ERROR_WEB_SESSION_EXPIRED(103),
CONFIGURATION_ERROR_MISSING_PARAMETER(104),
JOB_REQUEST_NOJOB(200),
JOB_REQUEST_ERROR_NO_RENDERING_RIGHT(201),
JOB_REQUEST_ERROR_DEAD_SESSION(202),
JOB_REQUEST_ERROR_SESSION_DISABLED(203),
JOB_REQUEST_ERROR_INTERNAL_ERROR(204),
JOB_REQUEST_ERROR_RENDERER_NOT_AVAILABLE(205),
JOB_REQUEST_SERVER_IN_MAINTENANCE(206),
JOB_REQUEST_SERVER_OVERLOADED(207),
JOB_VALIDATION_ERROR_MISSING_PARAMETER(300),
JOB_VALIDATION_ERROR_BROKEN_MACHINE(301), // in GPU the generated frame is black
JOB_VALIDATION_ERROR_FRAME_IS_NOT_IMAGE(302),
JOB_VALIDATION_ERROR_UPLOAD_FAILED(303),
JOB_VALIDATION_ERROR_SESSION_DISABLED(304), // missing heartbeat or broken machine
KEEPMEALIVE_STOP_RENDERING(400),
// internal error handling
ERROR_NO_ROOT(2),
ERROR_BAD_RESPONSE(3),
ERROR_REQUEST_FAILED(5);
private final int id;
private ServerCode(int id) {
this.id = id;
}
public int getValue() {
return id;
}
public static ServerCode fromInt(int val) {
ServerCode[] As = ServerCode.values();
for (ServerCode A : As) {
if (A.getValue() == val) {
return A;
}
}
return ServerCode.UNKNOWN;
}
}
public static Type ServerCodeToType(ServerCode sc) {
switch (sc) {
case OK:
return Type.OK;
case UNKNOWN:
return Type.UNKNOWN;
case CONFIGURATION_ERROR_CLIENT_TOO_OLD:
return Type.TOO_OLD_CLIENT;
case CONFIGURATION_ERROR_AUTH_FAILED:
return Type.AUTHENTICATION_FAILED;
case CONFIGURATION_ERROR_NO_CLIENT_VERSION_GIVEN:
case CONFIGURATION_ERROR_WEB_SESSION_EXPIRED:
return Type.WRONG_CONFIGURATION;
case JOB_REQUEST_ERROR_SESSION_DISABLED:
case JOB_VALIDATION_ERROR_SESSION_DISABLED:
return Type.SESSION_DISABLED;
case JOB_REQUEST_ERROR_RENDERER_NOT_AVAILABLE:
return Type.RENDERER_NOT_AVAILABLE;
default:
return Type.UNKNOWN;
}
}
public static String humanString(Type in) {
switch (in) {
case ERROR_BAD_RESPONSE:
return "Bad answer from server. It's a server side error, wait a bit and retry later.";
case NETWORK_ISSUE:
return "Could not connect to the server, please check if you have connectivity issue";
case TOO_OLD_CLIENT:
return "This client is too old, you need to update it";
case AUTHENTICATION_FAILED:
return "Failed to authenticate, please check your login and password";
case DOWNLOAD_FILE:
return "Error while downloading project files. Will try another project in a few minutes.";
case NOOUTPUTFILE:
return "Renderer has generated no output file, possibly a wrong project configuration or you are missing required libraries. Will try another project in a few minutes.";
case RENDERER_CRASHED:
return "Renderer has crashed. It's usually due to a bad project or not enough memory. There is nothing you can do about it. Will try another project in a few minutes.";
case RENDERER_CRASHED_PYTHON_ERROR:
return "Renderer has crashed due to Python error. Will try another project in a few minutes.";
case RENDERER_OUT_OF_VIDEO_MEMORY:
return "Renderer has crashed, due to not enough video memory (vram). There is nothing you can do about it. Will try another project in a few minutes.";
case RENDERER_OUT_OF_MEMORY:
return "No more memory available. There is nothing you can do about it. Will try another project in a few minutes.";
case GPU_NOT_SUPPORTED:
return "Rendering have failed because your GPU is not supported";
case RENDERER_MISSING_LIBRARIES:
return "Failed to launch renderer. Please check if you have necessary libraries installed and if you have enough free space in your working directory.";
case RENDERER_KILLED:
return "The renderer stopped because either you asked to stop or the server did (usually for a render time too high).";
case RENDERER_KILLED_BY_USER:
return "The renderer stopped because you've blocked its project.";
case RENDERER_KILLED_BY_SERVER:
return "The renderer stopped because it's been killed by the server. Usually because the project will take too much time or it's been paused.";
case SESSION_DISABLED:
return "The server has disabled your session. Your client may have generated a broken frame (GPU not compatible, not enough RAM/VRAM, etc).";
case RENDERER_NOT_AVAILABLE:
return "No renderer are available on the server for your machine.";
case MISSING_RENDERER:
return "Unable to locate the Blender renderer within the binary download.";
case OS_NOT_SUPPORTED:
return "Operating System not supported.";
case CPU_NOT_SUPPORTED:
return "CPU not supported.";
case NO_SPACE_LEFT_ON_DEVICE:
return "No space left on hard disk";
default:
return in.toString();
}
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright (C) 2010-2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
public interface Gui {
public void start();
public void stop();
public void status(String msg_);
public void setRenderingProjectName(String name_);
public void setRemainingTime(String time_);
public void setRenderingTime(String time_);
public void displayStats(Stats stats);
public void error(String err_);
public void AddFrameRendered();
public void setClient(Client cli);
public void setComputeMethod(String computeMethod_);
public Client getClient();
}

View File

@@ -1,795 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.Error.Type;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.hardware.gpu.opencl.OpenCL;
import com.sheepit.client.os.OS;
import lombok.Data;
import lombok.Getter;
@Data
public class Job {
public static final String UPDATE_METHOD_BY_REMAINING_TIME = "remainingtime";
public static final String UPDATE_METHOD_BLENDER_INTERNAL_BY_PART = "blenderinternal";
public static final String UPDATE_METHOD_BY_TILE = "by_tile";
private String frameNumber;
private String sceneMD5;
private String rendererMD5;
private String id;
private String outputImagePath;
private String path; // path inside of the archive
private String rendererCommand;
private String script;
private boolean useGPU;
private String name;
private String password;
private String extras;
private String updateRenderingStatusMethod;
private boolean synchronousUpload;
private RenderProcess render;
private boolean askForRendererKill;
private boolean userBlockJob;
private boolean serverBlockJob;
private Gui gui;
private Configuration configuration;
private Log log;
public Job(Configuration config_, Gui gui_, Log log_, String id_, String frame_, String path_, boolean use_gpu, String command_, String script_, String sceneMd5_, String rendererMd5_, String name_, String password_, String extras_, boolean synchronous_upload_, String update_method_) {
configuration = config_;
id = id_;
frameNumber = frame_;
path = path_;
useGPU = use_gpu;
rendererCommand = command_;
sceneMD5 = sceneMd5_;
rendererMD5 = rendererMd5_;
name = name_;
password = password_;
extras = extras_;
synchronousUpload = synchronous_upload_;
gui = gui_;
outputImagePath = null;
script = script_;
updateRenderingStatusMethod = update_method_;
askForRendererKill = false;
userBlockJob = false;
serverBlockJob = false;
log = log_;
render = new RenderProcess();
}
public void block() {
setAskForRendererKill(true);
setUserBlockJob(true);
RenderProcess process = getProcessRender();
if (process != null) {
OS.getOS().kill(process.getProcess());
}
}
public RenderProcess getProcessRender() {
return render;
}
public String toString() {
return String.format("Job (numFrame '%s' sceneMD5 '%s' rendererMD5 '%s' ID '%s' pictureFilename '%s' jobPath '%s' gpu %s name '%s' extras '%s' updateRenderingStatusMethod '%s' render %s)", frameNumber, sceneMD5, rendererMD5, id, outputImagePath, path, useGPU, name, extras, updateRenderingStatusMethod, render);
}
public String getPrefixOutputImage() {
return id + "_";
}
public String getRendererDirectory() {
return configuration.getWorkingDirectory().getAbsolutePath() + File.separator + rendererMD5;
}
public String getRendererPath() {
return getRendererDirectory() + File.separator + OS.getOS().getRenderBinaryPath();
}
public String getRendererArchivePath() {
return configuration.getStorageDir().getAbsolutePath() + File.separator + rendererMD5 + ".zip";
}
public String getSceneDirectory() {
return configuration.getWorkingDirectory().getAbsolutePath() + File.separator + sceneMD5;
}
public String getScenePath() {
return getSceneDirectory() + File.separator + this.path;
}
public String getSceneArchivePath() {
return configuration.getWorkingDirectory().getAbsolutePath() + File.separator + sceneMD5 + ".zip";
}
public Error.Type render(Observer renderStarted) {
gui.status("Rendering");
RenderProcess process = getProcessRender();
Timer timerOfMaxRenderTime = null;
String core_script = "";
// When sending Ctrl+C to the terminal it also get's sent to all subprocesses e.g. also the render process.
// The java program handles Ctrl+C but the renderer quits on Ctrl+C.
// This script causes the renderer to ignore Ctrl+C.
String ignore_signal_script= "import signal\n"
+ "def hndl(signum, frame):\n"
+ " pass\n"
+ "signal.signal(signal.SIGINT, hndl)\n";
if (isUseGPU() && configuration.getGPUDevice() != null && configuration.getComputeMethod() != ComputeType.CPU) {
core_script = "sheepit_set_compute_device(\"" + configuration.getGPUDevice().getType() + "\", \"GPU\", \"" + configuration.getGPUDevice().getId() + "\")\n";
gui.setComputeMethod("GPU");
}
else {
core_script = "sheepit_set_compute_device(\"NONE\", \"CPU\", \"CPU\")\n";
gui.setComputeMethod("CPU");
}
core_script += ignore_signal_script;
core_script += String.format("bpy.context.scene.render.tile_x = %1$d\nbpy.context.scene.render.tile_y = %1$d\n", getTileSize());
File script_file = null;
String command1[] = getRendererCommand().split(" ");
int size_command = command1.length + 2; // + 2 for script
if (configuration.getNbCores() > 0) { // user has specified something
size_command += 2;
}
List<String> command = new ArrayList<String>(size_command);
Map<String, String> new_env = new HashMap<String, String>();
new_env.put("BLENDER_USER_CONFIG", configuration.getWorkingDirectory().getAbsolutePath().replace("\\", "\\\\"));
new_env.put("CORES", Integer.toString(configuration.getNbCores()));
new_env.put("PRIORITY", Integer.toString(configuration.getPriority()));
new_env.put("PYTHONPATH", ""); // make sure blender is using the embedded python, if not it could create "Fatal Python error: Py_Initialize"
new_env.put("PYTHONHOME", "");// make sure blender is using the embedded python, if not it could create "Fatal Python error: Py_Initialize"
if (isUseGPU() && configuration.getGPUDevice() != null && configuration.getComputeMethod() != ComputeType.CPU && OpenCL.TYPE.equals(configuration.getGPUDevice().getType())) {
new_env.put("CYCLES_OPENCL_SPLIT_KERNEL_TEST", "1");
this.updateRenderingStatusMethod = UPDATE_METHOD_BY_TILE; // don't display remaining time
}
for (String arg : command1) {
switch (arg) {
case ".c":
command.add(getScenePath());
command.add("-P");
try {
script_file = File.createTempFile("script_", "", configuration.getWorkingDirectory());
File file = new File(script_file.getAbsolutePath());
FileWriter txt;
txt = new FileWriter(file);
PrintWriter out = new PrintWriter(txt);
out.write(getScript());
out.write("\n");
out.write(core_script); // GPU part
out.write("\n"); // GPU part
out.close();
command.add(script_file.getAbsolutePath());
}
catch (IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("Job::render exception on script generation, will return UNKNOWN " + e + " stacktrace " + sw.toString());
return Error.Type.UNKNOWN;
}
script_file.deleteOnExit();
break;
case ".e":
command.add(getRendererPath());
// the number of cores has to be put after the binary and before the scene arg
if (configuration.getNbCores() > 0) {
command.add("-t");
command.add(Integer.toString(configuration.getNbCores()));
}
break;
case ".o":
command.add(configuration.getWorkingDirectory().getAbsolutePath() + File.separator + getPrefixOutputImage());
break;
case ".f":
command.add(getFrameNumber());
break;
default:
command.add(arg);
break;
}
}
try {
renderStartedObservable event = new renderStartedObservable(renderStarted);
String line;
log.debug(command.toString());
OS os = OS.getOS();
process.setCoresUsed(configuration.getNbCores());
process.start();
getProcessRender().setProcess(os.exec(command, new_env));
BufferedReader input = new BufferedReader(new InputStreamReader(getProcessRender().getProcess().getInputStream()));
if (configuration.getMaxRenderTime() > 0) {
timerOfMaxRenderTime = new Timer();
timerOfMaxRenderTime.schedule(new TimerTask() {
@Override
public void run() {
RenderProcess process = getProcessRender();
if (process != null) {
long duration = (new Date().getTime() - process.getStartTime() ) / 1000; // in seconds
if (configuration.getMaxRenderTime() > 0 && duration > configuration.getMaxRenderTime()) {
log.debug("Killing render because process duration");
OS.getOS().kill(process.getProcess());
setAskForRendererKill(true);
}
}
}
}, configuration.getMaxRenderTime() * 1000 + 2000); // +2s to be sure the delay is over
}
log.debug("renderer output");
try {
while ((line = input.readLine()) != null) {
log.debug(line);
updateRenderingMemoryPeak(line);
if (configuration.getMaxMemory() != -1 && process.getMemoryUsed() > configuration.getMaxMemory()) {
log.debug("Blocking render because process ram used (" + process.getMemoryUsed() + "k) is over user setting (" + configuration.getMaxMemory() + "k)");
OS.getOS().kill(process.getProcess());
process.finish();
if (script_file != null) {
script_file.delete();
}
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
updateRenderingStatus(line);
Type error = detectError(line);
if (error != Error.Type.OK) {
if (script_file != null) {
script_file.delete();
}
return error;
}
if (event.isStarted() == false && (process.getMemoryUsed() > 0 || process.getRemainingDuration() > 0)) {
event.doNotifyIsStarted();
}
}
input.close();
}
catch (IOException err1) { // for the input.readline
// most likely The handle is invalid
log.error("Job::render exception(B) (silent error) " + err1);
}
log.debug("end of rendering");
}
catch (Exception err) {
if (script_file != null) {
script_file.delete();
}
StringWriter sw = new StringWriter();
err.printStackTrace(new PrintWriter(sw));
log.error("Job::render exception(A) " + err + " stacktrace " + sw.toString());
return Error.Type.FAILED_TO_EXECUTE;
}
int exit_value = process.exitValue();
process.finish();
if (timerOfMaxRenderTime != null) {
timerOfMaxRenderTime.cancel();
}
if (script_file != null) {
script_file.delete();
}
// find the picture file
final String filename_without_extension = getPrefixOutputImage() + getFrameNumber();
FilenameFilter textFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(filename_without_extension);
}
};
File[] files = configuration.getWorkingDirectory().listFiles(textFilter);
if (isAskForRendererKill()) {
log.debug("Job::render been asked to end render");
long duration = (new Date().getTime() - process.getStartTime() ) / 1000; // in seconds
if (configuration.getMaxRenderTime() > 0 && duration > configuration.getMaxRenderTime()) {
log.debug("Render killed because process duration (" + duration + "s) is over user setting (" + configuration.getMaxRenderTime() + "s)");
return Error.Type.RENDERER_KILLED_BY_USER_OVER_TIME;
}
if (files.length != 0) {
new File(files[0].getAbsolutePath()).delete();
}
if (isServerBlockJob()) {
return Error.Type.RENDERER_KILLED_BY_SERVER;
}
if (isUserBlockJob()) {
return Error.Type.RENDERER_KILLED_BY_USER;
}
return Error.Type.RENDERER_KILLED;
}
if (files.length == 0) {
log.error("Job::render no picture file found (after finished render (filename_without_extension " + filename_without_extension + ")");
String basename = "";
try {
basename = getPath().substring(0, getPath().lastIndexOf('.'));
}
catch (Exception e) {
e.printStackTrace();
}
File crash_file = new File(configuration.getWorkingDirectory() + File.separator + basename + ".crash.txt");
if (crash_file.exists()) {
log.error("Job::render crash file found => the renderer crashed");
crash_file.delete();
return Error.Type.RENDERER_CRASHED;
}
if (exit_value == 127 && process.getDuration() < 10) {
log.error("Job::render renderer returned 127 and took " + process.getDuration() + "s, some libraries may be missing");
return Error.Type.RENDERER_MISSING_LIBRARIES;
}
return Error.Type.NOOUTPUTFILE;
}
else {
setOutputImagePath(files[0].getAbsolutePath());
log.debug("Job::render pictureFilename: '" + getOutputImagePath() + "'");
}
File scene_dir = new File(getSceneDirectory());
long date_modification_scene_directory = (long) Utils.lastModificationTime(scene_dir);
if (date_modification_scene_directory > process.getStartTime()) {
scene_dir.delete();
}
gui.status(String.format("Frame rendered in %dmin%ds", process.getDuration() / 60, process.getDuration() % 60));
return Error.Type.OK;
}
private void updateRenderingStatus(String line) {
if (getUpdateRenderingStatusMethod() != null && getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BLENDER_INTERNAL_BY_PART)) {
String search = " Part ";
int index = line.lastIndexOf(search);
if (index != -1) {
String buf = line.substring(index + search.length());
String[] parts = buf.split("-");
if (parts.length == 2) {
try {
int current = Integer.parseInt(parts[0]);
int total = Integer.parseInt(parts[1]);
if (total != 0) {
long end_render = (new Date().getTime() - this.render.getStartTime()) * total / current;
Date date = new Date(end_render);
gui.setRemainingTime(String.format("%s %% (%s)", (int) (100.0 - 100.0 * current / total), Utils.humanDuration(date)));
getProcessRender().setRemainingDuration((int) (date.getTime() / 1000));
return;
}
}
catch (NumberFormatException e) {
System.out.println("Exception 92: " + e);
}
}
}
gui.status("Rendering");
}
else if (getUpdateRenderingStatusMethod() == null || getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BY_REMAINING_TIME)) {
String search_remaining = "remaining:";
int index = line.toLowerCase().indexOf(search_remaining);
if (index != -1) {
String buf1 = line.substring(index + search_remaining.length());
index = buf1.indexOf(" ");
if (index != -1) {
String remaining_time = buf1.substring(0, index).trim();
int last_index = remaining_time.lastIndexOf('.'); //format 00:00:00.00 (hr:min:sec)
if (last_index > 0) {
remaining_time = remaining_time.substring(0, last_index);
}
try {
DateFormat date_parse_minute = new SimpleDateFormat("m:s");
DateFormat date_parse_hour = new SimpleDateFormat("h:m:s");
DateFormat date_parse = date_parse_minute;
if (remaining_time.split(":").length > 2) {
date_parse = date_parse_hour;
}
date_parse.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = date_parse.parse(remaining_time);
gui.setRemainingTime(Utils.humanDuration(date));
getProcessRender().setRemainingDuration((int) (date.getTime() / 1000));
}
catch (ParseException err) {
log.error("Client::updateRenderingStatus ParseException " + err);
}
}
}
}
else if (getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BY_TILE)) {
String search = " Tile ";
int index = line.lastIndexOf(search);
if (index != -1) {
String buf = line.substring(index + search.length());
String[] parts = buf.split("/");
if (parts.length == 2) {
try {
int current = Integer.parseInt(parts[0]);
int total = Integer.parseInt(parts[1]);
if (total != 0) {
gui.status(String.format("Rendering %s %%", (int) (100.0 * current / total)));
return;
}
}
catch (NumberFormatException e) {
System.out.println("Exception 94: " + e);
}
}
}
gui.status("Rendering");
}
}
private void updateRenderingMemoryPeak(String line) {
String[] elements = line.toLowerCase().split("(peak)");
for (String element : elements) {
if (element.isEmpty() == false && element.charAt(0) == ' ') {
int end = element.indexOf(')');
if (end > 0) {
try {
long mem = Utils.parseNumber(element.substring(1, end).trim()) / 1000; // internal use of ram is in kB
if (mem > getProcessRender().getMemoryUsed()) {
getProcessRender().setMemoryUsed(mem);
}
}
catch (IllegalStateException | NumberFormatException e) {
// failed to parseNumber
}
}
}
else {
if (element.isEmpty() == false && element.charAt(0) == ':') {
int end = element.indexOf('|');
if (end > 0) {
try {
long mem = Utils.parseNumber(element.substring(1, end).trim()) / 1000; // internal use of ram is in kB
if (mem > getProcessRender().getMemoryUsed()) {
getProcessRender().setMemoryUsed(mem);
}
}
catch (IllegalStateException | NumberFormatException e) {
// failed to parseNumber
}
}
}
}
}
}
private Type detectError(String line) {
if (line.contains("CUDA error: Out of memory")) {
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Mem:470.26M, Peak:470.26M | Scene, RenderLayer | Updating Device | Writing constant memory
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Mem:470.26M, Peak:470.26M | Scene, RenderLayer | Path Tracing Tile 0/135, Sample 0/200
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Mem:470.82M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 1/135, Sample 0/200
// CUDA error: Out of memory in cuLaunchKernel(cuPathTrace, xblocks , yblocks, 1, xthreads, ythreads, 1, 0, 0, args, 0)
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Remaining:09:26.57 | Mem:470.26M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 1/135, Sample 200/200
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Remaining:00:00.06 | Mem:470.50M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 134/135, Sample 0/200
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Remaining:00:00.03 | Mem:470.26M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 134/135, Sample 200/200
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Remaining:00:00.03 | Mem:470.50M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 135/135, Sample 0/200
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Mem:470.26M, Peak:470.82M | Scene, RenderLayer | Path Tracing Tile 135/135, Sample 200/200
// Error: CUDA error: Out of memory in cuLaunchKernel(cuPathTrace, xblocks , yblocks, 1, xthreads, ythreads, 1, 0, 0, args, 0)
// Fra:151 Mem:405.91M (0.00M, Peak 633.81M) | Mem:470.26M, Peak:470.82M | Scene, RenderLayer | Cancel | CUDA error: Out of memory in cuLaunchKernel(cuPathTrace, xblocks , yblocks, 1, xthreads, ythreads, 1, 0, 0, args, 0)
// Fra:151 Mem:405.89M (0.00M, Peak 633.81M) Sce: Scene Ve:0 Fa:0 La:0
// Saved: /tmp/xx/26885_0151.png Time: 00:04.67 (Saving: 00:00.22)
// Blender quit
return Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA error at cuCtxCreate: Out of memory")) {
// renderer output
// CUDA error at cuCtxCreate: Out of memory
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
// found bundled python: /tmp/aaaa/bbbb/2.78/python
// read blend: /tmp/aaaa/bbbb/compute-method.blend
// Fra:340 Mem:7.25M (0.00M, Peak 7.25M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Sun
// Fra:340 Mem:7.25M (0.00M, Peak 7.25M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Plane
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Cube
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Camera
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Initializing
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Loading render kernels (may take a few minutes the first time)
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Error | CUDA error at cuCtxCreate: Out of memory
// Error: CUDA error at cuCtxCreate: Out of memory
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Waiting for render to start
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Cancel | CUDA error at cuCtxCreate: Out of memory
// CUDA error: Invalid value in cuCtxDestroy(cuContext)
// Fra:340 Mem:7.25M (0.00M, Peak 7.26M) | Time:00:00.13 | Sce: Scene Ve:0 Fa:0 La:0
// Blender quit
// end of rendering
return Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA error: Launch exceeded timeout in")) {
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:01:08.44 | Mem:176.04M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 2/24, Sample 10/14
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:01:07.08 | Mem:175.48M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 2/24, Sample 14/14
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:01:07.11 | Mem:176.04M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 3/24, Sample 0/14
// CUDA error: Launch exceeded timeout in cuCtxSynchronize()
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
// CUDA error: Launch exceeded timeout in cuMemcpyDtoH((uchar*)mem.data_pointer + offset, (CUdeviceptr)(mem.device_pointer + offset), size)
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:03:04.30 | Mem:176.04M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 3/24, Sample 1/14
// CUDA error: Launch exceeded timeout in cuMemcpyDtoH((uchar*)mem.data_pointer + offset, (CUdeviceptr)(mem.device_pointer + offset), size)
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:02:01.87 | Mem:175.48M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 3/24, Sample 14/14
// CUDA error: Launch exceeded timeout in cuMemAlloc(&device_pointer, size)
// CUDA error: Launch exceeded timeout in cuMemAlloc(&device_pointer, size)
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:02:01.87 | Mem:176.04M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 4/24, Sample 0/14
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:01:27.05 | Mem:176.04M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 4/24, Sample 14/14
// CUDA error: Launch exceeded timeout in cuMemAlloc(&device_pointer, size)
// CUDA error: Launch exceeded timeout in cuMemAlloc(&device_pointer, size)
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Remaining:00:00.75 | Mem:185.66M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 24/24, Sample 0/14
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Mem:185.66M, Peak:199.23M | Scene, RenderLayer | Path Tracing Tile 24/24, Sample 14/14
// Error: CUDA error: Launch exceeded timeout in cuCtxSynchronize()
// Fra:420 Mem:102.41M (0.00M, Peak 215.18M) | Mem:185.66M, Peak:199.23M | Scene, RenderLayer | Cancel | CUDA error: Launch exceeded timeout in cuCtxSynchronize()
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// CUDA error: Launch exceeded timeout in cuMemFree(cuda_device_ptr(mem.device_pointer))
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 1-6
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 2-6
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 3-6
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 4-6
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 5-6
// Mem:109.00M (0.00M, Peak 215.18M) | Elapsed 00:00.00 | Tree Compositing Nodetree, Tile 6-6
// Fra:420 Mem:109.00M (0.00M, Peak 215.18M) Sce: Scene Ve:0 Fa:0 La:0
// Saved: /tmp/xx/1234_0420.bmp Time: 00:18.29 (Saving: 00:00.06)
// Blender quit
// end of rendering
return Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA error: Invalid value in cuTexRefSetAddress(")) {
// Fra:83 Mem:1201.77M (0.00M, Peak 1480.94M) | Time:00:59.30 | Mem:894.21M, Peak:894.21M | color 3, RenderLayer | Updating Mesh | Copying Strands to device
// Fra:83 Mem:1316.76M (0.00M, Peak 1480.94M) | Time:01:02.84 | Mem:1010.16M, Peak:1010.16M | color 3, RenderLayer | Cancel | CUDA error: Invalid value in cuTexRefSetAddress(NULL, texref, cuda_device_ptr(mem.device_pointer), size)
// Error: CUDA error: Invalid value in cuTexRefSetAddress(NULL, texref, cuda_device_ptr(mem.device_pointer), size)
// Fra:83 Mem:136.82M (0.00M, Peak 1480.94M) | Time:01:03.40 | Sce: color 3 Ve:0 Fa:0 La:0
// Blender quit
// CUDA error: Invalid value in cuTexRefSetAddress(NULL, texref, cuda_device_ptr(mem.device_pointer), size)
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
return Error.Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA error: Launch failed in cuCtxSynchronize()")) {
// Fra:60 Mem:278.24M (0.00M, Peak 644.01M) | Time:05:08.95 | Remaining:00:03.88 | Mem:210.79M, Peak:210.79M | Scene, W Laser | Path Tracing Tile 16/18, Sample 36/36
// Fra:60 Mem:278.24M (0.00M, Peak 644.01M) | Time:05:08.96 | Remaining:00:00.82 | Mem:211.04M, Peak:211.04M | Scene, W Laser | Path Tracing Tile 17/18, Sample 36/36
// Fra:60 Mem:278.24M (0.00M, Peak 644.01M) | Time:05:08.96 | Mem:211.11M, Peak:211.11M | Scene, W Laser | Path Tracing Tile 18/18
// Error: CUDA error: Launch failed in cuCtxSynchronize(), line 1372
// Fra:60 Mem:278.24M (0.00M, Peak 644.01M) | Time:05:08.96 | Mem:211.11M, Peak:211.11M | Scene, W Laser | Cancel | CUDA error: Launch failed in cuCtxSynchronize(), line 1372
// Cycles shader graph connect: can only connect closure to closure (Invert.Color to Mix Shader.Closure1).
// Cycles shader graph connect: can only connect closure to closure (Mix Shader.Closure to Bump.Normal).
// CUDA error: Launch failed in cuCtxSynchronize(), line 1372
// Refer to the Cycles GPU rendering documentation for possible solutions:
// https://docs.blender.org/manual/en/dev/render/cycles/gpu_rendering.html
// CUDA error: Launch failed in cuMemcpyDtoH((uchar*)mem.data_pointer + offset, (CUdeviceptr)(mem.device_pointer + offset), size), line 591
// CUDA error: Launch failed in cuMemcpyDtoH((uchar*)mem.data_pointer + offset, (CUdeviceptr)(mem.device_pointer + offset), size), line 591
// CUDA error: Launch failed in cuMemFree(cuda_device_ptr(mem.device_pointer)), line 615
return Error.Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA error: Illegal address in cuCtxSynchronize()")) {
// Fra:124 Mem:434.77M (0.00M, Peak 435.34M) | Time:25:50.81 | Remaining:01:10:05.16 | Mem:175.14M, Peak:265.96M | Scene, RenderLayer | Path Tracing Tile 34/135, Sample 800/800, Denoised 17 tiles
// Fra:124 Mem:432.71M (0.00M, Peak 435.34M) | Time:25:50.81 | Remaining:01:10:04.95 | Mem:264.84M, Peak:266.90M | Scene, RenderLayer | Path Tracing Tile 34/135, Sample 800/800, Denoised 18 tiles
// Fra:124 Mem:434.77M (0.00M, Peak 435.34M) | Time:25:50.82 | Remaining:01:07:20.83 | Mem:266.90M, Peak:266.90M | Scene, RenderLayer | Path Tracing Tile 35/135, Sample 800/800, Denoised 18 tiles
// Fra:124 Mem:432.71M (0.00M, Peak 435.34M) | Time:25:50.82 | Remaining:01:07:20.63 | Mem:356.60M, Peak:358.67M | Scene, RenderLayer | Path Tracing Tile 35/135, Sample 800/800, Denoised 19 tiles
// Fra:124 Mem:434.77M (0.00M, Peak 435.34M) | Time:25:50.82 | Remaining:01:04:45.63 | Mem:358.67M, Peak:358.67M | Scene, RenderLayer | Path Tracing Tile 36/135, Sample 800/800, Denoised 19 tiles
// Fra:124 Mem:432.71M (0.00M, Peak 435.34M) | Time:25:50.82 | Remaining:01:04:45.45 | Mem:448.37M, Peak:450.43M | Scene, RenderLayer | Path Tracing Tile 36/135, Sample 800/800, Denoised 20 tiles
// Fra:124 Mem:434.77M (0.00M, Peak 435.34M) | Time:25:50.83 | Remaining:01:02:18.83 | Mem:450.43M, Peak:450.43M | Scene, RenderLayer | Path Tracing Tile 37/135, Sample 800/800, Denoised 20 tiles
// CUDA error: Illegal address in cuCtxSynchronize(), line 1372
// Refer to the Cycles GPU rendering documentation for possible solutions:
return Error.Type.RENDERER_OUT_OF_VIDEO_MEMORY;
}
else if (line.contains("CUDA device supported only with compute capability")) {
// found bundled python: /tmp/xx/2.73/python
// read blend: /tmp/xx/compute-method.blend
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Sun
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Plane
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Cube
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Camera
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Initializing
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Loading render kernels (may take a few minutes the first time)
// CUDA device supported only with compute capability 2.0 or up, found 1.2.
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Error | CUDA device supported only with compute capability 2.0 or up, found 1.2.
// Error: CUDA device supported only with compute capability 2.0 or up, found 1.2.
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Waiting for render to start
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Cancel | CUDA device supported only with compute capability 2.0 or up, found 1.2.
// Fra:340 Mem:7.64M (0.00M, Peak 8.23M) Sce: Scene Ve:0 Fa:0 La:0
// Saved: /tmp/xx/0_0340.png Time: 00:00.12 (Saving: 00:00.03)
// Blender quit
return Type.GPU_NOT_SUPPORTED;
}
else if (line.contains("terminate called after throwing an instance of 'boost::filesystem::filesystem_error'")) {
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.24 | Mem:1.64M, Peak:1.64M | Scene, RenderLayer | Updating Mesh | Computing attributes
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.24 | Mem:1.64M, Peak:1.64M | Scene, RenderLayer | Updating Mesh | Copying Attributes to device
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.24 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Building
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.24 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Building BVH
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.24 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Looking in BVH cache
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.27 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Packing BVH triangles and strands
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.27 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Packing BVH nodes
// Fra:2103 Mem:29.54M (0.00M, Peak 29.54M) | Time:00:00.27 | Mem:1.97M, Peak:1.97M | Scene, RenderLayer | Updating Scene BVH | Writing BVH cache
// terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
// what(): boost::filesystem::create_directory: Permission denied: "/var/local/cache"
return Error.Type.NOOUTPUTFILE;
}
else if (line.contains("terminate called after throwing an instance of 'std::bad_alloc'")) {
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Mesh BVH Plane.083 171/2 | Building BVH
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Mesh BVH Mesh 172/2 | Building BVH
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Mesh BVH Mesh 172/2 | Packing BVH triangles and strands
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Mesh BVH Mesh 172/2 | Packing BVH nodes
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Scene BVH | Building
// Fra:80 Mem:1333.02M (0.00M, Peak 1651.23M) | Mem:780.37M, Peak:780.37M | Scene, RenderLayer | Updating Scene BVH | Building BVH
// terminate called after throwing an instance of 'std::bad_alloc'
// what(): std::bad_alloc
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
else if (line.contains("what(): std::bad_alloc")) {
// Fra:7 Mem:1247.01M (0.00M, Peak 1247.01M) | Time:00:28.84 | Mem:207.63M, Peak:207.63M | Scene, RenderLayer | Updating Scene BVH | Building BVH 93%, duplicates 0%terminate called recursively
// terminate called after throwing an instance of 'St9bad_alloc'
// what(): std::bad_alloc
// scandir: Cannot allocate memory
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
else if (line.contains("EXCEPTION_ACCESS_VIOLATION")) {
// Fra:638 Mem:342.17M (63.28M, Peak 735.33M) | Time:00:07.65 | Remaining:02:38.28 | Mem:246.91M, Peak:262.16M | scene_top_01_90, chip_top_view_scene_01 | Path Tracing Tile 57/2040, Denoised 0 tiles
// Fra:638 Mem:342.32M (63.28M, Peak 735.33M) | Time:00:07.70 | Remaining:02:38.20 | Mem:247.05M, Peak:262.16M | scene_top_01_90, chip_top_view_scene_01 | Path Tracing Tile 58/2040, Denoised 0 tiles
// Error: EXCEPTION_ACCESS_VIOLATION
return Error.Type.RENDERER_CRASHED;
}
else if (line.contains("Fatal Python error: Py_Initialize")) {
// Fatal Python error: Py_Initialize: unable to load the file system codec
// ImportError: No module named 'encodings'
// Current thread 0x0000388c (most recent call first):
return Error.Type.RENDERER_CRASHED_PYTHON_ERROR;
}
else if (line.contains("Calloc returns null")) {
// Fra:1 Mem:976.60M (0.00M, Peak 1000.54M) | Time:00:01.34 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Left
// Calloc returns null: len=7186416 in CDMLoopUV, total 2145859048
// Calloc returns null: len=7186416 in CDMLoopUV, total 2145859048
// Malloc returns null: len=3190672 in CDMTexPoly, total 2149293176
// Writing: /home/user/.sheepit/LEFT packed.crash.txt
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
else if (line.contains("Malloc returns null")) {
// Fra:1 Mem:976.60M (0.00M, Peak 1000.54M) | Time:00:01.34 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Left
// Calloc returns null: len=7186416 in CDMLoopUV, total 2145859048
// Calloc returns null: len=7186416 in CDMLoopUV, total 2145859048
// Malloc returns null: len=3190672 in CDMTexPoly, total 2149293176
// Writing: /home/user/.sheepit/LEFT packed.crash.txt
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
else if (line.contains("CUDA kernel compilation failed")) {
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.02 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Sun.001
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.02 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Synchronizing object | Sun.002
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.02 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Initializing
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.02 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Loading render kernels (may take a few minutes the first time)
// nvcc fatal : Value 'sm_61' is not defined for option 'gpu-architecture'
// CUDA kernel compilation failed, see console for details.
// Refer to the Cycles GPU rendering documentation for possible solutions:
// http://www.blender.org/manual/render/cycles/gpu_rendering.html
// Compiling CUDA kernel ...
// "nvcc" -arch=sm_61 -m64 --cubin "/tmp/cache/c36db40aa5e59f5ea4ff139180353dbc/2.77/scripts/addons/cycles/kernel/kernels/cuda/kernel.cu" -o "/tmp/cache/cycles_kernel_sm61_079195D400571E023CC499D037AB6EE5.cubin" --ptxas-options="-v" --use_fast_math -I"/tmp/cache/c36db40aa5e59f5ea4ff139180353dbc/2.77/scripts/addons/cycles/kernel" -DNVCC -D__KERNEL_CUDA_VERSION__=75
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.08 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Error | CUDA kernel compilation failed, see console for details.
// Error: CUDA kernel compilation failed, see console for details.
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.08 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Waiting for render to start
// Fra:1 Mem:200.70M (0.00M, Peak 378.15M) | Time:00:01.08 | Mem:0.00M, Peak:0.00M | Scene, RenderLayer | Cancel | CUDA kernel compilation failed, see console for details.
// Fra:1 Mem:147.74M (0.00M, Peak 378.15M) | Time:00:01.12 | Sce: Scene Ve:0 Fa:0 La:0
// Saved: '/tmp/cache/8_0001.png'
return Error.Type.GPU_NOT_SUPPORTED;
}
return Type.OK;
}
public int getTileSize() {
if (configuration.getTileSize() == -1) { // not set
int size = 32; // CPU
GPUDevice gpu = this.configuration.getGPUDevice();
if (isUseGPU() && gpu != null) {
return gpu.getRecommandedTileSize();
}
return size;
}
else {
return configuration.getTileSize();
}
}
public static class renderStartedObservable extends Observable {
@Getter
private boolean isStarted;
public renderStartedObservable(Observer observer) {
super();
addObserver(observer);
}
public void doNotifyIsStarted() {
setChanged();
notifyObservers();
isStarted = true;
}
}
}

View File

@@ -1,106 +0,0 @@
/*
* Copyright (C) 2011-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class Log {
private static Log instance = null;
private Map<Integer, ArrayList<String>> checkpoints = new HashMap<Integer, ArrayList<String>>();
private int lastCheckPoint;
private DateFormat dateFormat;
private boolean printStdOut;
private Log(boolean print_) {
this.printStdOut = print_;
this.lastCheckPoint = 0;
this.checkpoints.put(this.lastCheckPoint, new ArrayList<String>());
this.dateFormat = new SimpleDateFormat("dd-MM HH:mm:ss");
}
public void debug(String msg_) {
this.append("debug", msg_);
}
public void info(String msg_) {
this.append("info", msg_);
}
public void error(String msg_) {
this.append("error", msg_);
}
private void append(String level_, String msg_) {
if (msg_.equals("") == false) {
String line = this.dateFormat.format(new java.util.Date()) + " (" + level_ + ") " + msg_;
if (this.checkpoints.containsKey(this.lastCheckPoint)) {
this.checkpoints.get(this.lastCheckPoint).add(line);
}
if (this.printStdOut == true) {
System.out.println(line);
}
}
}
public int newCheckPoint() {
int time = (int) (new Date().getTime());
this.checkpoints.put(time, new ArrayList<String>());
this.lastCheckPoint = time;
return this.lastCheckPoint;
}
public ArrayList<String> getForCheckPoint(int point_) {
return this.checkpoints.get(point_);
}
public void removeCheckPoint(int point_) {
try {
this.checkpoints.remove(point_);
}
catch (UnsupportedOperationException e) {
}
}
public static synchronized Log getInstance(Configuration config) {
if (instance == null) {
boolean print = false;
if (config != null) {
print = config.isPrintLog();
}
instance = new Log(print);
}
return instance;
}
public static synchronized void printCheckPoint(int point_) {
Log log = Log.getInstance(null);
ArrayList<String> logs = log.getForCheckPoint(point_);
for (String alog : logs) {
System.out.println(alog);
}
}
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sheepit.client;
import java.util.Objects;
/**
* Container to ease passing around a pair of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class Pair<F, S> {
public final F first;
public final S second;
/**
* Constructor for a Pair.
*
* @param first the first object in the Pair
* @param second the second object in the pair
*/
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
/**
* Checks the two objects for equality by delegating to their respective
* {@link Object#equals(Object)} methods.
*
* @param o the {@link Pair} to which this one is to be checked for equality
* @return true if the underlying objects of the Pair are both considered
* equal
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
return Objects.equals(p.first, first) && Objects.equals(p.second, second);
}
/**
* Compute a hash code using the hash codes of the underlying objects
*
* @return a hashcode of the Pair
*/
@Override
public int hashCode() {
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
}
/**
* Convenience method for creating an appropriately typed pair.
*
* @param a the first object in the Pair
* @param b the second object in the pair
* @return a Pair that is templatized with the types of a and b
*/
public static <A, B> Pair<A, B> create(A a, B b) {
return new Pair<A, B>(a, b);
}
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import lombok.Data;
import java.util.Date;
@Data
public class RenderProcess {
private long startTime;
private long endTime;
private int remainingDuration; // in seconds
private long memoryUsed; // in kB
private int coresUsed;
private Process process;
public RenderProcess() {
process = null;
startTime = -1;
endTime = -1;
memoryUsed = 0;
coresUsed = 0;
remainingDuration = 0;
}
/**
*
* @return duration in seconds
*/
public int getDuration() {
if (startTime != -1 && endTime != -1) {
return (int) ((endTime - startTime) / 1000);
}
else if (startTime != -1) {
return (int) ((new Date().getTime() - startTime) / 1000);
}
return 0;
}
public void finish() {
endTime = new Date().getTime();
process = null;
}
public void start() {
startTime = new Date().getTime();
}
public int exitValue() {
int value = 0;
if (process == null) {
return -1;
}
try {
value = process.exitValue();
}
catch (IllegalThreadStateException e) {
// the process is not finished yet
value = 0;
}
catch (Exception e) {
// actually is for java.io.IOException: GetExitCodeProcess error=6, The handle is invalid
// it was not declared throwable
// the process is not finished yet
value = 0;
}
return value;
}
}

View File

@@ -1,955 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.UnknownHostException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.Error.ServerCode;
import com.sheepit.client.exception.FermeException;
import com.sheepit.client.exception.FermeExceptionBadResponseFromServer;
import com.sheepit.client.exception.FermeExceptionNoRendererAvailable;
import com.sheepit.client.exception.FermeExceptionNoRightToRender;
import com.sheepit.client.exception.FermeExceptionNoSession;
import com.sheepit.client.exception.FermeExceptionNoSpaceLeftOnDevice;
import com.sheepit.client.exception.FermeExceptionServerInMaintenance;
import com.sheepit.client.exception.FermeExceptionServerOverloaded;
import com.sheepit.client.exception.FermeExceptionSessionDisabled;
import com.sheepit.client.exception.FermeServerDown;
import com.sheepit.client.os.OS;
public class Server extends Thread implements HostnameVerifier, X509TrustManager {
private String base_url;
private Configuration user_config;
private Client client;
private HashMap<String, String> pages;
private Log log;
private long lastRequestTime;
private int keepmealive_duration; // time in ms
public Server(String url_, Configuration user_config_, Client client_) {
super();
this.base_url = url_;
this.user_config = user_config_;
this.client = client_;
this.pages = new HashMap<String, String>();
this.log = Log.getInstance(this.user_config);
this.lastRequestTime = 0;
this.keepmealive_duration = 15 * 60 * 1000; // default 15min
CookieManager cookies = new CookieManager();
CookieHandler.setDefault(cookies);
}
public void run() {
this.stayAlive();
}
public void stayAlive() {
while (true) {
long current_time = new Date().getTime();
if ((current_time - this.lastRequestTime) > this.keepmealive_duration) {
try {
String args = "";
if (this.client != null && this.client.getRenderingJob() != null) {
args = "?frame=" + this.client.getRenderingJob().getFrameNumber() + "&job=" + this.client.getRenderingJob().getId();
if (this.client.getRenderingJob().getExtras() != null && this.client.getRenderingJob().getExtras().isEmpty() == false) {
args += "&extras=" + this.client.getRenderingJob().getExtras();
}
if (this.client.getRenderingJob().getProcessRender() != null) {
args += "&rendertime=" + this.client.getRenderingJob().getProcessRender().getDuration();
args += "&remainingtime=" + this.client.getRenderingJob().getProcessRender().getRemainingDuration();
}
}
HttpURLConnection connection = this.HTTPRequest(this.getPage("keepmealive") + args);
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK && connection.getContentType().startsWith("text/xml")) {
DataInputStream in = new DataInputStream(connection.getInputStream());
try {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
ServerCode ret = Utils.statusIsOK(document, "keepmealive");
if (ret == ServerCode.KEEPMEALIVE_STOP_RENDERING) {
this.log.debug("Server::stayAlive server asked to kill local render process");
// kill the current process, it will generate an error but it's okay
if (this.client != null && this.client.getRenderingJob() != null && this.client.getRenderingJob().getProcessRender().getProcess() != null) {
this.client.getRenderingJob().setServerBlockJob(true);
this.client.getRenderingJob().setAskForRendererKill(true);
OS.getOS().kill(this.client.getRenderingJob().getProcessRender().getProcess());
}
}
}
catch (SAXException e) {
}
catch (ParserConfigurationException e) {
}
}
}
catch (NoRouteToHostException e) {
this.log.debug("Server::stayAlive can not connect to server");
}
catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::stayAlive IOException " + e + " stacktrace: " + sw.toString());
}
}
try {
Thread.sleep(60 * 1000); // 1min
}
catch (InterruptedException e) {
return;
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::stayAlive Exception " + e + " stacktrace: " + sw.toString());
}
}
}
public String toString() {
return String.format("Server (base_url '%s', user_config %s, pages %s", this.base_url, this.user_config, this.pages);
}
public Error.Type getConfiguration() {
OS os = OS.getOS();
HttpURLConnection connection = null;
try {
String url_remote = this.base_url + "/server/config.php";
String parameters = String.format("login=%s&password=%s&cpu_family=%s&cpu_model=%s&cpu_model_name=%s&cpu_cores=%s&os=%s&ram=%s&bits=%s&version=%s&hostname=%s&ui=%s&extras=%s",
URLEncoder.encode(this.user_config.getLogin(), "UTF-8"),
URLEncoder.encode(this.user_config.getPassword(), "UTF-8"),
URLEncoder.encode(os.getCPU().family(), "UTF-8"),
URLEncoder.encode(os.getCPU().model(), "UTF-8"),
URLEncoder.encode(os.getCPU().name(), "UTF-8"),
((this.user_config.getNbCores() == -1) ? os.getCPU().cores() : this.user_config.getNbCores()),
URLEncoder.encode(os.name(), "UTF-8"),
os.getMemory(),
URLEncoder.encode(os.getCPU().arch(), "UTF-8"),
this.user_config.getJarVersion(),
URLEncoder.encode(this.user_config.getHostname(), "UTF-8"),
this.client.getGui().getClass().getSimpleName(),
this.user_config.getExtras());
this.log.debug("Server::getConfiguration url " + url_remote);
connection = this.HTTPRequest(url_remote, parameters);
int r = connection.getResponseCode();
String contentType = connection.getContentType();
if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/xml")) {
DataInputStream in = new DataInputStream(connection.getInputStream());
Document document = null;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
}
catch (SAXException e) {
this.log.error("getConfiguration error: failed to parse XML SAXException " + e);
return Error.Type.WRONG_CONFIGURATION;
}
catch (IOException e) {
this.log.error("getConfiguration error: failed to parse XML IOException " + e);
return Error.Type.WRONG_CONFIGURATION;
}
catch (ParserConfigurationException e) {
this.log.error("getConfiguration error: failed to parse XML ParserConfigurationException " + e);
return Error.Type.WRONG_CONFIGURATION;
}
ServerCode ret = Utils.statusIsOK(document, "config");
if (ret != ServerCode.OK) {
return Error.ServerCodeToType(ret);
}
Element config_node = null;
NodeList ns = null;
ns = document.getElementsByTagName("config");
if (ns.getLength() == 0) {
this.log.error("getConfiguration error: failed to parse XML, no node 'config'");
return Error.Type.WRONG_CONFIGURATION;
}
config_node = (Element) ns.item(0);
ns = config_node.getElementsByTagName("request");
if (ns.getLength() == 0) {
this.log.error("getConfiguration error: failed to parse XML, node 'config' has no child node 'request'");
return Error.Type.WRONG_CONFIGURATION;
}
for (int i = 0; i < ns.getLength(); i++) {
Element element = (Element) ns.item(i);
if (element.hasAttribute("type") && element.hasAttribute("path")) {
this.pages.put(element.getAttribute("type"), element.getAttribute("path"));
if (element.getAttribute("type").equals("keepmealive") && element.hasAttribute("max-period")) {
this.keepmealive_duration = (Integer.parseInt(element.getAttribute("max-period")) - 120) * 1000; // put 2min of safety net
}
}
}
}
else if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/html")) {
return Error.Type.ERROR_BAD_RESPONSE;
}
else {
this.log.error("Server::getConfiguration: Invalid response " + contentType + " " + r);
return Error.Type.WRONG_CONFIGURATION;
}
}
catch (ConnectException e) {
this.log.error("Server::getConfiguration error ConnectException " + e);
return Error.Type.NETWORK_ISSUE;
}
catch (UnknownHostException e) {
this.log.error("Server::getConfiguration: exception UnknownHostException " + e);
return Error.Type.NETWORK_ISSUE;
}
catch (UnsupportedEncodingException e) {
this.log.error("Server::getConfiguration: exception UnsupportedEncodingException " + e);
return Error.Type.UNKNOWN;
}
catch (IOException e) {
this.log.error("Server::getConfiguration: exception IOException " + e);
return Error.Type.UNKNOWN;
}
finally {
if (connection != null) {
connection.disconnect();
}
}
return Error.Type.OK;
}
public Job requestJob() throws FermeException {
this.log.debug("Server::requestJob");
String url_contents = "";
HttpURLConnection connection = null;
try {
OS os = OS.getOS();
long maxMemory = this.user_config.getMaxMemory();
long freeMemory = os.getFreeMemory();
if (maxMemory < 0) {
maxMemory = freeMemory;
}
else if (freeMemory > 0 && maxMemory > 0) {
maxMemory = Math.min(maxMemory, freeMemory);
}
String url = String.format("%s?computemethod=%s&cpu_cores=%s&ram_max=%s&rendertime_max=%s", this.getPage("request-job"), this.user_config.computeMethodToInt(), ((this.user_config.getNbCores() == -1) ? os.getCPU().cores() : this.user_config.getNbCores()), maxMemory, this.user_config.getMaxRenderTime());
if (this.user_config.getComputeMethod() != ComputeType.CPU && this.user_config.getGPUDevice() != null) {
String gpu_model = "";
try {
gpu_model = URLEncoder.encode(this.user_config.getGPUDevice().getModel(), "UTF-8");
}
catch (UnsupportedEncodingException e) {
}
url += "&gpu_model=" + gpu_model + "&gpu_ram=" + this.user_config.getGPUDevice().getMemory() + "&gpu_type=" + this.user_config.getGPUDevice().getType();
}
connection = this.HTTPRequest(url, this.generateXMLForMD5cache());
int r = connection.getResponseCode();
String contentType = connection.getContentType();
if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/xml")) {
DataInputStream in = new DataInputStream(connection.getInputStream());
Document document = null;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
}
catch (SAXException e) {
throw new FermeException("error requestJob: parseXML failed, SAXException " + e);
}
catch (IOException e) {
throw new FermeException("error requestJob: parseXML failed IOException " + e);
}
catch (ParserConfigurationException e) {
throw new FermeException("error requestJob: parseXML failed ParserConfigurationException " + e);
}
ServerCode ret = Utils.statusIsOK(document, "jobrequest");
if (ret != ServerCode.OK) {
if (ret == ServerCode.JOB_REQUEST_NOJOB) {
handleFileMD5DeleteDocument(document, "jobrequest");
return null;
}
else if (ret == ServerCode.JOB_REQUEST_ERROR_NO_RENDERING_RIGHT) {
throw new FermeExceptionNoRightToRender();
}
else if (ret == ServerCode.JOB_REQUEST_ERROR_DEAD_SESSION) {
throw new FermeExceptionNoSession();
}
else if (ret == ServerCode.JOB_REQUEST_ERROR_RENDERER_NOT_AVAILABLE) {
throw new FermeExceptionNoRendererAvailable();
}
else if (ret == ServerCode.JOB_REQUEST_ERROR_SESSION_DISABLED) {
throw new FermeExceptionSessionDisabled();
}
else if (ret == ServerCode.JOB_REQUEST_SERVER_IN_MAINTENANCE) {
throw new FermeExceptionServerInMaintenance();
}
else if (ret == ServerCode.JOB_REQUEST_SERVER_OVERLOADED) {
throw new FermeExceptionServerOverloaded();
}
this.log.error("Server::requestJob: Utils.statusIsOK(document, 'jobrequest') -> ret " + ret);
throw new FermeException("error requestJob: status is not ok (it's " + ret + ")");
}
handleFileMD5DeleteDocument(document, "jobrequest");
Element a_node = null;
NodeList ns = null;
ns = document.getElementsByTagName("stats");
if (ns.getLength() == 0) {
throw new FermeException("error requestJob: parseXML failed, no 'frame' node");
}
a_node = (Element) ns.item(0);
int remaining_frames = 0;
int credits_earned = 0;
int credits_earned_session = 0;
int waiting_project = 0;
int renderable_project = 0;
int connected_machine = 0;
if (a_node.hasAttribute("frame_remaining") && a_node.hasAttribute("credits_total") && a_node.hasAttribute("credits_session") && a_node.hasAttribute("waiting_project") && a_node.hasAttribute("connected_machine")) {
remaining_frames = Integer.parseInt(a_node.getAttribute("frame_remaining"));
credits_earned = Integer.parseInt(a_node.getAttribute("credits_total"));
credits_earned_session = Integer.parseInt(a_node.getAttribute("credits_session"));
waiting_project = Integer.parseInt(a_node.getAttribute("waiting_project"));
connected_machine = Integer.parseInt(a_node.getAttribute("connected_machine"));
}
if (a_node.hasAttribute("renderable_project")) {
renderable_project = Integer.parseInt(a_node.getAttribute("renderable_project"));
}
ns = document.getElementsByTagName("job");
if (ns.getLength() == 0) {
throw new FermeException("error requestJob: parseXML failed, no 'job' node");
}
Element job_node = (Element) ns.item(0);
ns = job_node.getElementsByTagName("renderer");
if (ns.getLength() == 0) {
throw new FermeException("error requestJob: parseXML failed, node 'job' have no sub-node 'renderer'");
}
Element renderer_node = (Element) ns.item(0);
String script = "import bpy\n";
// blender 2.7x
script += "try:\n";
script += "\tbpy.context.user_preferences.filepaths.temporary_directory = \"" + this.user_config.getWorkingDirectory().getAbsolutePath().replace("\\", "\\\\") + "\"\n";
script += "except AttributeError:\n";
script += "\tpass\n";
// blender 2.80
script += "try:\n";
script += "\tbpy.context.preferences.filepaths.temporary_directory = \"" + this.user_config.getWorkingDirectory().getAbsolutePath().replace("\\", "\\\\") + "\"\n";
script += "except AttributeError:\n";
script += "\tpass\n";
try {
ns = job_node.getElementsByTagName("script");
if (ns.getLength() != 0) {
Element a_node3 = (Element) ns.item(0);
script += a_node3.getTextContent();
}
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::requestJob Exception " + e + " stacktrace: " + sw.toString());
}
String[] job_node_require_attribute = { "id", "archive_md5", "path", "use_gpu", "frame", "name", "extras", "password" };
String[] renderer_node_require_attribute = { "md5", "commandline" };
for (String e : job_node_require_attribute) {
if (job_node.hasAttribute(e) == false) {
throw new FermeException("error requestJob: parseXML failed, job_node have to attribute '" + e + "'");
}
}
for (String e : renderer_node_require_attribute) {
if (renderer_node.hasAttribute(e) == false) {
throw new FermeException("error requestJob: parseXML failed, renderer_node have to attribute '" + e + "'");
}
}
boolean use_gpu = (job_node.getAttribute("use_gpu").compareTo("1") == 0);
boolean synchronous_upload = true;
if (job_node.hasAttribute("synchronous_upload")) {
synchronous_upload = (job_node.getAttribute("synchronous_upload").compareTo("1") == 0);
}
String frame_extras = "";
if (job_node.hasAttribute("extras")) {
frame_extras = job_node.getAttribute("extras");
}
String update_method = null;
if (renderer_node.hasAttribute("update_method")) {
update_method = renderer_node.getAttribute("update_method");
}
Job a_job = new Job(
this.user_config,
this.client.getGui(),
this.client.getLog(),
job_node.getAttribute("id"),
job_node.getAttribute("frame"),
job_node.getAttribute("path").replace("/", File.separator),
use_gpu,
renderer_node.getAttribute("commandline"),
script,
job_node.getAttribute("archive_md5"),
renderer_node.getAttribute("md5"),
job_node.getAttribute("name"),
job_node.getAttribute("password"),
frame_extras,
synchronous_upload,
update_method
);
this.client.getGui().displayStats(new Stats(remaining_frames, credits_earned, credits_earned_session, renderable_project, waiting_project, connected_machine));
return a_job;
}
else {
System.out.println("Server::requestJob url " + url_contents + " r " + r + " contentType " + contentType);
if (r == HttpURLConnection.HTTP_UNAVAILABLE || r == HttpURLConnection. HTTP_CLIENT_TIMEOUT) {
// most likely varnish is up but apache down
throw new FermeServerDown();
}
else if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/html")) {
throw new FermeExceptionBadResponseFromServer();
}
InputStream in = connection.getInputStream();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
while ((line = reader.readLine()) != null) {
System.out.print(line);
}
System.out.println("");
}
}
catch (FermeException e) {
throw e;
}
catch (NoRouteToHostException e) {
throw new FermeServerDown();
}
catch (UnknownHostException e) {
throw new FermeServerDown();
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
throw new FermeException("error requestJob: unknown exception " + e + " stacktrace: " + sw.toString());
}
finally {
if (connection != null) {
connection.disconnect();
}
}
throw new FermeException("error requestJob, end of function");
}
public HttpURLConnection HTTPRequest(String url_) throws IOException {
return this.HTTPRequest(url_, null);
}
public HttpURLConnection HTTPRequest(String url_, String data_) throws IOException {
this.log.debug("Server::HTTPRequest url(" + url_ + ")");
HttpURLConnection connection = null;
URL url = new URL(url_);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("GET");
if (url_.startsWith("https://")) {
try {
SSLContext sc;
sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { this }, null);
SSLSocketFactory factory = sc.getSocketFactory();
((HttpsURLConnection) connection).setSSLSocketFactory(factory);
((HttpsURLConnection) connection).setHostnameVerifier(this);
}
catch (NoSuchAlgorithmException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPRequest NoSuchAlgorithmException " + e + " stacktrace: " + sw.toString());
return null;
}
catch (KeyManagementException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPRequest KeyManagementException " + e + " stacktrace: " + sw.toString());
return null;
}
}
if (data_ != null) {
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(data_);
out.flush();
out.close();
}
// actually use the connection to, in case of timeout, generate an exception
connection.getResponseCode();
this.lastRequestTime = new Date().getTime();
return connection;
}
public int HTTPGetFile(String url_, String destination_, Gui gui_, String status_) throws FermeExceptionNoSpaceLeftOnDevice {
// the destination_ parent directory must exist
try {
HttpURLConnection httpCon = this.HTTPRequest(url_);
InputStream inStrm = httpCon.getInputStream();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) {
this.log.error("Server::HTTPGetFile(" + url_ + ", ...) HTTP code is not " + HttpURLConnection.HTTP_OK + " it's " + httpCon.getResponseCode());
return -1;
}
int size = httpCon.getContentLength();
long start = new Date().getTime();
FileOutputStream fos = new FileOutputStream(destination_);
byte[] ch = new byte[512 * 1024];
int nb;
long written = 0;
long last_gui_update = 0; // size in byte
while ((nb = inStrm.read(ch)) != -1) {
fos.write(ch, 0, nb);
written += nb;
if ((written - last_gui_update) > 1000000) { // only update the gui every 1MB
gui_.status(String.format(status_, (int) (100.0 * written / size)));
last_gui_update = written;
}
}
fos.close();
inStrm.close();
long end = new Date().getTime();
this.log.debug(String.format("File downloaded at %.1f kB/s, written %d B", ((float) (size / 1000)) / ((float) (end - start) / 1000), written));
this.lastRequestTime = new Date().getTime();
return 0;
}
catch (Exception e) {
if (Utils.noFreeSpaceOnDisk(new File(destination_).getParent())) {
throw new FermeExceptionNoSpaceLeftOnDevice();
}
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
this.log.error("Server::HTTPGetFile Exception " + e + " stacktrace " + sw.toString());
}
this.log.debug("Server::HTTPGetFile(" + url_ + ", ...) will failed (end of function)");
return -2;
}
public ServerCode HTTPSendFile(String surl, String file1) {
this.log.debug("Server::HTTPSendFile(" + surl + "," + file1 + ")");
HttpURLConnection conn = null;
DataOutputStream dos = null;
BufferedReader inStream = null;
String exsistingFileName = file1;
File fFile2Snd = new File(exsistingFileName);
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "***232404jkg4220957934FW**";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
String urlString = surl;
try {
FileInputStream fileInputStream = new FileInputStream(new File(exsistingFileName));
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
if (urlString.startsWith("https://")) {
try {
SSLContext sc;
sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { this }, null);
SSLSocketFactory factory = sc.getSocketFactory();
((HttpsURLConnection) conn).setSSLSocketFactory(factory);
((HttpsURLConnection) conn).setHostnameVerifier(this);
}
catch (NoSuchAlgorithmException e) {
this.log.error("Server::HTTPSendFile, exception NoSuchAlgorithmException " + e);
try {
fileInputStream.close();
}
catch (Exception e1) {
}
return ServerCode.UNKNOWN;
}
catch (KeyManagementException e) {
this.log.error("Server::HTTPSendFile, exception KeyManagementException " + e);
try {
fileInputStream.close();
}
catch (Exception e1) {
}
return ServerCode.UNKNOWN;
}
}
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";" + " filename=\"" + fFile2Snd.getName() + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
fileInputStream.close();
dos.flush();
dos.close();
}
catch (MalformedURLException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.error("Server::HTTPSendFile, MalformedURLException " + e + " stacktrace " + sw.toString());
return ServerCode.UNKNOWN;
}
catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.error("Server::HTTPSendFile, IOException " + e + " stacktrace " + sw.toString());
return ServerCode.UNKNOWN;
}
catch (OutOfMemoryError e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.error("Server::HTTPSendFile, OutOfMemoryError " + e + " stacktrace " + sw.toString());
return ServerCode.JOB_VALIDATION_ERROR_UPLOAD_FAILED;
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.error("Server::HTTPSendFile, Exception " + e + " stacktrace " + sw.toString());
return ServerCode.UNKNOWN;
}
int r;
try {
r = conn.getResponseCode();
}
catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPSendFile IOException " + e + " stacktrace: " + sw.toString());
return ServerCode.UNKNOWN;
}
String contentType = conn.getContentType();
if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/xml")) {
DataInputStream in;
try {
in = new DataInputStream(conn.getInputStream());
}
catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPSendFile IOException " + e + " stacktrace: " + sw.toString());
return ServerCode.UNKNOWN;
}
Document document = null;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
}
catch (SAXException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPSendFile SAXException " + e + " stacktrace: " + sw.toString());
return ServerCode.UNKNOWN;
}
catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPSendFile IOException " + e + " stacktrace: " + sw.toString());
return ServerCode.UNKNOWN;
}
catch (ParserConfigurationException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::HTTPSendFile ParserConfigurationException " + e + " stacktrace: " + sw.toString());
return ServerCode.UNKNOWN;
}
this.lastRequestTime = new Date().getTime();
ServerCode ret1 = Utils.statusIsOK(document, "jobvalidate");
if (ret1 != ServerCode.OK) {
this.log.error("Server::HTTPSendFile wrong status (is " + ret1 + ")");
return ret1;
}
return ServerCode.OK;
}
else if (r == HttpURLConnection.HTTP_OK && contentType.startsWith("text/html")) {
return ServerCode.ERROR_BAD_RESPONSE;
}
else {
try {
inStream = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String str;
while ((str = inStream.readLine()) != null) {
System.out.println(str);
System.out.println("");
}
inStream.close();
}
catch (IOException ioex) {
}
}
return ServerCode.UNKNOWN;
}
public byte[] getLastRender() {
try {
HttpURLConnection httpCon = this.HTTPRequest(this.getPage("last-render-frame"));
InputStream inStrm = httpCon.getInputStream();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) {
this.log.debug("Server::getLastRender code not ok " + httpCon.getResponseCode());
return null;
}
int size = httpCon.getContentLength();
if (size <= 0) {
this.log.debug("Server::getLastRender size is negative (size: " + size + ")");
return null;
}
byte[] ret = new byte[size];
byte[] ch = new byte[512 * 1024];
int n = 0;
int i = 0;
while ((n = inStrm.read(ch)) != -1) {
System.arraycopy(ch, 0, ret, i, n);
i += n;
}
inStrm.close();
return ret;
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.log.debug("Server::getLastRender Exception " + e + " stacktrace: " + sw.toString());
}
return null;
}
private String generateXMLForMD5cache() {
String xml_str = null;
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document_cache = docBuilder.newDocument();
Element rootElement = document_cache.createElement("cache");
document_cache.appendChild(rootElement);
List<File> local_files = this.user_config.getLocalCacheFiles();
for (File local_file : local_files) {
Element node_file = document_cache.createElement("file");
rootElement.appendChild(node_file);
try {
String extension = local_file.getName().substring(local_file.getName().lastIndexOf('.')).toLowerCase();
String name = local_file.getName().substring(0, local_file.getName().length() - 1 * extension.length());
if (extension.equals(".zip")) {
node_file.setAttribute("md5", name);
}
}
catch (StringIndexOutOfBoundsException e) { // because the file does not have an . his path
}
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(document_cache), new StreamResult(writer));
xml_str = writer.getBuffer().toString();
}
catch (TransformerConfigurationException e) {
this.log.debug("Server::generateXMLForMD5cache " + e);
}
catch (TransformerException e) {
this.log.debug("Server::generateXMLForMD5cache " + e);
}
catch (ParserConfigurationException e) {
this.log.debug("Server::generateXMLForMD5cache " + e);
}
return xml_str;
}
private void handleFileMD5DeleteDocument(Document document, String root_nodename) {
NodeList ns = document.getElementsByTagName(root_nodename);
if (ns.getLength() > 0) {
Element root_node = (Element) ns.item(0);
ns = root_node.getElementsByTagName("file");
if (ns.getLength() > 0) {
for (int i = 0; i < ns.getLength(); ++i) {
Element file_node = (Element) ns.item(i);
if (file_node.hasAttribute("md5") && file_node.hasAttribute("action") && file_node.getAttribute("action").equals("delete")) {
String path = this.user_config.getWorkingDirectory().getAbsolutePath() + File.separatorChar + file_node.getAttribute("md5");
this.log.debug("Server::handleFileMD5DeleteDocument delete old file " + path);
File file_to_delete = new File(path + ".zip");
file_to_delete.delete();
Utils.delete(new File(path));
}
}
}
}
}
public String getPage(String key) {
if (this.pages.containsKey(key)) {
return this.base_url + this.pages.get(key);
}
return "";
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true; // trust every ssl certificate
}
}

View File

@@ -1,379 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import com.sheepit.client.Configuration;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.hardware.gpu.GPU;
import com.sheepit.client.hardware.gpu.GPUDevice;
public class SettingsLoader {
private String path;
private String login;
private String password;
private String proxy;
private String hostname;
private String computeMethod;
private String gpu;
private String cores;
private String ram;
private String renderTime;
private String cacheDir;
private String autoSignIn;
private String ui;
private String tileSize;
private int priority;
public SettingsLoader(String path_) {
if (path_ == null) {
path = getDefaultFilePath();
}
else {
path = path_;
}
}
public SettingsLoader(String path_, String login_, String password_, String proxy_, String hostname_, ComputeType computeMethod_, GPUDevice gpu_, int cores_, long maxRam_, int maxRenderTime_, String cacheDir_, boolean autoSignIn_, String ui_, String tileSize_, int priority_) {
if (path_ == null) {
path = getDefaultFilePath();
}
else {
path = path_;
}
login = login_;
password = password_;
proxy = proxy_;
hostname = hostname_;
cacheDir = cacheDir_;
autoSignIn = String.valueOf(autoSignIn_);
ui = ui_;
tileSize = tileSize_;
priority = priority_;
if (cores_ > 0) {
cores = String.valueOf(cores_);
}
if (maxRam_ > 0) {
ram = String.valueOf(maxRam_) + "k";
}
if (maxRenderTime_ > 0) {
renderTime = String.valueOf(maxRenderTime_);
}
if (computeMethod_ != null) {
try {
computeMethod = computeMethod_.name();
}
catch (IllegalArgumentException e) {
}
}
if (gpu_ != null) {
gpu = gpu_.getId();
}
}
public static String getDefaultFilePath() {
return System.getProperty("user.home") + File.separator + ".sheepit.conf";
}
public String getFilePath() {
return path;
}
public void saveFile() {
Properties prop = new Properties();
OutputStream output = null;
try {
output = new FileOutputStream(path);
prop.setProperty("priority", new Integer(priority).toString());
if (cacheDir != null) {
prop.setProperty("cache-dir", cacheDir);
}
if (computeMethod != null) {
prop.setProperty("compute-method", computeMethod);
}
if (gpu != null) {
prop.setProperty("compute-gpu", gpu);
}
if (cores != null) {
prop.setProperty("cores", cores);
}
if (ram != null) {
prop.setProperty("ram", ram);
}
if (renderTime != null) {
prop.setProperty("rendertime", renderTime);
}
if (login != null) {
prop.setProperty("login", login);
}
if (password != null) {
prop.setProperty("password", password);
}
if (proxy != null) {
prop.setProperty("proxy", proxy);
}
if (hostname != null) {
prop.setProperty("hostname", hostname);
}
if (autoSignIn != null) {
prop.setProperty("auto-signin", autoSignIn);
}
if (ui != null) {
prop.setProperty("ui", ui);
}
if (tileSize != null) {
prop.setProperty("tile-size", tileSize);
}
prop.store(output, null);
}
catch (IOException io) {
io.printStackTrace();
}
finally {
if (output != null) {
try {
output.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
// Set Owner read/write
Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
try {
Files.setPosixFilePermissions(Paths.get(path), perms);
}
catch (UnsupportedOperationException e) {
// most likely because it's MS Windows
}
catch (IOException e) {
e.printStackTrace();
}
}
public void loadFile() {
this.login = null;
this.password = null;
this.proxy = null;
this.hostname = null;
this.computeMethod = null;
this.gpu = null;
this.cacheDir = null;
this.autoSignIn = null;
this.ui = null;
this.tileSize = null;
this.priority = 19; // must be the same default as Configuration
this.ram = null;
this.renderTime = null;
if (new File(path).exists() == false) {
return;
}
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(path);
prop.load(input);
if (prop.containsKey("cache-dir")) {
this.cacheDir = prop.getProperty("cache-dir");
}
if (prop.containsKey("compute-method")) {
this.computeMethod = prop.getProperty("compute-method");
}
if (prop.containsKey("compute-gpu")) {
this.gpu = prop.getProperty("compute-gpu");
}
if (prop.containsKey("cpu-cores")) { // backward compatibility
this.cores = prop.getProperty("cpu-cores");
}
if (prop.containsKey("cores")) {
this.cores = prop.getProperty("cores");
}
if (prop.containsKey("ram")) {
this.ram = prop.getProperty("ram");
}
if (prop.containsKey("rendertime")) {
this.renderTime = prop.getProperty("rendertime");
}
if (prop.containsKey("login")) {
this.login = prop.getProperty("login");
}
if (prop.containsKey("password")) {
this.password = prop.getProperty("password");
}
if (prop.containsKey("proxy")) {
this.proxy = prop.getProperty("proxy");
}
if (prop.containsKey("hostname")) {
this.hostname = prop.getProperty("hostname");
}
if (prop.containsKey("auto-signin")) {
this.autoSignIn = prop.getProperty("auto-signin");
}
if (prop.containsKey("ui")) {
this.ui = prop.getProperty("ui");
}
if (prop.containsKey("tile-size")) {
this.tileSize = prop.getProperty("tile-size");
}
if (prop.containsKey("priority")) {
this.priority = Integer.parseInt(prop.getProperty("priority"));
}
}
catch (IOException io) {
io.printStackTrace();
}
finally {
if (input != null) {
try {
input.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Merge the Settings file with the Configuration.
* The Configuration will have high priority.
*/
public void merge(Configuration config) {
if (config == null) {
System.out.println("SettingsLoader::merge config is null");
}
loadFile();
if (config.getLogin().isEmpty() && login != null) {
config.setLogin(login);
}
if (config.getPassword().isEmpty() && password != null) {
config.setPassword(password);
}
if ((config.getProxy() == null || config.getProxy().isEmpty()) && proxy != null) {
config.setProxy(proxy);
}
if ((config.getHostname() == null || config.getHostname().isEmpty() || config.getHostname().equals(config.getDefaultHostname())) && hostname != null) {
config.setHostname(hostname);
}
if (config.getPriority() == 19) { // 19 is default value
config.setUsePriority(priority);
}
try {
if ((config.getComputeMethod() == null && computeMethod != null) || (computeMethod != null && config.getComputeMethod() != ComputeType.valueOf(computeMethod))) {
config.setComputeMethod(ComputeType.valueOf(computeMethod));
}
}
catch (IllegalArgumentException e) {
System.err.println("SettingsLoader::merge failed to handle compute method (raw value: '" + computeMethod + "')");
computeMethod = null;
}
if (config.getGPUDevice() == null && gpu != null) {
GPUDevice device = GPU.getGPUDevice(gpu);
if (device != null) {
config.setGPUDevice(device);
}
}
if (config.getNbCores() == -1 && cores != null) {
config.setNbCores(Integer.valueOf(cores));
}
if (config.getMaxMemory() == -1 && ram != null) {
config.setMaxMemory(Utils.parseNumber(ram) / 1000); // internal ram value is in kB
}
if (config.getMaxRenderTime() == -1 && renderTime != null) {
config.setMaxRenderTime(Integer.valueOf(renderTime));
}
if (config.isUserHasSpecifiedACacheDir() == false && cacheDir != null) {
config.setCacheDir(new File(cacheDir));
}
if (config.getUIType() == null && ui != null) {
config.setUIType(ui);
}
if (config.getTileSize() == -1 && tileSize != null) {
config.setTileSize(Integer.valueOf(tileSize));
}
config.setAutoSignIn(Boolean.valueOf(autoSignIn));
}
@Override
public String toString() {
return "SettingsLoader [path=" + path + ", login=" + login + ", password=" + password + ", computeMethod=" + computeMethod + ", gpu=" + gpu + ", cacheDir=" + cacheDir + "priority="+priority+"]";
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (C) 2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
public class ShutdownHook {
private Client _client;
public ShutdownHook(Client client_) {
this._client = client_;
}
public void attachShutDownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
_client.stop();
}
});
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2016 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
public class Stats {
private int remainingFrame;
private int creditsEarned;
private int creditsEarnedSession;
private int renderableProject;
private int waitingProject;
private int connectedMachine;
public Stats(int frame, int credits, int creditsSession, int renderables, int waitings, int machines) {
remainingFrame = frame;
creditsEarned = credits;
creditsEarnedSession = creditsSession;
renderableProject = renderables;
waitingProject = waitings;
connectedMachine = machines;
}
public Stats() {
remainingFrame = 0;
creditsEarned = 0;
creditsEarnedSession = 0;
renderableProject = 0;
waitingProject = 0;
connectedMachine = 0;
}
public int getRemainingFrame() {
return remainingFrame;
}
public int getCreditsEarnedDuringSession() {
return creditsEarnedSession;
}
public int getCreditsEarned() {
return creditsEarned;
}
public int getRenderableProject() {
return renderableProject;
}
public int getWaitingProject() {
return waitingProject;
}
public int getConnectedMachine() {
return connectedMachine;
}
@Override
public String toString() {
return "Stats [remainingFrame=" + remainingFrame + ", creditsEarned=" + creditsEarned + ", creditsEarnedSession=" + creditsEarnedSession + ", renderableProject=" + renderableProject + ", waitingProject=" + waitingProject + ", connectedMachine=" + connectedMachine + "]";
}
}

View File

@@ -1,216 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import net.lingala.zip4j.model.UnzipParameters;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.sheepit.client.Error.ServerCode;
import com.sheepit.client.exception.FermeExceptionNoSpaceLeftOnDevice;
public class Utils {
public static int unzipFileIntoDirectory(String zipFileName_, String destinationDirectory, String password, Log log) throws FermeExceptionNoSpaceLeftOnDevice {
try {
ZipFile zipFile = new ZipFile(zipFileName_);
UnzipParameters unzipParameters = new UnzipParameters();
unzipParameters.setIgnoreDateTimeAttributes(true);
if (password != null && zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(destinationDirectory, unzipParameters);
}
catch (ZipException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
log.debug("Utils::unzipFileIntoDirectory(" + zipFileName_ + "," + destinationDirectory + ") exception " + e + " stacktrace: " + sw.toString());
return -1;
}
return 0;
}
public static String md5(String path_of_file_) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
InputStream is = Files.newInputStream(Paths.get(path_of_file_));
DigestInputStream dis = new DigestInputStream(is, md);
byte[] buffer = new byte[8192];
while (dis.read(buffer) > 0)
; // process the entire file
String data = DatatypeConverter.printHexBinary(md.digest()).toLowerCase();
dis.close();
is.close();
return data;
}
catch (NoSuchAlgorithmException | IOException e) {
return "";
}
}
public static double lastModificationTime(File directory_) {
double max = 0.0;
if (directory_.isDirectory()) {
File[] list = directory_.listFiles();
if (list != null) {
for (File aFile : list) {
double max1 = lastModificationTime(aFile);
if (max1 > max) {
max = max1;
}
}
}
}
else if (directory_.isFile()) {
return directory_.lastModified();
}
return max;
}
public static ServerCode statusIsOK(Document document_, String rootname_) {
if (document_ == null) {
return Error.ServerCode.UNKNOWN;
}
NodeList ns = document_.getElementsByTagName(rootname_);
if (ns.getLength() == 0) {
return Error.ServerCode.ERROR_NO_ROOT;
}
Element a_node = (Element) ns.item(0);
if (a_node.hasAttribute("status")) {
return Error.ServerCode.fromInt(Integer.parseInt(a_node.getAttribute("status")));
}
return Error.ServerCode.UNKNOWN;
}
/**
* Will recursively delete a directory
*/
public static void delete(File file) {
if (file == null) {
return;
}
if (file.isDirectory()) {
String files[] = file.list();
if (files != null) {
if (files.length != 0) {
for (String temp : files) {
File fileDelete = new File(file, temp);
delete(fileDelete);
}
}
}
}
file.delete();
}
/**
* Parse a number string to a number.
* Input can be as "32", "10k", "100K", "100G", "1.3G", "0.4T"
*/
public static long parseNumber(String in) {
in = in.trim();
in = in.replaceAll(",", ".");
try {
return Long.parseLong(in);
}
catch (NumberFormatException e) {
}
final Matcher m = Pattern.compile("([\\d.,]+)\\s*(\\w)").matcher(in);
m.find();
int scale = 1;
switch (m.group(2).charAt(0)) {
case 'T':
case 't':
scale = 1000 * 1000 * 1000 * 1000;
break;
case 'G':
case 'g':
scale = 1000 * 1000 * 1000;
break;
case 'M':
case 'm':
scale = 1000 * 1000;
break;
case 'K':
case 'k':
scale = 1000;
break;
}
return Math.round(Double.parseDouble(m.group(1)) * scale);
}
public static String humanDuration(Date date) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.setTime(date);
int hours = (calendar.get(Calendar.DAY_OF_MONTH) - 1) * 24 + calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
String output = "";
if (hours > 0) {
output += hours + "h";
}
if (minutes > 0) {
output += minutes + "min";
}
if (seconds > 0) {
output += seconds + "s";
}
return output;
}
public static boolean noFreeSpaceOnDisk(String destination_) {
try {
File file = new File(destination_);
return (file.getUsableSpace() < 512 * 1024); // at least the same amount as Server.HTTPGetFile
}
catch (SecurityException e) {
}
return false;
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2010-2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeException extends Exception {
public FermeException() {
super();
}
public FermeException(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2016 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionBadResponseFromServer extends FermeException {
public FermeExceptionBadResponseFromServer() {
super();
}
public FermeExceptionBadResponseFromServer(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2017 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionNoRendererAvailable extends FermeException {
public FermeExceptionNoRendererAvailable() {
super();
}
public FermeExceptionNoRendererAvailable(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionNoRightToRender extends FermeException {
public FermeExceptionNoRightToRender() {
super();
}
public FermeExceptionNoRightToRender(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionNoSession extends FermeException {
public FermeExceptionNoSession() {
super();
}
public FermeExceptionNoSession(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2016 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionNoSpaceLeftOnDevice extends FermeException {
public FermeExceptionNoSpaceLeftOnDevice() {
super();
}
public FermeExceptionNoSpaceLeftOnDevice(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2016 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionServerInMaintenance extends FermeException {
public FermeExceptionServerInMaintenance() {
super();
}
public FermeExceptionServerInMaintenance(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2016 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionServerOverloaded extends FermeException {
public FermeExceptionServerOverloaded() {
super();
}
public FermeExceptionServerOverloaded(String message_) {
super(message_);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
public class FermeExceptionSessionDisabled extends FermeException {
public FermeExceptionSessionDisabled() {
super();
}
public FermeExceptionSessionDisabled(String message_) {
super(message_);
}
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.exception;
/**
* Server down (server side error) or unreachable (client side error)
*
*/
public class FermeServerDown extends FermeException {
public FermeServerDown() {
super();
}
public FermeServerDown(String message_) {
super(message_);
}
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.cpu;
public class CPU {
private String name;
private String model;
private String family;
private String arch; // 32 or 64 bits
public CPU() {
this.name = null;
this.model = null;
this.family = null;
this.generateArch();
}
public String name() {
return this.name;
}
public String model() {
return this.model;
}
public String family() {
return this.family;
}
public String arch() {
return this.arch;
}
public int cores() {
return Runtime.getRuntime().availableProcessors();
}
public void setName(String name_) {
this.name = name_;
}
public void setModel(String model_) {
this.model = model_;
}
public void setFamily(String family_) {
this.family = family_;
}
public void setArch(String arch_) {
this.arch = arch_;
}
public void generateArch() {
String arch = System.getProperty("os.arch").toLowerCase();
switch (arch) {
case "i386":
case "i686":
case "x86":
this.arch = "32bit";
break;
case "amd64":
case "x86_64":
this.arch = "64bit";
break;
default:
this.arch = null;
break;
}
}
public boolean haveData() {
return this.name != null && this.model != null && this.family != null && this.arch != null;
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu;
import java.util.LinkedList;
import java.util.List;
import com.sheepit.client.Configuration;
import com.sheepit.client.hardware.gpu.nvidia.Nvidia;
import com.sheepit.client.hardware.gpu.opencl.OpenCL;
import com.sheepit.client.os.OS;
import com.sheepit.client.os.Windows;
public class GPU {
public static List<GPUDevice> devices = null;
public static boolean generate() {
devices = new LinkedList<GPUDevice>();
List<GPUDevice> gpus = new Nvidia().getGpus();
if (gpus != null) {
devices.addAll(gpus);
}
OS os = OS.getOS();
if (os instanceof Windows) { // opencl detection will crash on Mac (and sometimes on Linux)
gpus = new OpenCL().getGpus();
if (gpus != null) {
devices.addAll(gpus);
}
}
return true;
}
public static List<String> listModels() {
if (devices == null) {
generate();
}
List<String> devs = new LinkedList<String>();
for (GPUDevice dev : devices) {
devs.add(dev.getModel());
}
return devs;
}
public static List<GPUDevice> listDevices(Configuration config) {
if (devices == null) {
if (config.isDetectGPUs()) {
generate();
}
else {
devices = new LinkedList<GPUDevice>();
}
}
return devices;
}
public static GPUDevice getGPUDevice(String deviceId) {
if (deviceId == null) {
return null;
}
if (devices == null) {
generate();
}
if (devices == null) {
return null;
}
for (GPUDevice dev : devices) {
if (deviceId.equals(dev.getId()) || deviceId.equals(dev.getOldId())) {
return dev;
}
}
return null;
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu;
public class GPUDevice {
private String type;
private String model;
private long memory; // in B
private String id;
private String oldId; // for backward compatibility
public GPUDevice(String type, String model, long ram, String id) {
this.type = type;
this.model = model;
this.memory = ram;
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public long getMemory() {
return memory;
}
public void setMemory(long memory) {
this.memory = memory;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOldId() {
return oldId;
}
public void setOldId(String id) {
this.oldId = id;
}
@Override
public String toString() {
return "GPUDevice [type=" + type + ", model='" + model + "', memory=" + memory + ", id=" + id + "]";
}
public int getRecommandedTileSize() {
// GPU
// if the vram is lower than 1G reduce the size of tile to avoid black output
return (getMemory() > 1073741824L) ? 256 : 128;
}
}

View File

@@ -1,7 +0,0 @@
package com.sheepit.client.hardware.gpu;
import java.util.List;
public interface GPULister {
public abstract List<GPUDevice> getGpus();
}

View File

@@ -1,43 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu.nvidia;
import com.sun.jna.Library;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
public interface CUDA extends Library {
public int cuInit(int flags);
/*
* @return: CUDA_SUCCESS, CUDA_ERROR_DEINITIALIZED, CUDA_ERROR_NOT_INITIALIZED, CUDA_ERROR_INVALID_CONTEXT, CUDA_ERROR_INVALID_VALUE
*/
public int cuDeviceGetCount(IntByReference count);
public int cuDeviceGetName(byte[] name, int len, int dev);
public int cuDeviceGet (IntByReference device, int ordinal);
public int cuDeviceGetAttribute (IntByReference pi, int attrib, int dev );
public int cuDeviceTotalMem_v2(LongByReference bytes, int dev);
public int cuDeviceTotalMem(LongByReference bytes, int dev);
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) 2018 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu.nvidia;
/**
* CUDA Device properties. Taken directly from the online manual:
* https://docs.nvidia.com/cuda/cuda-driver-api
*/
public class CUDeviceAttribute {
/**
* PCI bus ID of the device
*/
public static final int CU_DEVICE_ATTRIBUTE_PCI_BUS_ID = 33;
/**
* PCI device ID of the device
*/
public static final int CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID = 34;
/**
* PCI domain ID of the device
*/
public static final int CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID = 50;
}

View File

@@ -1,513 +0,0 @@
/*
* JCuda - Java bindings for NVIDIA CUDA driver and runtime API
*
* Copyright (c) 2009-2012 Marco Hutter - http://www.jcuda.org
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//package jcuda.driver;
package com.sheepit.client.hardware.gpu.nvidia;
/**
* Error codes.<br />
* <br />
* Most comments are taken from the CUDA reference manual.
*/
public class CUresult {
/**
* The API call returned with no errors. In the case of query calls, this
* can also mean that the operation being queried is complete (see
* ::cuEventQuery() and ::cuStreamQuery()).
*/
public static final int CUDA_SUCCESS = 0;
/**
* This indicates that one or more of the parameters passed to the API call
* is not within an acceptable range of values.
*/
public static final int CUDA_ERROR_INVALID_VALUE = 1;
/**
* The API call failed because it was unable to allocate enough memory to
* perform the requested operation.
*/
public static final int CUDA_ERROR_OUT_OF_MEMORY = 2;
/**
* This indicates that the CUDA driver has not been initialized with
* ::cuInit() or that initialization has failed.
*/
public static final int CUDA_ERROR_NOT_INITIALIZED = 3;
/**
* This indicates that the CUDA driver is in the process of shutting down.
*/
public static final int CUDA_ERROR_DEINITIALIZED = 4;
/**
* This indicates profiling APIs are called while application is running
* in visual profiler mode.
*/
public static final int CUDA_ERROR_PROFILER_DISABLED = 5;
/**
* This indicates profiling has not been initialized for this context.
* Call cuProfilerInitialize() to resolve this.
*
* @deprecated This error return is deprecated as of CUDA 5.0.
* It is no longer an error to attempt to enable/disable the
* profiling via ::cuProfilerStart or ::cuProfilerStop without
* initialization.
*/
public static final int CUDA_ERROR_PROFILER_NOT_INITIALIZED = 6;
/**
* This indicates profiler has already been started and probably
* cuProfilerStart() is incorrectly called.
*
* @deprecated This error return is deprecated as of CUDA 5.0.
* It is no longer an error to call cuProfilerStart() when
* profiling is already enabled.
*/
public static final int CUDA_ERROR_PROFILER_ALREADY_STARTED = 7;
/**
* This indicates profiler has already been stopped and probably
* cuProfilerStop() is incorrectly called.
*
* @deprecated This error return is deprecated as of CUDA 5.0.
* It is no longer an error to call cuProfilerStop() when
* profiling is already disabled.
*/
public static final int CUDA_ERROR_PROFILER_ALREADY_STOPPED = 8;
/**
* This indicates that no CUDA-capable devices were detected by the installed
* CUDA driver.
*/
public static final int CUDA_ERROR_NO_DEVICE = 100;
/**
* This indicates that the device ordinal supplied by the user does not
* correspond to a valid CUDA device.
*/
public static final int CUDA_ERROR_INVALID_DEVICE = 101;
/**
* This indicates that the device kernel image is invalid. This can also
* indicate an invalid CUDA module.
*/
public static final int CUDA_ERROR_INVALID_IMAGE = 200;
/**
* This most frequently indicates that there is no context bound to the
* current thread. This can also be returned if the context passed to an
* API call is not a valid handle (such as a context that has had
* ::cuCtxDestroy() invoked on it). This can also be returned if a user
* mixes different API versions (i.e. 3010 context with 3020 API calls).
* See ::cuCtxGetApiVersion() for more details.
*/
public static final int CUDA_ERROR_INVALID_CONTEXT = 201;
/**
* This indicated that the context being supplied as a parameter to the
* API call was already the active context.
* \deprecated
* This error return is deprecated as of CUDA 3.2. It is no longer an
* error to attempt to push the active context via ::cuCtxPushCurrent().
*/
public static final int CUDA_ERROR_CONTEXT_ALREADY_CURRENT = 202;
/**
* This indicates that a map or register operation has failed.
*/
public static final int CUDA_ERROR_MAP_FAILED = 205;
/**
* This indicates that an unmap or unregister operation has failed.
*/
public static final int CUDA_ERROR_UNMAP_FAILED = 206;
/**
* This indicates that the specified array is currently mapped and thus
* cannot be destroyed.
*/
public static final int CUDA_ERROR_ARRAY_IS_MAPPED = 207;
/**
* This indicates that the resource is already mapped.
*/
public static final int CUDA_ERROR_ALREADY_MAPPED = 208;
/**
* This indicates that there is no kernel image available that is suitable
* for the device. This can occur when a user specifies code generation
* options for a particular CUDA source file that do not include the
* corresponding device configuration.
*/
public static final int CUDA_ERROR_NO_BINARY_FOR_GPU = 209;
/**
* This indicates that a resource has already been acquired.
*/
public static final int CUDA_ERROR_ALREADY_ACQUIRED = 210;
/**
* This indicates that a resource is not mapped.
*/
public static final int CUDA_ERROR_NOT_MAPPED = 211;
/**
* This indicates that a mapped resource is not available for access as an
* array.
*/
public static final int CUDA_ERROR_NOT_MAPPED_AS_ARRAY = 212;
/**
* This indicates that a mapped resource is not available for access as a
* pointer.
*/
public static final int CUDA_ERROR_NOT_MAPPED_AS_POINTER = 213;
/**
* This indicates that an uncorrectable ECC error was detected during
* execution.
*/
public static final int CUDA_ERROR_ECC_UNCORRECTABLE = 214;
/**
* This indicates that the ::CUlimit passed to the API call is not
* supported by the active device.
*/
public static final int CUDA_ERROR_UNSUPPORTED_LIMIT = 215;
/**
* This indicates that the ::CUcontext passed to the API call can
* only be bound to a single CPU thread at a time but is already
* bound to a CPU thread.
*/
public static final int CUDA_ERROR_CONTEXT_ALREADY_IN_USE = 216;
/**
* This indicates that peer access is not supported across the given
* devices.
*/
public static final int CUDA_ERROR_PEER_ACCESS_UNSUPPORTED = 217;
/**
* This indicates that the device kernel source is invalid.
*/
public static final int CUDA_ERROR_INVALID_SOURCE = 300;
/**
* This indicates that the file specified was not found.
*/
public static final int CUDA_ERROR_FILE_NOT_FOUND = 301;
/**
* This indicates that a link to a shared object failed to resolve.
*/
public static final int CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302;
/**
* This indicates that initialization of a shared object failed.
*/
public static final int CUDA_ERROR_SHARED_OBJECT_INIT_FAILED = 303;
/**
* This indicates that an OS call failed.
*/
public static final int CUDA_ERROR_OPERATING_SYSTEM = 304;
/**
* This indicates that a resource handle passed to the API call was not
* valid. Resource handles are opaque types like ::CUstream and ::CUevent.
*/
public static final int CUDA_ERROR_INVALID_HANDLE = 400;
/**
* This indicates that a named symbol was not found. Examples of symbols
* are global/constant variable names, texture names, and surface names.
*/
public static final int CUDA_ERROR_NOT_FOUND = 500;
/**
* This indicates that asynchronous operations issued previously have not
* completed yet. This result is not actually an error, but must be indicated
* differently than ::CUDA_SUCCESS (which indicates completion). Calls that
* may return this value include ::cuEventQuery() and ::cuStreamQuery().
*/
public static final int CUDA_ERROR_NOT_READY = 600;
/**
* An exception occurred on the device while executing a kernel. Common
* causes include dereferencing an invalid device pointer and accessing
* out of bounds shared memory. The context cannot be used, so it must
* be destroyed (and a new one should be created). All existing device
* memory allocations from this context are invalid and must be
* reconstructed if the program is to continue using CUDA.
*/
public static final int CUDA_ERROR_LAUNCH_FAILED = 700;
/**
* This indicates that a launch did not occur because it did not have
* appropriate resources. This error usually indicates that the user has
* attempted to pass too many arguments to the device kernel, or the
* kernel launch specifies too many threads for the kernel's register
* count. Passing arguments of the wrong size (i.e. a 64-bit pointer
* when a 32-bit int is expected) is equivalent to passing too many
* arguments and can also result in this error.
*/
public static final int CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES = 701;
/**
* This indicates that the device kernel took too long to execute. This can
* only occur if timeouts are enabled - see the device attribute
* ::CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT for more information. The
* context cannot be used (and must be destroyed similar to
* ::CUDA_ERROR_LAUNCH_FAILED). All existing device memory allocations from
* this context are invalid and must be reconstructed if the program is to
* continue using CUDA.
*/
public static final int CUDA_ERROR_LAUNCH_TIMEOUT = 702;
/**
* This error indicates a kernel launch that uses an incompatible texturing
* mode.
*/
public static final int CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING = 703;
/**
* This error indicates that a call to ::cuCtxEnablePeerAccess() is
* trying to re-enable peer access to a context which has already
* had peer access to it enabled.
*/
public static final int CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED = 704;
/**
* This error indicates that a call to ::cuMemPeerRegister is trying to
* register memory from a context which has not had peer access
* enabled yet via ::cuCtxEnablePeerAccess(), or that
* ::cuCtxDisablePeerAccess() is trying to disable peer access
* which has not been enabled yet.
*/
public static final int CUDA_ERROR_PEER_ACCESS_NOT_ENABLED = 705;
/**
* This error indicates that a call to ::cuMemPeerRegister is trying to
* register already-registered memory.
*
* @deprecated This value has been added in CUDA 4.0 RC,
* and removed in CUDA 4.0 RC2
*/
public static final int CUDA_ERROR_PEER_MEMORY_ALREADY_REGISTERED = 706;
/**
* This error indicates that a call to ::cuMemPeerUnregister is trying to
* unregister memory that has not been registered.
*
* @deprecated This value has been added in CUDA 4.0 RC,
* and removed in CUDA 4.0 RC2
*/
public static final int CUDA_ERROR_PEER_MEMORY_NOT_REGISTERED = 707;
/**
* This error indicates that ::cuCtxCreate was called with the flag
* ::CU_CTX_PRIMARY on a device which already has initialized its
* primary context.
*/
public static final int CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE = 708;
/**
* This error indicates that the context current to the calling thread
* has been destroyed using ::cuCtxDestroy, or is a primary context which
* has not yet been initialized.
*/
public static final int CUDA_ERROR_CONTEXT_IS_DESTROYED = 709;
/**
* A device-side assert triggered during kernel execution. The context
* cannot be used anymore, and must be destroyed. All existing device
* memory allocations from this context are invalid and must be
* reconstructed if the program is to continue using CUDA.
*/
public static final int CUDA_ERROR_ASSERT = 710;
/**
* This error indicates that the hardware resources required to enable
* peer access have been exhausted for one or more of the devices
* passed to ::cuCtxEnablePeerAccess().
*/
public static final int CUDA_ERROR_TOO_MANY_PEERS = 711;
/**
* This error indicates that the memory range passed to ::cuMemHostRegister()
* has already been registered.
*/
public static final int CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED = 712;
/**
* This error indicates that the pointer passed to ::cuMemHostUnregister()
* does not correspond to any currently registered memory region.
*/
public static final int CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED = 713;
/**
* This error indicates that the attempted operation is not permitted.
*/
public static final int CUDA_ERROR_NOT_PERMITTED = 800;
/**
* This error indicates that the attempted operation is not supported
* on the current system or device.
*/
public static final int CUDA_ERROR_NOT_SUPPORTED = 801;
/**
* This indicates that an unknown internal error has occurred.
*/
public static final int CUDA_ERROR_UNKNOWN = 999;
/**
* Returns the String identifying the given CUresult
*
* @param result The CUresult value
* @return The String identifying the given CUresult
*/
public static String stringFor(int result) {
switch (result) {
case CUDA_SUCCESS:
return "CUDA_SUCCESS";
case CUDA_ERROR_INVALID_VALUE:
return "CUDA_ERROR_INVALID_VALUE";
case CUDA_ERROR_OUT_OF_MEMORY:
return "CUDA_ERROR_OUT_OF_MEMORY";
case CUDA_ERROR_NOT_INITIALIZED:
return "CUDA_ERROR_NOT_INITIALIZED";
case CUDA_ERROR_DEINITIALIZED:
return "CUDA_ERROR_DEINITIALIZED";
case CUDA_ERROR_PROFILER_DISABLED:
return "CUDA_ERROR_PROFILER_DISABLED";
case CUDA_ERROR_PROFILER_NOT_INITIALIZED:
return "CUDA_ERROR_PROFILER_NOT_INITIALIZED";
case CUDA_ERROR_PROFILER_ALREADY_STARTED:
return "CUDA_ERROR_PROFILER_ALREADY_STARTED";
case CUDA_ERROR_PROFILER_ALREADY_STOPPED:
return "CUDA_ERROR_PROFILER_ALREADY_STOPPED";
case CUDA_ERROR_NO_DEVICE:
return "CUDA_ERROR_NO_DEVICE";
case CUDA_ERROR_INVALID_DEVICE:
return "CUDA_ERROR_INVALID_DEVICE";
case CUDA_ERROR_INVALID_IMAGE:
return "CUDA_ERROR_INVALID_IMAGE";
case CUDA_ERROR_INVALID_CONTEXT:
return "CUDA_ERROR_INVALID_CONTEXT";
case CUDA_ERROR_CONTEXT_ALREADY_CURRENT:
return "CUDA_ERROR_CONTEXT_ALREADY_CURRENT";
case CUDA_ERROR_MAP_FAILED:
return "CUDA_ERROR_MAP_FAILED";
case CUDA_ERROR_UNMAP_FAILED:
return "CUDA_ERROR_UNMAP_FAILED";
case CUDA_ERROR_ARRAY_IS_MAPPED:
return "CUDA_ERROR_ARRAY_IS_MAPPED";
case CUDA_ERROR_ALREADY_MAPPED:
return "CUDA_ERROR_ALREADY_MAPPED";
case CUDA_ERROR_NO_BINARY_FOR_GPU:
return "CUDA_ERROR_NO_BINARY_FOR_GPU";
case CUDA_ERROR_ALREADY_ACQUIRED:
return "CUDA_ERROR_ALREADY_ACQUIRED";
case CUDA_ERROR_NOT_MAPPED:
return "CUDA_ERROR_NOT_MAPPED";
case CUDA_ERROR_NOT_MAPPED_AS_ARRAY:
return "CUDA_ERROR_NOT_MAPPED_AS_ARRAY";
case CUDA_ERROR_NOT_MAPPED_AS_POINTER:
return "CUDA_ERROR_NOT_MAPPED_AS_POINTER";
case CUDA_ERROR_ECC_UNCORRECTABLE:
return "CUDA_ERROR_ECC_UNCORRECTABLE";
case CUDA_ERROR_UNSUPPORTED_LIMIT:
return "CUDA_ERROR_UNSUPPORTED_LIMIT";
case CUDA_ERROR_CONTEXT_ALREADY_IN_USE:
return "CUDA_ERROR_CONTEXT_ALREADY_IN_USE";
case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED:
return "CUDA_ERROR_PEER_ACCESS_UNSUPPORTED";
case CUDA_ERROR_INVALID_SOURCE:
return "CUDA_ERROR_INVALID_SOURCE";
case CUDA_ERROR_FILE_NOT_FOUND:
return "CUDA_ERROR_FILE_NOT_FOUND";
case CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND:
return "CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND";
case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED:
return "CUDA_ERROR_SHARED_OBJECT_INIT_FAILED";
case CUDA_ERROR_OPERATING_SYSTEM:
return "CUDA_ERROR_OPERATING_SYSTEM";
case CUDA_ERROR_INVALID_HANDLE:
return "CUDA_ERROR_INVALID_HANDLE";
case CUDA_ERROR_NOT_FOUND:
return "CUDA_ERROR_NOT_FOUND";
case CUDA_ERROR_NOT_READY:
return "CUDA_ERROR_NOT_READY";
case CUDA_ERROR_LAUNCH_FAILED:
return "CUDA_ERROR_LAUNCH_FAILED";
case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES:
return "CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES";
case CUDA_ERROR_LAUNCH_TIMEOUT:
return "CUDA_ERROR_LAUNCH_TIMEOUT";
case CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING:
return "CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING";
case CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED:
return "CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED";
case CUDA_ERROR_PEER_ACCESS_NOT_ENABLED:
return "CUDA_ERROR_PEER_ACCESS_NOT_ENABLED";
case CUDA_ERROR_PEER_MEMORY_ALREADY_REGISTERED:
return "CUDA_ERROR_PEER_MEMORY_ALREADY_REGISTERED";
case CUDA_ERROR_PEER_MEMORY_NOT_REGISTERED:
return "CUDA_ERROR_PEER_MEMORY_NOT_REGISTERED";
case CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE:
return "CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE";
case CUDA_ERROR_CONTEXT_IS_DESTROYED:
return "CUDA_ERROR_CONTEXT_IS_DESTROYED";
case CUDA_ERROR_ASSERT:
return "CUDA_ERROR_ASSERT";
case CUDA_ERROR_TOO_MANY_PEERS:
return "CUDA_ERROR_TOO_MANY_PEERS";
case CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED:
return "CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED";
case CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED:
return "CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED";
case CUDA_ERROR_NOT_PERMITTED:
return "CUDA_ERROR_NOT_PERMITTED";
case CUDA_ERROR_NOT_SUPPORTED:
return "CUDA_ERROR_NOT_SUPPORTED";
case CUDA_ERROR_UNKNOWN:
return "CUDA_ERROR_UNKNOWN";
}
return "INVALID CUresult: " + result;
}
/**
* Private constructor to prevent instantiation.
*/
private CUresult() {
}
}

View File

@@ -1,141 +0,0 @@
package com.sheepit.client.hardware.gpu.nvidia;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.sheepit.client.hardware.gpu.nvidia.CUDeviceAttribute;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.hardware.gpu.GPULister;
import com.sheepit.client.os.OS;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
public class Nvidia implements GPULister {
public static String TYPE = "CUDA";
@Override
public List<GPUDevice> getGpus() {
OS os = OS.getOS();
String path = os.getCUDALib();
if (path == null) {
return null;
}
CUDA cudalib = null;
try {
cudalib = (CUDA) Native.loadLibrary(path, CUDA.class);
}
catch (java.lang.UnsatisfiedLinkError e) {
return null;
}
catch (java.lang.ExceptionInInitializerError e) {
System.out.println("Nvidia::getGpus ExceptionInInitializerError " + e);
return null;
}
catch (Exception e) {
System.out.println("Nvidia::getGpus generic exception " + e);
return null;
}
int result = CUresult.CUDA_ERROR_UNKNOWN;
result = cudalib.cuInit(0);
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuInit failed (ret: " + result + ")");
if (result == CUresult.CUDA_ERROR_UNKNOWN) {
System.out.println("If you are running Linux, this error is usually due to nvidia kernel module 'nvidia_uvm' not loaded.");
System.out.println("Relaunch the application as root or load the module.");
System.out.println("Most of time it does fix the issue.");
}
return null;
}
if (result == CUresult.CUDA_ERROR_NO_DEVICE) {
return null;
}
IntByReference count = new IntByReference();
result = cudalib.cuDeviceGetCount(count);
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGetCount failed (ret: " + CUresult.stringFor(result) + ")");
return null;
}
List<GPUDevice> devices = new LinkedList<GPUDevice>();
HashMap<String, GPUDevice> devicesWithPciId = new HashMap<String, GPUDevice>(count.getValue());
for (int num = 0; num < count.getValue(); num++) {
IntByReference aDevice = new IntByReference();
result = cudalib.cuDeviceGet(aDevice, num);
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGet failed (ret: " + CUresult.stringFor(result) + ")");
continue;
}
IntByReference pciDomainId = new IntByReference();
IntByReference pciBusId = new IntByReference();
IntByReference pciDeviceId = new IntByReference();
result = cudalib.cuDeviceGetAttribute(pciDomainId, CUDeviceAttribute.CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, aDevice.getValue());
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGetAttribute for CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID failed (ret: " + CUresult.stringFor(result) + ")");
continue;
}
result = cudalib.cuDeviceGetAttribute(pciBusId, CUDeviceAttribute.CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, aDevice.getValue());
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGetAttribute for CU_DEVICE_ATTRIBUTE_PCI_BUS_ID failed (ret: " + CUresult.stringFor(result) + ")");
continue;
}
result = cudalib.cuDeviceGetAttribute(pciDeviceId, CUDeviceAttribute.CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, aDevice.getValue());
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGetAttribute for CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID failed (ret: " + CUresult.stringFor(result) + ")");
continue;
}
byte name[] = new byte[256];
result = cudalib.cuDeviceGetName(name, 256, num);
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceGetName failed (ret: " + CUresult.stringFor(result) + ")");
continue;
}
LongByReference ram = new LongByReference();
try {
result = cudalib.cuDeviceTotalMem_v2(ram, num);
}
catch (UnsatisfiedLinkError e) {
// fall back to old function
result = cudalib.cuDeviceTotalMem(ram, num);
}
if (result != CUresult.CUDA_SUCCESS) {
System.out.println("Nvidia::getGpus cuDeviceTotalMem failed (ret: " + CUresult.stringFor(result) + ")");
return null;
}
String blenderId = String.format("CUDA_%s_%04x:%02x:%02x",
new String(name).trim(),
pciDomainId.getValue(),
pciBusId.getValue(),
pciDeviceId.getValue());
devicesWithPciId.put(Integer.toString(pciBusId.getValue()), new GPUDevice(TYPE, new String(name).trim(), ram.getValue(), blenderId));
}
// for backward compatibility generate a CUDA_N id
// in theory a set to environment "CUDA_DEVICE_ORDER=PCI_BUS_ID" should be enough but it didn't work
int i = 0;
for (Map.Entry<String, GPUDevice> entry : devicesWithPciId.entrySet()){
GPUDevice aDevice = entry.getValue();
aDevice.setOldId(TYPE + "_" + Integer.toString(i));
devices.add(aDevice);
i++;
}
return devices;
}
}

View File

@@ -1,172 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu.opencl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.hardware.gpu.GPULister;
import com.sheepit.client.hardware.gpu.opencl.OpenCLLib.CLDeviceId;
import com.sheepit.client.hardware.gpu.opencl.OpenCLLib.CLPlatformId;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
public class OpenCL implements GPULister {
public static String TYPE = "OPENCL";
@Override
public List<GPUDevice> getGpus() {
OpenCLLib lib = null;
String path = "OpenCL";
try {
lib = (OpenCLLib) Native.loadLibrary(path, OpenCLLib.class);
}
catch (java.lang.UnsatisfiedLinkError e) {
System.out.println("OpenCL::getGpus failed(A) to load OpenCL lib (path: " + path + ")");
return null;
}
catch (java.lang.ExceptionInInitializerError e) {
System.out.println("OpenCL::getGpus failed(B) ExceptionInInitializerError " + e);
return null;
}
catch (Exception e) {
System.out.println("OpenCL::getGpus failed(C) generic exception " + e);
return null;
}
int status = -1;
// get the number of platform
IntByReference number_platforms = new IntByReference();
status = lib.clGetPlatformIDs(0, null, number_platforms);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getGpus failed(D) status: " + status);
return null;
}
// now we can create the platforms
final OpenCLLib.CLPlatformId.ByReference e6ref = new OpenCLLib.CLPlatformId.ByReference();
OpenCLLib.CLPlatformId.ByReference[] plateforms = (OpenCLLib.CLPlatformId.ByReference[]) e6ref.toArray(number_platforms.getValue());
status = lib.clGetPlatformIDs(number_platforms.getValue(), plateforms, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getGpus failed(E) status: " + status);
return null;
}
List<GPUDevice> available_devices = new ArrayList<GPUDevice>(1);
// Devices are numbered consecutively across platforms.
int id = 0;
for (int i = 0; i < number_platforms.getValue(); i++) {
// get number of devices in platform
IntByReference device_count = new IntByReference();
status = lib.clGetDeviceIDs(plateforms[i], OpenCLLib.CL_DEVICE_TYPE_GPU, 0, null, device_count);
if (status == OpenCLLib.CL_DEVICE_NOT_FOUND) {
System.out.println("OpenCL::getGpus no device found on plateforms[" + i + "]");
continue;
}
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getGpus failed(F) status: " + status);
return null;
}
final OpenCLLib.CLDeviceId.ByReference e6ref4 = new OpenCLLib.CLDeviceId.ByReference();
OpenCLLib.CLDeviceId.ByReference[] devices = (OpenCLLib.CLDeviceId.ByReference[]) e6ref4.toArray(device_count.getValue());
status = lib.clGetDeviceIDs(plateforms[i], OpenCLLib.CL_DEVICE_TYPE_GPU, device_count.getValue(), devices, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getGpus failed(G) status: " + status);
return null;
}
for (int j = 0; j < device_count.getValue(); j++) {
String name = getInfodeviceString(lib, devices[j], OpenCLLib.CL_DEVICE_BOARD_NAME_AMD);
long vram = getInfodeviceLong(lib, devices[j], OpenCLLib.CL_DEVICE_GLOBAL_MEM_SIZE);
if (name != null && vram > 0) {
GPUDevice gpu = new GPUDevice(TYPE, new String(name).trim(), vram, getBlenderId(lib, devices[j]));
gpu.setOldId(TYPE + "_" + id);
available_devices.add(gpu);
}
id++;
}
}
return available_devices;
}
private static String getInfodeviceString(OpenCLLib lib, CLDeviceId.ByReference device, int type) {
byte name[] = new byte[256];
int status = lib.clGetDeviceInfo(device, type, 256, name, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getInfodeviceString failed(H) status: " + status + " type: " + type);
return null;
}
return new String(name).trim();
}
private static long getInfodeviceLong(OpenCLLib lib, CLDeviceId.ByReference device, int type) {
byte name[] = new byte[256];
int status = lib.clGetDeviceInfo(device, type, 256, name, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getInfodeviceLong failed(I) status: " + status + " type: " + type);
return -1;
}
ByteBuffer wrapped = ByteBuffer.wrap(name);
wrapped.order(ByteOrder.LITTLE_ENDIAN);
return wrapped.getLong();
}
private static String getInfoPlatform(OpenCLLib lib, CLPlatformId.ByReference platform, int type) {
byte name[] = new byte[256];
int status = lib.clGetPlatformInfo(platform, type, 256, name, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("GPU::getInfoPlatform failed(J) status: " + status + " type: " + type);
return null;
}
return new String(name).trim();
}
private static String getBlenderId(OpenCLLib lib, CLDeviceId.ByReference device) {
byte topology[] = new byte[24];
int status = lib.clGetDeviceInfo(device, 0x4037, 24, topology, null);
if (status != OpenCLLib.CL_SUCCESS) {
System.out.println("OpenCL::getBlenderId failed(I) status: " + status);
return "";
}
return String.format("%02x:%02x.%01x", topology[21], topology[22], topology[23]);
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2013-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.hardware.gpu.opencl;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
public interface OpenCLLib extends Library {
// status
public static final int CL_SUCCESS = 0;
public static final int CL_DEVICE_NOT_FOUND = -1;
public static final int CL_PLATFORM_VENDOR = 0x0903;
// cl_device_type
public static final int CL_DEVICE_TYPE_DEFAULT = (1 << 0);
public static final int CL_DEVICE_TYPE_CPU = (1 << 1);
public static final int CL_DEVICE_TYPE_GPU = (1 << 2);
public static final int CL_DEVICE_TYPE_ACCELERATOR = (1 << 3);
public static final int CL_DEVICE_TYPE_CUSTOM = (1 << 4);
public static final int CL_DEVICE_TYPE_ALL = 0xFFFFFFFF;
// cl_device_info
public static final int CL_DEVICE_NAME = 0x102B;
public static final int CL_DEVICE_GLOBAL_MEM_SIZE = 0x101F;
public static final int CL_DEVICE_BOARD_NAME_AMD = 0x4038;
public int clGetPlatformIDs(int num_entries, CLPlatformId.ByReference[] platforms, IntByReference num_platforms);
public int clGetPlatformInfo(CLPlatformId.ByReference platform, int param_name, long param_value_size, byte[] destination, long size_ret[]);
public int clGetDeviceIDs(CLPlatformId.ByReference platform, int param_name, int num_entries, CLDeviceId.ByReference[] devices, IntByReference device_count);
public int clGetDeviceInfo(CLDeviceId.ByReference device, int param_name, long param_value_size, byte[] destination, long size_ret[]);
public static class CLPlatformId extends Structure {
public static class ByReference extends CLPlatformId implements Structure.ByReference {
}
public int id;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "id" });
}
}
public static class CLDeviceId extends Structure {
public static class ByReference extends CLDeviceId implements Structure.ByReference {
}
public int id;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "id" });
}
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.network;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.Authenticator;
import com.sheepit.client.network.Proxy;
import com.sheepit.client.network.ProxyAuthenticator;
public class Proxy {
public static void set(String url_) throws MalformedURLException {
if (url_ == null || url_.isEmpty()) {
return;
}
URL url = new URL(url_);
String userinfo = url.getUserInfo();
if (userinfo != null) {
String[] elements = userinfo.split(":");
if (elements.length == 2) {
String proxy_user = elements[0];
String proxy_password = elements[1];
if (proxy_user != null && proxy_password != null) {
Authenticator.setDefault(new ProxyAuthenticator(proxy_user, proxy_password));
}
}
}
int port = url.getPort();
if (port == -1) {
port = 8080;
}
System.setProperty("http.proxyHost", url.getHost());
System.setProperty("http.proxyPort", Integer.toString(port));
System.setProperty("https.proxyHost", url.getHost());
System.setProperty("https.proxyPort", Integer.toString(port));
}
public static boolean isValidURL(String url_) {
if (url_ == null || url_.isEmpty()) {
return true;
}
try {
new URL(url_);
return true;
}
catch (MalformedURLException e) {
return false;
}
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (C) 2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.network;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class ProxyAuthenticator extends Authenticator {
private String user;
private String password;
public ProxyAuthenticator(String user, String password) {
this.user = user;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password.toCharArray());
}
}

View File

@@ -1,211 +0,0 @@
/*
* Copyright (C) 2010-2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import com.sheepit.client.Log;
import com.sheepit.client.hardware.cpu.CPU;
public class FreeBSD extends OS {
private final String NICE_BINARY_PATH = "nice";
private Boolean hasNiceBinary;
public FreeBSD() {
super();
this.hasNiceBinary = null;
}
public String name() {
return "freebsd";
}
@Override
public String getRenderBinaryPath() {
return "rend.exe";
}
@Override
public CPU getCPU() {
CPU ret = new CPU();
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec("dmesg");
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
if (line.startsWith("CPU:")) {
String buf[] = line.split(":");
if (buf.length > 1) {
ret.setName(buf[1].trim());
}
}
if (line.contains("Family=") && line.contains("Model=")) {
String buf[] = line.split(" ");
for (int i = 0; i < buf.length; i++) {
if (buf[i].contains("Family")) {
String family = buf[i].split("=")[1];
ret.setFamily(family.split("x")[1]);
}
if (buf[i].contains("Model")) {
String model = buf[i].split("=")[1];
ret.setModel(model.split("x")[1]);
}
}
}
}
b.close();
}
catch (Exception e) {
e.printStackTrace();
}
if (ret.haveData() == false) {
Log.getInstance(null).debug("OS::FreeBSD::getCPU failed to get CPU from dmesg, using partia sysctl");
ret.setModel("0");
ret.setFamily("0");
try {
Runtime run = Runtime.getRuntime();
Process sysctl = run.exec("sysctl -n hw.model");
BufferedReader buf = new BufferedReader(new InputStreamReader(sysctl.getInputStream()));
String name = "";
name = buf.readLine();
buf.close();
if (name == "") {
ret.setName("0");
}
else {
ret.setName(name);
}
}
catch (IOException e) {
Log.getInstance(null).debug("OS::FreeBSD::getCPU exception " + e);
}
}
return ret;
}
@Override
public long getMemory() {
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec("sysctl -n hw.usermem");
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
line = b.readLine();
b.close();
if (line.isEmpty()) {
return 0;
}
Long mem_byte = Long.parseLong(line.trim());
return mem_byte / Long.valueOf(1024);
}
catch (IOException e) {
Log.getInstance(null).debug("OS::FreeBSD::getMemory exception " + e);
}
return 0;
}
@Override
public long getFreeMemory() {
return -1;
}
@Override
public String getCUDALib() {
return "cuda";
}
@Override
public Process exec(List<String> command, Map<String, String> env_overight) throws IOException {
// the renderer have a lib directory so add to the LD_LIBRARY_PATH
// (even if we are not sure that it is the renderer who is launch
Map<String, String> new_env = new HashMap<String, String>();
new_env.putAll(java.lang.System.getenv()); // clone the env
Boolean has_ld_library_path = new_env.containsKey("LD_LIBRARY_PATH");
String lib_dir = (new File(command.get(0))).getParent() + File.separator + "lib";
if (has_ld_library_path == false) {
new_env.put("LD_LIBRARY_PATH", lib_dir);
}
else {
new_env.put("LD_LIBRARY_PATH", new_env.get("LD_LIBRARY_PATH") + ":" + lib_dir);
}
List<String> actual_command = command;
if (this.hasNiceBinary == null) {
this.checkNiceAvailability();
}
if (this.hasNiceBinary.booleanValue()) {
// launch the process in lowest priority
if (env_overight != null) {
actual_command.add(0, env_overight.get("PRIORITY"));
}
else {
actual_command.add(0, "19");
}
actual_command.add(0, "-n");
actual_command.add(0, NICE_BINARY_PATH);
}
else {
Log.getInstance(null).error("No low priority binary, will not launch renderer in normal priority");
}
ProcessBuilder builder = new ProcessBuilder(actual_command);
builder.redirectErrorStream(true);
Map<String, String> env = builder.environment();
env.putAll(new_env);
if (env_overight != null) {
env.putAll(env_overight);
}
return builder.start();
}
private void checkNiceAvailability() {
ProcessBuilder builder = new ProcessBuilder();
builder.command(NICE_BINARY_PATH);
builder.redirectErrorStream(true);
Process process = null;
try {
process = builder.start();
this.hasNiceBinary = true;
}
catch (IOException e) {
this.hasNiceBinary = false;
Log.getInstance(null).error("Failed to find low priority binary, will not launch renderer in normal priority (" + e + ")");
}
finally {
if (process != null) {
process.destroy();
}
}
}
}

View File

@@ -1,231 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import com.sheepit.client.Log;
import com.sheepit.client.hardware.cpu.CPU;
public class Linux extends OS {
private final String NICE_BINARY_PATH = "nice";
private Boolean hasNiceBinary;
public Linux() {
super();
this.hasNiceBinary = null;
}
public String name() {
return "linux";
}
@Override
public String getRenderBinaryPath() {
return "rend.exe";
}
@Override
public CPU getCPU() {
CPU ret = new CPU();
try {
String filePath = "/proc/cpuinfo";
Scanner scanner = new Scanner(new File(filePath));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("model name")) {
String buf[] = line.split(":");
if (buf.length > 1) {
ret.setName(buf[1].trim());
}
}
if (line.startsWith("cpu family")) {
String buf[] = line.split(":");
if (buf.length > 1) {
ret.setFamily(buf[1].trim());
}
}
if (line.startsWith("model") && line.startsWith("model name") == false) {
String buf[] = line.split(":");
if (buf.length > 1) {
ret.setModel(buf[1].trim());
}
}
}
scanner.close();
}
catch (java.lang.NoClassDefFoundError e) {
System.err.println("OS.Linux::getCPU error " + e + " mostly because Scanner class was introduced by Java 5 and you are running a lower version");
}
catch (Exception e) {
e.printStackTrace();
}
return ret;
}
@Override
public long getMemory() {
try {
String filePath = "/proc/meminfo";
Scanner scanner = new Scanner(new File(filePath));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("MemTotal")) {
String buf[] = line.split(":");
if (buf.length > 0) {
Integer buf2 = new Integer(buf[1].trim().split(" ")[0]);
return (((buf2 / 262144) + 1) * 262144); // 256*1024 = 262144
}
}
}
scanner.close();
}
catch (java.lang.NoClassDefFoundError e) {
System.err.println("Machine::type error " + e + " mostly because Scanner class was introducted by Java 5 and you are running a lower version");
}
catch (Exception e) {
e.printStackTrace();
}
return 0;
}
@Override
public long getFreeMemory() {
try {
String filePath = "/proc/meminfo";
Scanner scanner = new Scanner(new File(filePath));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("MemAvailable")) {
String buf[] = line.split(":");
if (buf.length > 0) {
Integer buf2 = new Integer(buf[1].trim().split(" ")[0]);
return (((buf2 / 262144) + 1) * 262144); // 256*1024 = 262144
}
}
}
scanner.close();
}
catch (java.lang.NoClassDefFoundError e) {
System.err.println("OS::Linux::getFreeMemory error " + e + " mostly because Scanner class was introducted by Java 5 and you are running a lower version");
}
catch (Exception e) {
e.printStackTrace();
}
return 0;
}
@Override
public String getCUDALib() {
return "cuda";
}
@Override
public Process exec(List<String> command, Map<String, String> env_overight) throws IOException {
// the renderer have a lib directory so add to the LD_LIBRARY_PATH
// (even if we are not sure that it is the renderer who is launch
Map<String, String> new_env = new HashMap<String, String>();
new_env.putAll(java.lang.System.getenv()); // clone the env
Boolean has_ld_library_path = new_env.containsKey("LD_LIBRARY_PATH");
String lib_dir = (new File(command.get(0))).getParent() + File.separator + "lib";
if (has_ld_library_path == false) {
new_env.put("LD_LIBRARY_PATH", lib_dir);
}
else {
new_env.put("LD_LIBRARY_PATH", new_env.get("LD_LIBRARY_PATH") + ":" + lib_dir);
}
List<String> actual_command = command;
if (this.hasNiceBinary == null) {
this.checkNiceAvailability();
}
if (this.hasNiceBinary.booleanValue()) {
// launch the process in lowest priority
if (env_overight != null) {
actual_command.add(0, env_overight.get("PRIORITY"));
}
else {
actual_command.add(0, "19");
}
actual_command.add(0, "-n");
actual_command.add(0, NICE_BINARY_PATH);
}
else {
Log.getInstance(null).error("No low priority binary, will not launch renderer in normal priority");
}
ProcessBuilder builder = new ProcessBuilder(actual_command);
builder.redirectErrorStream(true);
Map<String, String> env = builder.environment();
env.putAll(new_env);
if (env_overight != null) {
env.putAll(env_overight);
}
return builder.start();
}
@Override
public boolean getSupportHighPriority() {
// only the root user can create process with high (negative nice) value
String logname = System.getenv("LOGNAME");
String user = System.getenv("USER");
if ((logname != null && logname.equals("root")) || (user != null && user.equals("root"))) {
return true;
}
return false;
}
protected void checkNiceAvailability() {
ProcessBuilder builder = new ProcessBuilder();
builder.command(NICE_BINARY_PATH);
builder.redirectErrorStream(true);
Process process = null;
try {
process = builder.start();
this.hasNiceBinary = true;
}
catch (IOException e) {
this.hasNiceBinary = false;
Log.getInstance(null).error("Failed to find low priority binary, will not launch renderer in normal priority (" + e + ")");
}
finally {
if (process != null) {
process.destroy();
}
}
}
}

View File

@@ -1,200 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import com.sheepit.client.Log;
import com.sheepit.client.hardware.cpu.CPU;
public class Mac extends OS {
private final String NICE_BINARY_PATH = "nice";
private Boolean hasNiceBinary;
public Mac() {
super();
this.hasNiceBinary = null;
}
public String name() {
return "mac";
}
@Override
public String getRenderBinaryPath() {
return "Blender" + File.separator + "blender.app" + File.separator + "Contents" + File.separator + "MacOS" + File.separator + "blender";
}
@Override
public CPU getCPU() {
CPU ret = new CPU();
String command = "sysctl machdep.cpu.family machdep.cpu.brand_string";
Process p = null;
BufferedReader input = null;
try {
String line;
p = Runtime.getRuntime().exec(command);
input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
String option_cpu_family = "machdep.cpu.family:";
String option_model_name = "machdep.cpu.brand_string:";
if (line.startsWith(option_model_name)) {
ret.setName(line.substring(option_model_name.length()).trim());
}
if (line.startsWith(option_cpu_family)) {
ret.setFamily(line.substring(option_cpu_family.length()).trim());
}
}
input.close();
input = null;
}
catch (Exception err) {
System.out.println("exception " + err);
err.printStackTrace();
ret.setName("Unknown Mac name");
ret.setFamily("Unknown Mac family");
}
finally {
if (input != null) {
try {
input.close();
}
catch (IOException e) {
}
}
if (p != null) {
p.destroy();
}
}
ret.setModel("Unknown");
return ret;
}
@Override
public long getMemory() {
String command = "sysctl hw.memsize";
Process p = null;
BufferedReader input = null;
try {
String line;
p = Runtime.getRuntime().exec(command);
input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
String option = "hw.memsize:";
if (line.startsWith(option)) {
String memory = line.substring(option.length()).trim(); // memory in bytes
return Long.parseLong(memory) / 1024;
}
}
input.close();
input = null;
}
catch (Exception err) {
System.out.println("exception " + err);
err.printStackTrace();
}
finally {
if (input != null) {
try {
input.close();
}
catch (IOException e) {
}
}
if (p != null) {
p.destroy();
}
}
return -1;
}
@Override
public long getFreeMemory() {
return -1;
}
@Override
public Process exec(List<String> command, Map<String, String> env) throws IOException {
List<String> actual_command = command;
if (this.hasNiceBinary == null) {
this.checkNiceAvailability();
}
if (this.hasNiceBinary.booleanValue()) {
// launch the process in lowest priority
if (env != null) {
actual_command.add(0, env.get("PRIORITY"));
}
else {
actual_command.add(0, "19");
}
actual_command.add(0, "-n");
actual_command.add(0, NICE_BINARY_PATH);
}
else {
Log.getInstance(null).error("No low priority binary, will not launch renderer in normal priority");
}
ProcessBuilder builder = new ProcessBuilder(actual_command);
builder.redirectErrorStream(true);
if (env != null) {
builder.environment().putAll(env);
}
return builder.start();
}
@Override
public String getCUDALib() {
return "/usr/local/cuda/lib/libcuda.dylib";
}
protected void checkNiceAvailability() {
ProcessBuilder builder = new ProcessBuilder();
builder.command(NICE_BINARY_PATH);
builder.redirectErrorStream(true);
Process process = null;
try {
process = builder.start();
this.hasNiceBinary = true;
}
catch (IOException e) {
this.hasNiceBinary = false;
Log.getInstance(null).error("Failed to find low priority binary, will not launch renderer in normal priority (" + e + ")");
}
finally {
if (process != null) {
process.destroy();
}
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.sheepit.client.hardware.cpu.CPU;
public abstract class OS {
private static OS instance = null;
public abstract String name();
public abstract CPU getCPU();
public abstract long getMemory();
public abstract long getFreeMemory();
public abstract String getRenderBinaryPath();
public String getCUDALib() {
return null;
}
public boolean getSupportHighPriority() {
return true;
}
public Process exec(List<String> command, Map<String, String> env) throws IOException {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
if (env != null) {
builder.environment().putAll(env);
}
return builder.start();
}
public boolean kill(Process proc) {
if (proc != null) {
proc.destroy();
return true;
}
return false;
}
public static OS getOS() {
if (instance == null) {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
instance = new Windows();
}
else if (os.contains("mac")) {
instance = new Mac();
}
else if (os.contains("nix") || os.contains("nux")) {
instance = new Linux();
}
else if (os.contains("freebsd")) {
instance = new FreeBSD();
}
}
return instance;
}
}

View File

@@ -1,228 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.sheepit.client.hardware.cpu.CPU;
import com.sheepit.client.os.windows.Kernel32Lib;
import com.sheepit.client.os.windows.WinProcess;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase.MEMORYSTATUSEX;
import com.sun.jna.platform.win32.WinReg;
public class Windows extends OS {
public String name() {
return "windows";
}
@Override
public String getRenderBinaryPath() {
return "rend.exe";
}
@Override
public CPU getCPU() {
CPU ret = new CPU();
try {
String[] identifier = java.lang.System.getenv("PROCESSOR_IDENTIFIER").split(" ");
for (int i = 0; i < (identifier.length - 1); i++) {
if (identifier[i].equals("Family")) {
ret.setFamily(identifier[i + 1]);
}
if (identifier[i].equals("Model")) {
ret.setModel(identifier[i + 1]);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
try {
final String cpuRegistryRoot = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor";
String[] processorIds = Advapi32Util.registryGetKeys(WinReg.HKEY_LOCAL_MACHINE, cpuRegistryRoot);
if (processorIds.length > 0) {
String processorId = processorIds[0];
String cpuRegistryPath = cpuRegistryRoot + "\\" + processorId;
ret.setName(Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, cpuRegistryPath, "ProcessorNameString").trim());
}
}
catch (Exception e) {
e.printStackTrace();
}
// override the arch
String env_arch = java.lang.System.getenv("PROCESSOR_ARCHITEW6432");
if (env_arch == null || env_arch.compareTo("") == 0) {
env_arch = java.lang.System.getenv("PROCESSOR_ARCHITECTURE");
}
if (env_arch.compareTo("AMD64") == 0) {
ret.setArch("64bit");
}
else {
ret.setArch("32bit");
}
return ret;
}
@Override
public long getMemory() {
try {
MEMORYSTATUSEX _memory = new MEMORYSTATUSEX();
if (Kernel32.INSTANCE.GlobalMemoryStatusEx(_memory)) {
return _memory.ullTotalPhys.longValue() / 1024; // size in KB
}
}
catch (Exception e) {
e.printStackTrace();
}
return 0;
}
@Override
public long getFreeMemory() {
try {
MEMORYSTATUSEX _memory = new MEMORYSTATUSEX();
if (Kernel32.INSTANCE.GlobalMemoryStatusEx(_memory)) {
return _memory.ullAvailPhys.longValue() / 1024; // size in KB
}
}
catch (Exception e) {
e.printStackTrace();
}
return -1;
}
@Override
public String getCUDALib() {
return "nvcuda";
}
@Override
public Process exec(List<String> command, Map<String, String> env) throws IOException {
// disable a popup because the renderer might crash (seg fault)
Kernel32Lib kernel32lib = null;
try {
kernel32lib = (Kernel32Lib) Native.loadLibrary(Kernel32Lib.path, Kernel32Lib.class);
kernel32lib.SetErrorMode(Kernel32Lib.SEM_NOGPFAULTERRORBOX);
}
catch (java.lang.UnsatisfiedLinkError e) {
System.out.println("OS.Windows::exec failed to load kernel32lib " + e);
}
catch (java.lang.ExceptionInInitializerError e) {
System.out.println("OS.Windows::exec failed to load kernel32lib " + e);
}
catch (Exception e) {
System.out.println("OS.Windows::exec failed to load kernel32lib " + e);
}
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
if (env != null) {
builder.environment().putAll(env);
}
Process p = builder.start();
WinProcess wproc = new WinProcess(p);
if (env != null) {
String priority = env.get("PRIORITY");
wproc.setPriority(getPriorityClass(Integer.parseInt(priority)));
}
else {
wproc.setPriority(WinProcess.PRIORITY_BELOW_NORMAL);
}
return p;
}
int getPriorityClass(int priority) {
int process_class = WinProcess.PRIORITY_IDLE;
switch (priority) {
case 19:
case 18:
case 17:
case 16:
case 15:
process_class = WinProcess.PRIORITY_IDLE;
break;
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7:
case 6:
case 5:
process_class = WinProcess.PRIORITY_BELOW_NORMAL;
break;
case 4:
case 3:
case 2:
case 1:
case 0:
case -1:
case -2:
case -3:
process_class = WinProcess.PRIORITY_NORMAL;
break;
case -4:
case -5:
case -6:
case -7:
case -8:
case -9:
process_class = WinProcess.PRIORITY_ABOVE_NORMAL;
break;
case -10:
case -11:
case -12:
case -13:
case -14:
process_class = WinProcess.PRIORITY_HIGH;
break;
case -15:
case -16:
case -17:
case -18:
case -19:
process_class = WinProcess.PRIORITY_REALTIME;
break;
}
return process_class;
}
@Override
public boolean kill(Process process) {
if (process != null) {
WinProcess wproc = new WinProcess(process);
wproc.kill();
return true;
}
return false;
}
}

View File

@@ -1,214 +0,0 @@
/* This file was originally taken from JNA project (https://github.com/twall/jna)
* filename: contrib/platform/src/com/sun/jna/platform/win32/Tlhelp32.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sheepit.client.os.windows;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public interface Kernel32Lib extends Library {
public static final String path = "kernel32";
/**
* Includes all heaps of the process specified in th32ProcessID in the snapshot. To enumerate the heaps, see
* Heap32ListFirst.
*/
WinDef.DWORD TH32CS_SNAPHEAPLIST = new WinDef.DWORD(0x00000001);
/**
* Includes all processes in the system in the snapshot. To enumerate the processes, see Process32First.
*/
WinDef.DWORD TH32CS_SNAPPROCESS = new WinDef.DWORD(0x00000002);
/**
* Includes all threads in the system in the snapshot. To enumerate the threads, see Thread32First.
*/
WinDef.DWORD TH32CS_SNAPTHREAD = new WinDef.DWORD(0x00000004);
/**
* Includes all modules of the process specified in th32ProcessID in the snapshot. To enumerate the modules, see
* Module32First. If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds.
*/
WinDef.DWORD TH32CS_SNAPMODULE = new WinDef.DWORD(0x00000008);
/**
* Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit
* process. This flag can be combined with TH32CS_SNAPMODULE or TH32CS_SNAPALL. If the function fails with
* ERROR_BAD_LENGTH, retry the function until it succeeds.
*/
WinDef.DWORD TH32CS_SNAPMODULE32 = new WinDef.DWORD(0x00000010);
/**
* Includes all processes and threads in the system, plus the heaps and modules of the process specified in th32ProcessID.
*/
WinDef.DWORD TH32CS_SNAPALL = new WinDef.DWORD((TH32CS_SNAPHEAPLIST.intValue() | TH32CS_SNAPPROCESS.intValue() | TH32CS_SNAPTHREAD.intValue() | TH32CS_SNAPMODULE.intValue()));
/**
* Indicates that the snapshot handle is to be inheritable.
*/
WinDef.DWORD TH32CS_INHERIT = new WinDef.DWORD(0x80000000);
/**
* The system does not display the Windows Error Reporting dialog.
* See: http://msdn.microsoft.com/en-us/library/ms680621%28VS.85%29.aspx
*/
WinDef.DWORD SEM_NOGPFAULTERRORBOX = new WinDef.DWORD(0x0002);
/**
* Describes an entry from a list of the processes residing in the system address space when a snapshot was taken.
*/
public static class PROCESSENTRY32 extends Structure {
public static class ByReference extends PROCESSENTRY32 implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer memory) {
super(memory);
}
}
public PROCESSENTRY32() {
dwSize = new WinDef.DWORD(size());
}
public PROCESSENTRY32(Pointer memory) {
useMemory(memory);
read();
}
/**
* The size of the structure, in bytes. Before calling the Process32First function, set this member to
* sizeof(PROCESSENTRY32). If you do not initialize dwSize, Process32First fails.
*/
public WinDef.DWORD dwSize;
/**
* This member is no longer used and is always set to zero.
*/
public WinDef.DWORD cntUsage;
/**
* The process identifier.
*/
public WinDef.DWORD th32ProcessID;
/**
* This member is no longer used and is always set to zero.
*/
public BaseTSD.ULONG_PTR th32DefaultHeapID;
/**
* This member is no longer used and is always set to zero.
*/
public WinDef.DWORD th32ModuleID;
/**
* The number of execution threads started by the process.
*/
public WinDef.DWORD cntThreads;
/**
* The identifier of the process that created this process (its parent process).
*/
public WinDef.DWORD th32ParentProcessID;
/**
* The base priority of any threads created by this process.
*/
public WinDef.LONG pcPriClassBase;
/**
* This member is no longer used, and is always set to zero.
*/
public WinDef.DWORD dwFlags;
/**
* The name of the executable file for the process. To retrieve the full path to the executable file, call the
* Module32First function and check the szExePath member of the MODULEENTRY32 structure that is returned.
* However, if the calling process is a 32-bit process, you must call the QueryFullProcessImageName function to
* retrieve the full path of the executable file for a 64-bit process.
*/
public char[] szExeFile = new char[WinDef.MAX_PATH];
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "dwSize", "cntUsage", "th32ProcessID", "th32DefaultHeapID", "th32ModuleID", "cntThreads", "th32ParentProcessID", "pcPriClassBase", "dwFlags", "szExeFile" });
}
}
/**
* Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes.
*
* @param dwFlags The portions of the system to be included in the snapshot.
* @param th32ProcessID The process identifier of the process to be included in the snapshot. This parameter can be zero to indicate
* the current process. This parameter is used when the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE,
* TH32CS_SNAPMODULE32, or TH32CS_SNAPALL value is specified. Otherwise, it is ignored and all processes are
* included in the snapshot.
* <p/>
* If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last
* error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from opening them.
* <p/>
* If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the
* last error code is ERROR_PARTIAL_COPY (299).
* @return If the function succeeds, it returns an open handle to the specified snapshot.
* <p/>
* If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
* Possible error codes include ERROR_BAD_LENGTH.
*/
public WinNT.HANDLE CreateToolhelp32Snapshot(WinDef.DWORD dwFlags, WinDef.DWORD th32ProcessID);
/**
* Retrieves information about the first process encountered in a system snapshot.
*
* @param hSnapshot A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function.
* @param lppe A pointer to a PROCESSENTRY32 structure. It contains process information such as the name of the
* executable file, the process identifier, and the process identifier of the parent process.
* @return Returns TRUE if the first entry of the process list has been copied to the buffer or FALSE otherwise. The
* ERROR_NO_MORE_FILES error value is returned by the GetLastError function if no processes exist or the snapshot
* does not contain process information.
*/
public boolean Process32First(WinNT.HANDLE hSnapshot, Kernel32Lib.PROCESSENTRY32.ByReference lppe);
/**
* Retrieves information about the next process recorded in a system snapshot.
*
* @param hSnapshot A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function.
* @param lppe A pointer to a PROCESSENTRY32 structure.
* @return Returns TRUE if the next entry of the process list has been copied to the buffer or FALSE otherwise. The
* ERROR_NO_MORE_FILES error value is returned by the GetLastError function if no processes exist or the snapshot
* does not contain process information.
*/
public boolean Process32Next(WinNT.HANDLE hSnapshot, Kernel32Lib.PROCESSENTRY32.ByReference lppe);
public boolean SetPriorityClass(HANDLE hProcess, int dwPriorityClass);
/**
* Controls whether the system will handle the specified types of serious errors or whether the process will handle them.
* See: http://msdn.microsoft.com/en-us/library/ms680621%28VS.85%29.aspx
*
* @param uMode The process error mode. This parameter can be one or more of the following values.
*/
public int SetErrorMode(DWORD uMode);
}

View File

@@ -1,194 +0,0 @@
/*
* Copyright (C) 2013 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.os.windows;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT;
public class WinProcess {
public static final int PRIORITY_IDLE = 0x40;
public static final int PRIORITY_BELOW_NORMAL = 0x4000;
public static final int PRIORITY_NORMAL = 0x20;
public static final int PRIORITY_ABOVE_NORMAL = 0x8000;
public static final int PRIORITY_HIGH = 0x80;
public static final int PRIORITY_REALTIME = 0x100;
private WinNT.HANDLE handle;
private int pid;
Kernel32Lib kernel32lib;
public WinProcess() {
this.handle = null;
this.pid = -1;
this.kernel32lib = null;
try {
this.kernel32lib = (Kernel32Lib) Native.loadLibrary(Kernel32Lib.path, Kernel32Lib.class);
}
catch (java.lang.UnsatisfiedLinkError e) {
System.out.println("WinProcess::construct " + e);
}
catch (java.lang.ExceptionInInitializerError e) {
System.out.println("WinProcess::construct " + e);
}
catch (Exception e) {
System.out.println("WinProcess::construct " + e);
}
}
private static boolean processHasGetPid() {
try {
if (Process.class.getMethod("pid", null) != null) {
return true;
}
}
catch (NoSuchMethodException | SecurityException e) {
}
return false;
}
private static long getPid(Process process) {
try {
return (long) Process.class.getMethod("pid", null).invoke(process, null);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
}
return 0;
}
private static WinNT.HANDLE getHandleByPid(int pid_) throws IOException {
WinNT.HANDLE handle = Kernel32.INSTANCE.OpenProcess(0x0400 | // PROCESS_QUERY_INFORMATION
0x0800 | // PROCESS_SUSPEND_RESUME
0x0001 | // PROCESS_TERMINATE
0x0200 | // PROCESS_SET_INFORMATION
0x00100000, // SYNCHRONIZE
false, pid_);
if (handle == null) {
throw new IOException("OpenProcess failed: " + Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError()) + " (pid: " + pid_ + ")");
}
return handle;
}
public WinProcess(Process process) {
this();
if (processHasGetPid()) {
int _pid = (int) getPid(process);
try {
this.handle = getHandleByPid(_pid);
}
catch (IOException e) {
}
this.pid = _pid;
}
else {
try {
Field f = process.getClass().getDeclaredField("handle");
f.setAccessible(true);
long val = f.getLong(process);
this.handle = new WinNT.HANDLE();
this.handle.setPointer(Pointer.createConstant(val));
this.pid = Kernel32.INSTANCE.GetProcessId(this.handle);
}
catch (NoSuchFieldException e) {
}
catch (IllegalArgumentException e) {
}
catch (IllegalAccessException e) {
}
}
}
public WinProcess(int pid_) throws IOException {
this();
this.handle = getHandleByPid(pid_);
this.pid = pid_;
}
@Override
protected void finalize() throws Throwable {
if (this.handle != null) {
// Kernel32.INSTANCE.CloseHandle(this.handle); // do not close the handle because the parent Process object might still be alive
this.handle = null;
}
this.pid = -1;
}
public boolean kill() {
try {
List<WinProcess> children = this.getChildren();
this.terminate();
for (WinProcess child : children) {
child.kill();
}
}
catch (IOException e) {
e.printStackTrace();
}
return false;
}
public boolean setPriority(int priority) {
return this.kernel32lib.SetPriorityClass(this.handle, priority);
}
private void terminate() {
Kernel32.INSTANCE.TerminateProcess(this.handle, 0);
Kernel32.INSTANCE.CloseHandle(this.handle); // we are sure that the parent Process object is dead
}
private List<WinProcess> getChildren() throws IOException {
ArrayList<WinProcess> result = new ArrayList<WinProcess>();
WinNT.HANDLE hSnap = this.kernel32lib.CreateToolhelp32Snapshot(Kernel32Lib.TH32CS_SNAPPROCESS, new DWORD(0));
Kernel32Lib.PROCESSENTRY32.ByReference ent = new Kernel32Lib.PROCESSENTRY32.ByReference();
if (!this.kernel32lib.Process32First(hSnap, ent)) {
return result;
}
do {
if (ent.th32ParentProcessID.intValue() == this.pid) {
try {
result.add(new WinProcess(ent.th32ProcessID.intValue()));
}
catch (IOException e) {
System.err.println("WinProcess::getChildren, IOException " + e);
}
}
}
while (this.kernel32lib.Process32Next(hSnap, ent));
Kernel32.INSTANCE.CloseHandle(hSnap);
return result;
}
public String toString() {
return "WinProcess(pid: " + this.pid + ", handle " + this.handle + ")";
}
}

View File

@@ -1,346 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import java.awt.AWTException;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import com.sheepit.client.Client;
import com.sheepit.client.Configuration;
import com.sheepit.client.Gui;
import com.sheepit.client.Stats;
import com.sheepit.client.standalone.swing.activity.Settings;
import com.sheepit.client.standalone.swing.activity.Working;
public class GuiSwing extends JFrame implements Gui {
public static final String type = "swing";
public enum ActivityType {
WORKING, SETTINGS
}
private SystemTray sysTray;
private JPanel panel;
private Working activityWorking;
private Settings activitySettings;
private TrayIcon trayIcon;
private boolean useSysTray;
private String title;
private int framesRendered;
private boolean waitingForAuthentication;
private Client client;
private ThreadClient threadClient;
public GuiSwing(boolean useSysTray_, String title_) {
framesRendered = 0;
useSysTray = useSysTray_;
title = title_;
waitingForAuthentication = true;
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (activityWorking != null) {
activityWorking.updateTime();
}
}
}, 2 * 1000, 2 * 1000);
}
@Override
public void start() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
if (useSysTray) {
try {
sysTray = SystemTray.getSystemTray();
if (SystemTray.isSupported()) {
addWindowStateListener(new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
if (e.getNewState() == ICONIFIED) {
hideToTray();
}
}
});
}
}
catch (UnsupportedOperationException e) {
sysTray = null;
}
}
URL iconUrl = getClass().getResource("/icon.png");
if (iconUrl != null) {
ImageIcon img = new ImageIcon(iconUrl);
setIconImage(img.getImage());
}
setTitle(title);
setSize(520, 760);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridBagLayout());
setContentPane(this.panel);
panel.setBorder(new EmptyBorder(20, 20, 20, 20));
activityWorking = new Working(this);
activitySettings = new Settings(this);
this.showActivity(ActivityType.SETTINGS);
while (waitingForAuthentication) {
try {
synchronized (this) {
wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void stop() {
System.exit(0);
}
@Override
public void status(String msg_) {
if (activityWorking != null) {
this.activityWorking.setStatus(msg_);
}
}
@Override
public void setRenderingProjectName(String name_) {
if (activityWorking != null) {
this.activityWorking.setRenderingProjectName(name_);
}
}
@Override
public void error(String msg_) {
status(msg_);
}
@Override
public void setRemainingTime(String time_) {
if (activityWorking != null) {
this.activityWorking.setRemainingTime(time_);
}
}
@Override
public void setRenderingTime(String time_) {
if (activityWorking != null) {
this.activityWorking.setRenderingTime(time_);
}
}
@Override
public void AddFrameRendered() {
framesRendered++;
if (activityWorking != null) {
this.activityWorking.setRenderedFrame(framesRendered);
}
else {
System.out.println("GuiSwing::AddFrameRendered() error: no working activity");
}
}
@Override
public void displayStats(Stats stats) {
if (activityWorking != null) {
this.activityWorking.displayStats(stats);
}
}
@Override
public Client getClient() {
return client;
}
@Override
public void setClient(Client cli) {
client = cli;
}
@Override
public void setComputeMethod(String computeMethod) {
this.activityWorking.setComputeMethod(computeMethod);
}
public Configuration getConfiguration() {
return client.getConfiguration();
}
public void setCredentials(String contentLogin, String contentPassword) {
client.getConfiguration().setLogin(contentLogin);
client.getConfiguration().setPassword(contentPassword);
waitingForAuthentication = false;
synchronized (this) {
notifyAll();
}
if (threadClient == null || threadClient.isAlive() == false) {
threadClient = new ThreadClient();
threadClient.start();
}
showActivity(ActivityType.WORKING);
}
public void showActivity(ActivityType type) {
panel.removeAll();
panel.doLayout();
if (type == ActivityType.WORKING) {
activityWorking.show();
}
else if (type == ActivityType.SETTINGS) {
activitySettings.show();
}
setVisible(true);
panel.repaint();
}
public void hideToTray() {
if (sysTray == null || SystemTray.isSupported() == false) {
System.out.println("GuiSwing::hideToTray SystemTray not supported!");
return;
}
try {
trayIcon = getTrayIcon();
sysTray.add(trayIcon);
}
catch (AWTException e) {
System.out.println("GuiSwing::hideToTray an error occured while trying to add system tray icon (exception: " + e + ")");
return;
}
setVisible(false);
}
public void restoreFromTray() {
if (sysTray != null && SystemTray.isSupported()) {
sysTray.remove(trayIcon);
setVisible(true);
setExtendedState(getExtendedState() & ~JFrame.ICONIFIED & JFrame.NORMAL); // for toFront and requestFocus to actually work
toFront();
requestFocus();
}
}
public TrayIcon getTrayIcon() {
final PopupMenu trayMenu = new PopupMenu();
URL iconUrl = getClass().getResource("/icon.png");
Image img = Toolkit.getDefaultToolkit().getImage(iconUrl);
final TrayIcon icon = new TrayIcon(img);
MenuItem exit = new MenuItem("Exit");
exit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
trayMenu.add(exit);
MenuItem open = new MenuItem("Open...");
open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
restoreFromTray();
}
});
trayMenu.add(open);
MenuItem settings = new MenuItem("Settings...");
settings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
restoreFromTray();
showActivity(ActivityType.SETTINGS);
}
});
trayMenu.add(settings);
icon.setPopupMenu(trayMenu);
icon.setImageAutoSize(true);
icon.setToolTip("SheepIt! Client");
icon.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
restoreFromTray();
}
});
return icon;
}
public class ThreadClient extends Thread {
@Override
public void run() {
if (GuiSwing.this.client != null) {
GuiSwing.this.client.run();
}
}
}
}

View File

@@ -1,148 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import com.sheepit.client.Client;
import com.sheepit.client.Gui;
import com.sheepit.client.Job;
import com.sheepit.client.Log;
import com.sheepit.client.Stats;
import com.sheepit.client.standalone.text.CLIInputActionHandler;
import com.sheepit.client.standalone.text.CLIInputObserver;
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class GuiText implements Gui {
public static final String type = "text";
private int framesRendered;
private int sigIntCount = 0;
private Log log;
private Client client;
public GuiText() {
this.framesRendered = 0;
this.log = Log.getInstance(null);
}
@Override
public void start() {
if (client != null) {
CLIInputObserver cli_input_observer = new CLIInputObserver(client);
cli_input_observer.addListener(new CLIInputActionHandler());
Thread cli_input_observer_thread = new Thread(cli_input_observer);
cli_input_observer_thread.start();
Signal.handle(new Signal("INT"), new SignalHandler() {
@Override
public void handle(Signal signal) {
sigIntCount++;
if (sigIntCount == 4) {
// This is only for ugly issues that might occur
System.out.println("WARNING: Hitting Ctrl-C again will force close the application.");
}
else if (sigIntCount == 5) {
Signal.raise(new Signal("INT"));
Runtime.getRuntime().halt(0);
}
else if (client.isRunning() && client.isSuspended() == false) {
client.askForStop();
System.out.println("Will exit after current frame... Press Ctrl+C again to exit now.");
}
else {
client.stop();
GuiText.this.stop();
}
}
});
client.run();
client.stop();
}
}
@Override
public void stop() {
Runtime.getRuntime().halt(0);
}
@Override
public void status(String msg_) {
System.out.println(msg_);
log.debug("GUI " + msg_);
}
@Override
public void error(String err_) {
System.out.println("Error " + err_);
log.error("Error " + err_);
}
@Override
public void AddFrameRendered() {
this.framesRendered += 1;
System.out.println("Frames rendered: " + this.framesRendered);
}
@Override
public void displayStats(Stats stats) {
System.out.println("Frames remaining: " + stats.getRemainingFrame());
System.out.println("Credits earned: " + stats.getCreditsEarnedDuringSession());
}
@Override
public void setRenderingProjectName(String name_) {
if (name_ != null && name_.isEmpty() == false) {
System.out.println("Rendering project \"" + name_ + "\"");
}
}
@Override
public void setRemainingTime(String time_) {
System.out.println("Rendering (remaining " + time_ + ")");
}
@Override
public void setRenderingTime(String time_) {
System.out.println("Rendering " + time_);
}
@Override
public void setClient(Client cli) {
client = cli;
}
@Override
public void setComputeMethod(String computeMethod) {
System.out.println("Compute method: " + computeMethod);
}
@Override
public Client getClient() {
return client;
}
}

View File

@@ -1,171 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import com.sheepit.client.Client;
import com.sheepit.client.Gui;
import com.sheepit.client.Job;
import com.sheepit.client.Stats;
import com.sheepit.client.standalone.text.CLIInputActionHandler;
import com.sheepit.client.standalone.text.CLIInputObserver;
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class GuiTextOneLine implements Gui {
public static final String type = "oneLine";
private String project;
private int rendered;
private int remaining;
private String creditsEarned;
private int sigIntCount = 0;
private String computeMethod;
private String status;
private String line;
private boolean exiting = false;
private Client client;
public GuiTextOneLine() {
project = "";
rendered = 0;
remaining = 0;
creditsEarned = null;
status = "";
computeMethod = "";
line = "";
}
@Override
public void start() {
if (client != null) {
CLIInputObserver cli_input_observer = new CLIInputObserver(client);
cli_input_observer.addListener(new CLIInputActionHandler());
Thread cli_input_observer_thread = new Thread(cli_input_observer);
cli_input_observer_thread.start();
Signal.handle(new Signal("INT"), new SignalHandler() {
@Override
public void handle(Signal signal) {
sigIntCount++;
if (sigIntCount == 5) {
Signal.raise(new Signal("INT"));
Runtime.getRuntime().halt(0);
}
else if (client.isRunning() && client.isSuspended() == false) {
client.askForStop();
exiting = true;
}
else {
client.stop();
GuiTextOneLine.this.stop();
}
}
});
client.run();
client.stop();
}
}
@Override
public void stop() {
Runtime.getRuntime().halt(0);
}
@Override
public void status(String msg_) {
status = msg_;
updateLine();
}
@Override
public void setRenderingProjectName(String name_) {
if (name_ == null || name_.isEmpty()) {
project = "";
}
else {
project = "Project \"" + name_ + "\" |";
}
updateLine();
}
@Override
public void error(String msg_) {
status = "Error " + msg_;
updateLine();
}
@Override
public void AddFrameRendered() {
rendered += 1;
updateLine();
}
@Override
public void displayStats(Stats stats) {
remaining = stats.getRemainingFrame();
creditsEarned = String.valueOf(stats.getCreditsEarnedDuringSession());
updateLine();
}
@Override
public void setRemainingTime(String time_) {
status = "(remaining " + time_ + ")";
updateLine();
}
@Override
public void setRenderingTime(String time_) {
status = "Rendering " + time_;
updateLine();
}
@Override
public void setClient(Client cli) {
client = cli;
}
@Override
public void setComputeMethod(String computeMethod_) {
computeMethod = computeMethod_;
}
@Override
public Client getClient() {
return client;
}
private void updateLine() {
int charToRemove = line.length();
System.out.print("\r");
line = String.format("Frames: %d Points: %s | %s %s %s", rendered, creditsEarned != null ? creditsEarned : "unknown", project, computeMethod, status + (exiting ? " (Exiting after this frame)" : ""));
System.out.print(line);
for (int i = line.length(); i <= charToRemove; i++) {
System.out.print(" ");
}
}
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (C) 2017 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import java.util.List;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
import com.sheepit.client.Configuration;
import com.sheepit.client.hardware.gpu.GPU;
import com.sheepit.client.hardware.gpu.GPUDevice;
public class ListGpuParameterHandler<T> extends OptionHandler<T> {
public ListGpuParameterHandler(CmdLineParser parser, OptionDef option, Setter<? super T> setter) {
super(parser, option, setter);
}
@Override
public int parseArguments(Parameters params) throws CmdLineException {
List<GPUDevice> gpus = GPU.listDevices(new Configuration(null, null, null));
if (gpus != null) {
for (GPUDevice gpu : gpus) {
System.out.println("Id : " + gpu.getId());
System.out.println("Model : " + gpu.getModel());
System.out.println("Memory, MB: " + (int) (gpu.getMemory() / (1024 * 1024)));
System.out.println();
}
}
System.exit(0);
return 0;
}
@Override
public String getDefaultMetaVariable() {
return null;
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
import com.sheepit.client.Configuration;
public class VersionParameterHandler<T> extends OptionHandler<T> {
public VersionParameterHandler(CmdLineParser parser, OptionDef option, Setter<? super T> setter) {
super(parser, option, setter);
}
@Override
public int parseArguments(Parameters params) throws CmdLineException {
Configuration config = new Configuration(null, "", "");
System.out.println("Version: " + config.getJarVersion());
System.exit(0);
return 0;
}
@Override
public String getDefaultMetaVariable() {
return null;
}
}

View File

@@ -1,332 +0,0 @@
/*
* Copyright (C) 2010-2014 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import static org.kohsuke.args4j.ExampleMode.REQUIRED;
import org.kohsuke.args4j.Option;
import java.io.File;
import java.net.MalformedURLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedList;
import com.sheepit.client.Client;
import com.sheepit.client.Configuration;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.Gui;
import com.sheepit.client.Log;
import com.sheepit.client.Pair;
import com.sheepit.client.SettingsLoader;
import com.sheepit.client.ShutdownHook;
import com.sheepit.client.Utils;
import com.sheepit.client.hardware.gpu.GPU;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.hardware.gpu.nvidia.Nvidia;
import com.sheepit.client.hardware.gpu.opencl.OpenCL;
import com.sheepit.client.network.Proxy;
public class Worker {
@Option(name = "-server", usage = "Render-farm server, default https://client.sheepit-renderfarm.com", metaVar = "URL", required = false)
private String server = "https://client.sheepit-renderfarm.com";
@Option(name = "-login", usage = "User's login", metaVar = "LOGIN", required = false)
private String login = "";
@Option(name = "-password", usage = "User's password", metaVar = "PASSWORD", required = false)
private String password = "";
@Option(name = "-cache-dir", usage = "Cache/Working directory. Caution, everything in it not related to the render-farm will be removed", metaVar = "/tmp/cache", required = false)
private String cache_dir = null;
@Option(name = "-max-uploading-job", usage = "", metaVar = "1", required = false)
private int max_upload = -1;
@Option(name = "-gpu", usage = "Name of the GPU used for the render, for example CUDA_0 for Nvidia or OPENCL_0 for AMD/Intel card", metaVar = "CUDA_0", required = false)
private String gpu_device = null;
@Option(name = "--no-gpu", usage = "Don't detect GPUs", required = false)
private boolean no_gpu_detection = false;
@Option(name = "-compute-method", usage = "CPU: only use cpu, GPU: only use gpu, CPU_GPU: can use cpu and gpu (not at the same time) if -gpu is not use it will not use the gpu", metaVar = "CPU", required = false)
private String method = null;
@Option(name = "-cores", usage = "Number of cores/threads to use for the render", metaVar = "3", required = false)
private int nb_cores = -1;
@Option(name = "-memory", usage = "Maximum memory allow to be used by renderer, number with unit (800M, 2G, ...)", required = false)
private String max_ram = null;
@Option(name = "-rendertime", usage = "Maximum time allow for each frame (in minute)", required = false)
private int max_rendertime = -1;
@Option(name = "--verbose", usage = "Display log", required = false)
private boolean print_log = false;
@Option(name = "-request-time", usage = "H1:M1-H2:M2,H3:M3-H4:M4 Use the 24h format. For example to request job between 2am-8.30am and 5pm-11pm you should do --request-time 2:00-8:30,17:00-23:00 Caution, it's the requesting job time to get a project not the working time", metaVar = "2:00-8:30,17:00-23:00", required = false)
private String request_time = null;
@Option(name = "-proxy", usage = "URL of the proxy", metaVar = "http://login:password@host:port", required = false)
private String proxy = null;
@Option(name = "-extras", usage = "Extras data push on the authentication request", required = false)
private String extras = null;
@Option(name = "-ui", usage = "Specify the user interface to use, default '" + GuiSwing.type + "', available '" + GuiTextOneLine.type + "', '" + GuiText.type + "', '" + GuiSwing.type + "' (graphical)", required = false)
private String ui_type = null;
@Option(name = "-config", usage = "Specify the configuration file", required = false)
private String config_file = null;
@Option(name = "--version", usage = "Display application version", required = false, handler = VersionParameterHandler.class)
private VersionParameterHandler versionHandler;
@Option(name = "--show-gpu", usage = "Print available CUDA devices and exit", required = false, handler = ListGpuParameterHandler.class)
private ListGpuParameterHandler listGpuParameterHandler;
@Option(name = "--no-systray", usage = "Don't use systray", required = false)
private boolean no_systray = false;
@Option(name = "-priority", usage = "Set render process priority (19 lowest to -19 highest)", required = false)
private int priority = 19;
@Option(name = "-title", usage = "Custom title for the GUI Client", required = false)
private String title = "SheepIt Render Farm";
public static void main(String[] args) {
new Worker().doMain(args);
}
public void doMain(String[] args) {
CmdLineParser parser = new CmdLineParser(this);
try {
parser.parseArgument(args);
}
catch (CmdLineException e) {
System.err.println(e.getMessage());
System.err.println("Usage: ");
parser.printUsage(System.err);
System.err.println();
System.err.println("Example: java " + this.getClass().getName() + " " + parser.printExample(REQUIRED));
return;
}
ComputeType compute_method = ComputeType.CPU;
Configuration config = new Configuration(null, login, password);
config.setPrintLog(print_log);
config.setUsePriority(priority);
config.setDetectGPUs(! no_gpu_detection);
if (cache_dir != null) {
File a_dir = new File(cache_dir);
a_dir.mkdirs();
if (a_dir.isDirectory() && a_dir.canWrite()) {
config.setCacheDir(a_dir);
}
}
if (max_upload != -1) {
if (max_upload <= 0) {
System.err.println("Error: max upload should be a greater than zero");
return;
}
config.setMaxUploadingJob(max_upload);
}
if (gpu_device != null) {
if (gpu_device.startsWith(Nvidia.TYPE) == false && gpu_device.startsWith(OpenCL.TYPE) == false) {
System.err.println("GPU_ID should look like '" + Nvidia.TYPE + "_X' or '" + OpenCL.TYPE + "_X' more info on gpus available with --show-gpu");
System.exit(2);
}
String family = "";
if (gpu_device.startsWith(Nvidia.TYPE) == false && gpu_device.startsWith(OpenCL.TYPE) == false) {
System.err.println("GPU_ID should look like '" + Nvidia.TYPE + "_X' or '" + OpenCL.TYPE + "_X' more info on gpus available with --show-gpu");
return;
}
GPUDevice gpu = GPU.getGPUDevice(gpu_device);
if (gpu == null) {
System.err.println("GPU unknown, list of available gpus can be display with --show-gpu");
System.exit(2);
}
config.setGPUDevice(gpu);
}
if (request_time != null) {
String[] intervals = request_time.split(",");
if (intervals != null) {
config.setRequestTime(new LinkedList<Pair<Calendar, Calendar>>());
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
for (String interval : intervals) {
String[] times = interval.split("-");
if (times != null && times.length == 2) {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
try {
start.setTime(timeFormat.parse(times[0]));
end.setTime(timeFormat.parse(times[1]));
}
catch (ParseException e) {
System.err.println("Error: wrong format in request time");
System.exit(2);
}
if (start.before(end)) {
config.getRequestTime().add(new Pair<Calendar, Calendar>(start, end));
}
else {
System.err.println("Error: wrong request time " + times[0] + " is after " + times[1]);
System.exit(2);
}
}
}
}
}
if (nb_cores < -1 || nb_cores == 0) { // -1 is the default
System.err.println("Error: use-number-core should be a greater than zero");
return;
}
else {
config.setNbCores(nb_cores);
}
if (max_ram != null) {
try {
config.setMaxMemory(Utils.parseNumber(max_ram) / 1000); // internal value are in kB
}
catch (java.lang.IllegalStateException e) {
System.err.println("Error: failed to parse memory parameter");
return;
}
}
if (max_rendertime > 0) {
config.setMaxRenderTime(max_rendertime * 60);
}
if (method != null) {
try {
compute_method = ComputeType.valueOf(method);
}
catch (IllegalArgumentException e) {
System.err.println("Error: compute-method unknown");
System.exit(2);
}
}
else {
if (config.getGPUDevice() == null) {
compute_method = ComputeType.CPU;
}
else {
compute_method = ComputeType.GPU;
}
}
if (proxy != null) {
try {
Proxy.set(proxy);
}
catch (MalformedURLException e) {
System.err.println("Error: wrong url for proxy");
System.err.println(e);
System.exit(2);
}
}
if (extras != null) {
config.setExtras(extras);
}
if (compute_method == ComputeType.CPU && config.getGPUDevice() != null) {
System.err.println("You choose to only use the CPU but a GPU was also provided. You can not do both.");
System.err.println("Aborting");
System.exit(2);
}
else if (compute_method == ComputeType.CPU_GPU && config.getGPUDevice() == null) {
System.err.println("You choose to only use the CPU and GPU but no GPU device was provided.");
System.err.println("Aborting");
System.exit(2);
}
else if (compute_method == ComputeType.GPU && config.getGPUDevice() == null) {
System.err.println("You choose to only use the GPU but no GPU device was provided.");
System.err.println("Aborting");
System.exit(2);
}
else if (compute_method == ComputeType.CPU) {
config.setGPUDevice(null); // remove the GPU
}
config.setComputeMethod(compute_method);
if (ui_type != null) {
config.setUIType(ui_type);
}
if (config_file != null) {
if (new File(config_file).exists() == false) {
System.err.println("Configuration file not found.");
System.err.println("Aborting");
System.exit(2);
}
config.setConfigFilePath(config_file);
new SettingsLoader(config_file).merge(config);
}
Log.getInstance(config).debug("client version " + config.getJarVersion());
Gui gui;
String type = config.getUIType();
if (type == null) {
type = "swing";
}
switch (type) {
case GuiTextOneLine.type:
if (config.isPrintLog()) {
System.out.println("OneLine UI can not be used if verbose mode is enabled");
System.exit(2);
}
gui = new GuiTextOneLine();
break;
case GuiText.type:
gui = new GuiText();
break;
default:
case GuiSwing.type:
if (java.awt.GraphicsEnvironment.isHeadless()) {
System.out.println("Graphical ui can not be launch.");
System.out.println("You should set a DISPLAY or use a text ui (with -ui " + GuiTextOneLine.type + " or -ui " + GuiText.type + ").");
System.exit(3);
}
gui = new GuiSwing(no_systray == false, title);
break;
}
Client cli = new Client(gui, config, server);
gui.setClient(cli);
ShutdownHook hook = new ShutdownHook(cli);
hook.attachShutDownHook();
gui.start();
}
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.swing.activity;
public interface Activity {
public void show();
}

View File

@@ -1,656 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.swing.activity;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import com.sheepit.client.Configuration;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.SettingsLoader;
import com.sheepit.client.hardware.cpu.CPU;
import com.sheepit.client.hardware.gpu.GPU;
import com.sheepit.client.hardware.gpu.GPUDevice;
import com.sheepit.client.network.Proxy;
import com.sheepit.client.os.OS;
import com.sheepit.client.standalone.GuiSwing;
import com.sheepit.client.standalone.swing.components.CollapsibleJPanel;
public class Settings implements Activity {
private static final String DUMMY_CACHE_DIR = "Auto detected";
private GuiSwing parent;
private JTextField login;
private JPasswordField password;
private JLabel cacheDirText;
private File cacheDir;
private JFileChooser cacheDirChooser;
private JCheckBox useCPU;
private List<JCheckBoxGPU> useGPUs;
private JSlider cpuCores;
private JSlider ram;
private JSpinner renderTime;
private JSlider priority;
private JTextField proxy;
private JTextField hostname;
private JCheckBox saveFile;
private JCheckBox autoSignIn;
JButton saveButton;
private boolean haveAutoStarted;
private JTextField tileSizeValue;
private JLabel tileSizeLabel;
private JCheckBox customTileSize;
public Settings(GuiSwing parent_) {
parent = parent_;
cacheDir = null;
useGPUs = new LinkedList<JCheckBoxGPU>();
haveAutoStarted = false;
}
@Override
public void show() {
Configuration config = parent.getConfiguration();
new SettingsLoader(config.getConfigFilePath()).merge(config);
List<GPUDevice> gpus = GPU.listDevices(config);
GridBagConstraints constraints = new GridBagConstraints();
int currentRow = 0;
ImageIcon image = new ImageIcon(getClass().getResource("/title.png"));
constraints.fill = GridBagConstraints.CENTER;
JLabel labelImage = new JLabel(image);
constraints.gridwidth = 2;
constraints.gridx = 0;
constraints.gridy = currentRow;
parent.getContentPane().add(labelImage, constraints);
++currentRow;
// authentication
CollapsibleJPanel authentication_panel = new CollapsibleJPanel(new GridLayout(2, 2));
authentication_panel.setBorder(BorderFactory.createTitledBorder("Authentication"));
JLabel loginLabel = new JLabel("Username:");
login = new JTextField();
login.setText(parent.getConfiguration().getLogin());
login.setColumns(20);
login.addKeyListener(new CheckCanStart());
JLabel passwordLabel = new JLabel("Password:");
password = new JPasswordField();
password.setText(parent.getConfiguration().getPassword());
password.setColumns(10);
password.addKeyListener(new CheckCanStart());
authentication_panel.add(loginLabel);
authentication_panel.add(login);
authentication_panel.add(passwordLabel);
authentication_panel.add(password);
constraints.gridx = 0;
constraints.gridy = currentRow;
constraints.fill = GridBagConstraints.HORIZONTAL;
parent.getContentPane().add(authentication_panel, constraints);
// directory
CollapsibleJPanel directory_panel = new CollapsibleJPanel(new GridLayout(1, 3));
directory_panel.setBorder(BorderFactory.createTitledBorder("Cache"));
JLabel cacheLabel = new JLabel("Working directory:");
directory_panel.add(cacheLabel);
String destination = DUMMY_CACHE_DIR;
if (config.isUserHasSpecifiedACacheDir()) {
destination = config.getCacheDirForSettings().getName();
}
JPanel cacheDirWrapper = new JPanel();
cacheDirWrapper.setLayout(new BoxLayout(cacheDirWrapper, BoxLayout.LINE_AXIS));
cacheDirText = new JLabel(destination);
cacheDirWrapper.add(cacheDirText);
cacheDirWrapper.add(Box.createHorizontalGlue());
cacheDirChooser = new JFileChooser();
cacheDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
JButton openButton = new JButton("...");
openButton.addActionListener(new ChooseFileAction());
cacheDirWrapper.add(openButton);
directory_panel.add(cacheDirWrapper);
currentRow++;
constraints.gridx = 0;
constraints.gridy = currentRow;
constraints.gridwidth = 2;
parent.getContentPane().add(directory_panel, constraints);
// compute devices
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints compute_devices_constraints = new GridBagConstraints();
CollapsibleJPanel compute_devices_panel = new CollapsibleJPanel(gridbag);
compute_devices_panel.setBorder(BorderFactory.createTitledBorder("Compute devices"));
ComputeType method = config.getComputeMethod();
useCPU = new JCheckBox("CPU");
boolean gpuChecked = false;
if (method == ComputeType.CPU_GPU) {
useCPU.setSelected(true);
gpuChecked = true;
}
else if (method == ComputeType.CPU) {
useCPU.setSelected(true);
gpuChecked = false;
}
else if (method == ComputeType.GPU) {
useCPU.setSelected(false);
gpuChecked = true;
}
useCPU.addActionListener(new CpuChangeAction());
compute_devices_constraints.gridx = 1;
compute_devices_constraints.gridy = 0;
compute_devices_constraints.fill = GridBagConstraints.BOTH;
compute_devices_constraints.weightx = 1.0;
compute_devices_constraints.weighty = 1.0;
gridbag.setConstraints(useCPU, compute_devices_constraints);
compute_devices_panel.add(useCPU);
for (GPUDevice gpu : gpus) {
JCheckBoxGPU gpuCheckBox = new JCheckBoxGPU(gpu);
gpuCheckBox.setToolTipText(gpu.getId());
if (gpuChecked) {
GPUDevice config_gpu = config.getGPUDevice();
if (config_gpu != null && config_gpu.getId().equals(gpu.getId())) {
gpuCheckBox.setSelected(gpuChecked);
}
}
gpuCheckBox.addActionListener(new GpuChangeAction());
compute_devices_constraints.gridy++;
gridbag.setConstraints(gpuCheckBox, compute_devices_constraints);
compute_devices_panel.add(gpuCheckBox);
useGPUs.add(gpuCheckBox);
}
CPU cpu = new CPU();
if (cpu.cores() > 1) { // if only one core is available, no need to show the choice
double step = 1;
double display = (double)cpu.cores() / step;
while (display > 10) {
step += 1.0;
display = (double)cpu.cores() / step;
}
cpuCores = new JSlider(1, cpu.cores());
cpuCores.setMajorTickSpacing((int)(step));
cpuCores.setMinorTickSpacing(1);
cpuCores.setPaintTicks(true);
cpuCores.setPaintLabels(true);
cpuCores.setValue(config.getNbCores() != -1 ? config.getNbCores() : cpuCores.getMaximum());
JLabel coreLabel = new JLabel("CPU cores:");
compute_devices_constraints.weightx = 1.0 / gpus.size();
compute_devices_constraints.gridx = 0;
compute_devices_constraints.gridy++;
gridbag.setConstraints(coreLabel, compute_devices_constraints);
compute_devices_panel.add(coreLabel);
compute_devices_constraints.gridx = 1;
compute_devices_constraints.weightx = 1.0;
gridbag.setConstraints(cpuCores, compute_devices_constraints);
compute_devices_panel.add(cpuCores);
}
// max ram allowed to render
OS os = OS.getOS();
int all_ram = (int) os.getMemory();
ram = new JSlider(0, all_ram);
int step = 1000000;
double display = (double)all_ram / (double)step;
while (display > 10) {
step += 1000000;
display = (double)all_ram / (double)step;
}
Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
for (int g = 0; g < all_ram; g += step) {
labelTable.put(new Integer(g), new JLabel("" + (g / 1000000)));
}
ram.setMajorTickSpacing(step);
ram.setLabelTable(labelTable);
ram.setPaintTicks(true);
ram.setPaintLabels(true);
ram.setValue((int)(config.getMaxMemory() != -1 ? config.getMaxMemory() : os.getMemory()));
JLabel ramLabel = new JLabel("Memory:");
compute_devices_constraints.weightx = 1.0 / gpus.size();
compute_devices_constraints.gridx = 0;
compute_devices_constraints.gridy++;
gridbag.setConstraints(ramLabel, compute_devices_constraints);
compute_devices_panel.add(ramLabel);
compute_devices_constraints.gridx = 1;
compute_devices_constraints.weightx = 1.0;
gridbag.setConstraints(ram, compute_devices_constraints);
compute_devices_panel.add(ram);
parent.getContentPane().add(compute_devices_panel, constraints);
// priority
boolean high_priority_support = os.getSupportHighPriority();
priority = new JSlider(high_priority_support ? -19 : 0, 19);
priority.setMajorTickSpacing(19);
priority.setMinorTickSpacing(1);
priority.setPaintTicks(true);
priority.setPaintLabels(true);
priority.setValue(config.getPriority());
JLabel priorityLabel = new JLabel(high_priority_support ? "Priority (High <-> Low):" : "Priority (Normal <-> Low):" );
compute_devices_constraints.weightx = 1.0 / gpus.size();
compute_devices_constraints.gridx = 0;
compute_devices_constraints.gridy++;
gridbag.setConstraints(priorityLabel, compute_devices_constraints);
compute_devices_panel.add(priorityLabel);
compute_devices_constraints.gridx = 1;
compute_devices_constraints.weightx = 1.0;
gridbag.setConstraints(priority, compute_devices_constraints);
compute_devices_panel.add(priority);
currentRow++;
constraints.gridx = 0;
constraints.gridy = currentRow;
constraints.gridwidth = 2;
parent.getContentPane().add(compute_devices_panel, constraints);
// other
CollapsibleJPanel advanced_panel = new CollapsibleJPanel(new GridLayout(5, 2));
advanced_panel.setBorder(BorderFactory.createTitledBorder("Advanced options"));
JLabel proxyLabel = new JLabel("Proxy:");
proxyLabel.setToolTipText("http://login:password@host:port");
proxy = new JTextField();
proxy.setToolTipText("http://login:password@host:port");
proxy.setText(parent.getConfiguration().getProxy());
proxy.addKeyListener(new CheckCanStart());
advanced_panel.add(proxyLabel);
advanced_panel.add(proxy);
JLabel hostnameLabel = new JLabel("Computer name:");
hostname = new JTextField();
hostname.setText(parent.getConfiguration().getHostname());
advanced_panel.add(hostnameLabel);
advanced_panel.add(hostname);
JLabel renderTimeLabel = new JLabel("Max time per frame (in minute):");
int val = 0;
if (parent.getConfiguration().getMaxRenderTime() > 0) {
val = parent.getConfiguration().getMaxRenderTime() / 60;
}
renderTime = new JSpinner(new SpinnerNumberModel(val,0,1000,1));
advanced_panel.add(renderTimeLabel);
advanced_panel.add(renderTime);
JLabel customTileSizeLabel = new JLabel("Custom render tile size:");
customTileSize = new JCheckBox("", config.getTileSize() != -1);
advanced_panel.add(customTileSizeLabel);
advanced_panel.add(customTileSize);
customTileSize.addActionListener(new TileSizeChange());
tileSizeLabel = new JLabel("Tile Size:");
tileSizeValue = new JTextField();
int fromConfig = parent.getConfiguration().getTileSize();
if (fromConfig == -1) {
if (parent.getConfiguration().getGPUDevice() != null) {
fromConfig = parent.getConfiguration().getGPUDevice().getRecommandedTileSize();
}
else {
fromConfig = 32;
}
}
tileSizeValue.setText(Integer.toString(fromConfig));
hideCustomTileSize(config.getTileSize() != -1, false);
advanced_panel.add(tileSizeLabel);
advanced_panel.add(tileSizeValue);
currentRow++;
constraints.gridx = 0;
constraints.gridy = currentRow;
constraints.gridwidth = 2;
parent.getContentPane().add(advanced_panel, constraints);
advanced_panel.setCollapsed(true);
// general settings
JPanel general_panel = new JPanel(new GridLayout(1, 2));
saveFile = new JCheckBox("Save settings", true);
general_panel.add(saveFile);
autoSignIn = new JCheckBox("Auto sign in", config.isAutoSignIn());
autoSignIn.addActionListener(new AutoSignInChangeAction());
general_panel.add(autoSignIn);
currentRow++;
constraints.gridx = 0;
constraints.gridy = currentRow;
constraints.gridwidth = 2;
parent.getContentPane().add(general_panel, constraints);
String buttonText = "Start";
if (parent.getClient() != null) {
if (parent.getClient().isRunning()) {
buttonText = "Save";
}
}
saveButton = new JButton(buttonText);
checkDisplaySaveButton();
saveButton.addActionListener(new SaveAction());
currentRow++;
constraints.gridwidth = 2;
constraints.gridx = 0;
constraints.gridy = currentRow;
parent.getContentPane().add(saveButton, constraints);
if (haveAutoStarted == false && config.isAutoSignIn() && checkDisplaySaveButton()) {
// auto start
haveAutoStarted = true;
new SaveAction().actionPerformed(null);
}
}
public void hideCustomTileSize(boolean hidden, boolean displayWarning) {
tileSizeValue.setVisible(hidden);
tileSizeLabel.setVisible(hidden);
if (customTileSize.isSelected() == true && displayWarning) {
JOptionPane.showMessageDialog(parent.getContentPane(), "<html>These settings should only be changed if you are an advanced user.<br /> Improper settings may lead to invalid and slower renders!</html>", "Warning: Advanced Users Only!", JOptionPane.WARNING_MESSAGE);
}
}
public boolean checkDisplaySaveButton() {
boolean selected = useCPU.isSelected();
for (JCheckBoxGPU box : useGPUs) {
if (box.isSelected()) {
selected = true;
}
}
if (login.getText().isEmpty() || password.getPassword().length == 0 || Proxy.isValidURL(proxy.getText()) == false) {
selected = false;
}
if (customTileSize.isSelected()) {
try {
Integer.parseInt(tileSizeValue.getText().replaceAll(",", ""));
}
catch (NumberFormatException e) {
selected = false;
}
}
saveButton.setEnabled(selected);
return selected;
}
class ChooseFileAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(parent.getContentPane(), "<html>The working directory has to be dedicated directory. <br />Caution, everything not related to SheepIt-Renderfarm will be removed.<br />You should create a directory specifically for it.</html>", "Warning: files will be removed!", JOptionPane.WARNING_MESSAGE);
int returnVal = cacheDirChooser.showOpenDialog(parent.getContentPane());
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = cacheDirChooser.getSelectedFile();
cacheDir = file;
cacheDirText.setText(cacheDir.getName());
}
}
}
class CpuChangeAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
checkDisplaySaveButton();
}
}
class GpuChangeAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
for (JCheckBox box : useGPUs) {
if (box.equals(e.getSource()) == false) {
box.setSelected(false);
}
}
checkDisplaySaveButton();
}
}
class AutoSignInChangeAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (autoSignIn.isSelected()) {
saveFile.setSelected(true);
}
}
}
class TileSizeChange implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
boolean custom = customTileSize.isSelected();
hideCustomTileSize(custom, true);
}
}
class SaveAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (parent == null) {
return;
}
Configuration config = parent.getConfiguration();
if (config == null) {
return;
}
if (cacheDir != null) {
File fromConfig = config.getStorageDir();
if (fromConfig != null && fromConfig.getAbsolutePath().equals(cacheDir.getAbsolutePath()) == false) {
config.setCacheDir(cacheDir);
}
else {
// do nothing because the directory is the same as before
}
}
GPUDevice selected_gpu = null;
for (JCheckBoxGPU box : useGPUs) {
if (box.isSelected()) {
selected_gpu = box.getGPUDevice();
}
}
ComputeType method = ComputeType.CPU;
if (useCPU.isSelected() && selected_gpu == null) {
method = ComputeType.CPU;
}
else if (useCPU.isSelected() == false && selected_gpu != null) {
method = ComputeType.GPU;
}
else if (useCPU.isSelected() && selected_gpu != null) {
method = ComputeType.CPU_GPU;
}
config.setComputeMethod(method);
if (selected_gpu != null) {
config.setGPUDevice(selected_gpu);
}
int cpu_cores = -1;
if (cpuCores != null) {
cpu_cores = cpuCores.getValue();
}
if (cpu_cores > 0) {
config.setNbCores(cpu_cores);
}
long max_ram = -1;
if (ram != null) {
max_ram = ram.getValue();
}
if (max_ram > 0) {
config.setMaxMemory(max_ram);
}
int max_rendertime = -1;
if (renderTime != null) {
max_rendertime = (Integer)renderTime.getValue() * 60;
config.setMaxRenderTime(max_rendertime);
}
config.setUsePriority(priority.getValue());
String proxyText = null;
if (proxy != null) {
try {
Proxy.set(proxy.getText());
proxyText = proxy.getText();
}
catch (MalformedURLException e1) {
System.err.println("Error: wrong url for proxy");
System.err.println(e1);
System.exit(2);
}
}
String tile = null;
if (customTileSize.isSelected() && tileSizeValue != null) {
try {
tile = tileSizeValue.getText().replaceAll(",", "");
config.setTileSize(Integer.parseInt(tile));
}
catch (NumberFormatException e1) {
System.err.println("Error: wrong tile format");
System.err.println(e1);
System.exit(2);
}
}
else {
config.setTileSize(-1); // no tile
}
parent.setCredentials(login.getText(), new String(password.getPassword()));
String cachePath = null;
if (config.isUserHasSpecifiedACacheDir() && config.getCacheDirForSettings() != null) {
cachePath = config.getCacheDirForSettings().getAbsolutePath();
}
String hostnameText = hostname.getText();
if (hostnameText == null || hostnameText.isEmpty()) {
hostnameText = parent.getConfiguration().getHostname();
}
if (saveFile.isSelected()) {
new SettingsLoader(config.getConfigFilePath(), login.getText(), new String(password.getPassword()), proxyText, hostnameText, method, selected_gpu, cpu_cores, max_ram, max_rendertime, cachePath, autoSignIn.isSelected(), GuiSwing.type, tile, priority.getValue()).saveFile();
}
}
}
class JCheckBoxGPU extends JCheckBox {
private GPUDevice gpu;
public JCheckBoxGPU(GPUDevice gpu) {
super(gpu.getModel());
this.gpu = gpu;
}
public GPUDevice getGPUDevice() {
return gpu;
}
}
public class CheckCanStart implements KeyListener {
@Override
public void keyPressed(KeyEvent arg0) {
}
@Override
public void keyReleased(KeyEvent arg0) {
checkDisplaySaveButton();
}
@Override
public void keyTyped(KeyEvent arg0) {
}
}
}

View File

@@ -1,420 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.swing.activity;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Spring;
import javax.swing.SpringLayout;
import com.sheepit.client.Client;
import com.sheepit.client.Job;
import com.sheepit.client.RenderProcess;
import com.sheepit.client.Server;
import com.sheepit.client.Stats;
import com.sheepit.client.Utils;
import com.sheepit.client.os.OS;
import com.sheepit.client.standalone.GuiSwing;
import com.sheepit.client.standalone.GuiSwing.ActivityType;
public class Working implements Activity {
private GuiSwing parent;
private JLabel statusContent;
private JLabel renderedFrameContent;
private JLabel remainingFrameContent;
private JLabel lastRenderTime;
private JLabel lastRender;
private JLabel creditEarned;
private JButton pauseButton;
private JButton exitAfterFrame;
private JLabel current_project_name_value;
private JLabel current_project_duration_value;
private JLabel currrent_project_progression_value;
private JLabel current_project_compute_method_value;
private JLabel user_info_points_total_value;
private JLabel renderable_projects_value;
private JLabel waiting_projects_value;
private JLabel connected_machines_value;
private JLabel user_info_total_rendertime_this_session_value;
public Working(GuiSwing parent_) {
parent = parent_;
statusContent = new JLabel("Init");
renderedFrameContent = new JLabel("");
remainingFrameContent = new JLabel("");
creditEarned = new JLabel("");
current_project_name_value = new JLabel("");
current_project_duration_value = new JLabel("");
currrent_project_progression_value = new JLabel("");
current_project_compute_method_value = new JLabel("");
user_info_points_total_value = new JLabel("");
renderable_projects_value = new JLabel("");
waiting_projects_value = new JLabel("");
connected_machines_value = new JLabel("");
user_info_total_rendertime_this_session_value = new JLabel("");
lastRenderTime = new JLabel("");
lastRender = new JLabel("");
}
@Override
public void show() {
// current project
JPanel current_project_panel = new JPanel(new SpringLayout());
current_project_panel.setBorder(BorderFactory.createTitledBorder("Project"));
JLabel current_project_status = new JLabel("Status: ", JLabel.TRAILING);
JLabel current_project_name = new JLabel("Name: ", JLabel.TRAILING);
JLabel current_project_duration = new JLabel("Rendering for: ", JLabel.TRAILING);
JLabel current_project_progression = new JLabel("Remaining: ", JLabel.TRAILING);
JLabel current_project_compute_method_label = new JLabel("Compute method: ", JLabel.TRAILING);
current_project_panel.add(current_project_status);
current_project_panel.add(statusContent);
current_project_panel.add(current_project_name);
current_project_panel.add(current_project_name_value);
current_project_panel.add(current_project_duration);
current_project_panel.add(current_project_duration_value);
current_project_panel.add(current_project_progression);
current_project_panel.add(currrent_project_progression_value);
current_project_panel.add(current_project_compute_method_label);
current_project_panel.add(current_project_compute_method_value);
// user info
JPanel session_info_panel = new JPanel(new SpringLayout());
session_info_panel.setBorder(BorderFactory.createTitledBorder("Session infos"));
JLabel user_info_credits_this_session = new JLabel("Points earned: ", JLabel.TRAILING);
JLabel user_info_total_rendertime_this_session = new JLabel("Duration: ", JLabel.TRAILING);
JLabel user_info_rendered_frame_this_session = new JLabel("Rendered frames: ", JLabel.TRAILING);
JLabel global_static_renderable_project = new JLabel("Renderable projects: ", JLabel.TRAILING);
session_info_panel.add(user_info_credits_this_session);
session_info_panel.add(creditEarned);
session_info_panel.add(user_info_rendered_frame_this_session);
session_info_panel.add(renderedFrameContent);
session_info_panel.add(global_static_renderable_project);
session_info_panel.add(renderable_projects_value);
session_info_panel.add(user_info_total_rendertime_this_session);
session_info_panel.add(user_info_total_rendertime_this_session_value);
// global stats
JPanel global_stats_panel = new JPanel(new SpringLayout());
global_stats_panel.setBorder(BorderFactory.createTitledBorder("Global stats"));
JLabel global_stats_machine_connected = new JLabel("Machines connected: ", JLabel.TRAILING);
JLabel global_stats_remaining_frame = new JLabel("Remaining frames: ", JLabel.TRAILING);
JLabel global_stats_waiting_project = new JLabel("Active projects: ", JLabel.TRAILING);
JLabel global_stats_user_points = new JLabel("User's points: ", JLabel.TRAILING);
global_stats_panel.add(global_stats_waiting_project);
global_stats_panel.add(waiting_projects_value);
global_stats_panel.add(global_stats_machine_connected);
global_stats_panel.add(connected_machines_value);
global_stats_panel.add(global_stats_remaining_frame);
global_stats_panel.add(remainingFrameContent);
global_stats_panel.add(global_stats_user_points);
global_stats_panel.add(user_info_points_total_value);
// last frame
JPanel last_frame_panel = new JPanel();
last_frame_panel.setLayout(new BoxLayout(last_frame_panel, BoxLayout.Y_AXIS));
last_frame_panel.setBorder(BorderFactory.createTitledBorder("Last rendered frame"));
lastRender.setIcon(new ImageIcon(new BufferedImage(200, 120, BufferedImage.TYPE_INT_ARGB)));
lastRender.setAlignmentX(Component.CENTER_ALIGNMENT);
lastRenderTime.setAlignmentX(Component.CENTER_ALIGNMENT);
last_frame_panel.add(lastRenderTime);
last_frame_panel.add(lastRender);
ImageIcon image = new ImageIcon(getClass().getResource("/title.png"));
JLabel labelImage = new JLabel(image);
labelImage.setAlignmentX(Component.CENTER_ALIGNMENT);
parent.getContentPane().add(labelImage);
JPanel buttonsPanel = new JPanel(new GridLayout(2, 2));
JButton settingsButton = new JButton("Settings");
settingsButton.addActionListener(new SettingsAction());
pauseButton = new JButton("Pause");
Client client = parent.getClient();
if (client != null && client.isSuspended()) {
pauseButton.setText("Resume");
}
pauseButton.addActionListener(new PauseAction());
JButton blockJob = new JButton("Block this project");
blockJob.addActionListener(new blockJobAction());
exitAfterFrame = new JButton("Exit after this frame");
exitAfterFrame.addActionListener(new ExitAfterAction());
buttonsPanel.add(settingsButton);
buttonsPanel.add(pauseButton);
buttonsPanel.add(blockJob);
buttonsPanel.add(exitAfterFrame);
parent.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints global_constraints = new GridBagConstraints();
global_constraints.fill = GridBagConstraints.HORIZONTAL;
global_constraints.weightx = 1;
global_constraints.gridx = 0;
parent.getContentPane().add(current_project_panel, global_constraints);
parent.getContentPane().add(global_stats_panel, global_constraints);
parent.getContentPane().add(session_info_panel, global_constraints);
parent.getContentPane().add(last_frame_panel, global_constraints);
parent.getContentPane().add(buttonsPanel, global_constraints);
Spring widthLeftColumn = getBestWidth(current_project_panel, 4, 2);
widthLeftColumn = Spring.max(widthLeftColumn, getBestWidth(global_stats_panel, 4, 2));
widthLeftColumn = Spring.max(widthLeftColumn, getBestWidth(session_info_panel, 3, 2));
alignPanel(current_project_panel, 5, 2, widthLeftColumn);
alignPanel(global_stats_panel, 4, 2, widthLeftColumn);
alignPanel(session_info_panel, 4, 2, widthLeftColumn);
}
public void setStatus(String msg_) {
statusContent.setText("<html>" + msg_ + "</html>");
}
public void setRenderingProjectName(String msg_) {
current_project_name_value.setText("<html>" + (msg_.length() > 26 ? msg_.substring(0, 26) : msg_) + "</html>");
}
public void setRemainingTime(String time_) {
currrent_project_progression_value.setText("<html>" + time_ + "</html>");
}
public void setRenderingTime(String time_) {
current_project_duration_value.setText("<html>" + time_ + "</html>");
}
public void setComputeMethod(String computeMethod_) {
this.current_project_compute_method_value.setText(computeMethod_);
}
public void displayStats(Stats stats) {
DecimalFormat df = new DecimalFormat("##,##,##,##,##,##,##0");
remainingFrameContent.setText(df.format(stats.getRemainingFrame()));
creditEarned.setText(df.format(stats.getCreditsEarnedDuringSession()));
user_info_points_total_value.setText(df.format(stats.getCreditsEarned()));
renderable_projects_value.setText(df.format(stats.getRenderableProject()));
waiting_projects_value.setText(df.format(stats.getWaitingProject()));
connected_machines_value.setText(df.format(stats.getConnectedMachine()));
updateTime();
}
public void updateTime() {
if (this.parent.getClient().getStartTime() != 0) {
user_info_total_rendertime_this_session_value.setText(Utils.humanDuration(new Date((new Date().getTime() - this.parent.getClient().getStartTime()))));
}
Job job = this.parent.getClient().getRenderingJob();
if (job != null && job.getProcessRender() != null && job.getProcessRender().getStartTime() > 0) {
current_project_duration_value.setText("<html>" + Utils.humanDuration(new Date((new Date().getTime() - job.getProcessRender().getStartTime()))) + "</html>");
}
else {
current_project_duration_value.setText("");
}
}
public void setRenderedFrame(int n) {
renderedFrameContent.setText(String.valueOf(n));
showLastRender();
}
public void showLastRender() {
Client client = parent.getClient();
if (client != null) {
Job lastJob = client.getPreviousJob();
Server server = client.getServer();
if (server != null) {
byte[] data = server.getLastRender();
if (data != null) {
InputStream is = new ByteArrayInputStream(data);
try {
BufferedImage image = ImageIO.read(is);
if (image != null) {
lastRender.setIcon(new ImageIcon(image));
if (lastJob != null) {
// don't use lastJob.getProcessRender().getDuration() due to timezone
if (lastJob.getProcessRender().getDuration() > 1) {
lastRenderTime.setText("Render time : " + Utils.humanDuration(new Date(lastJob.getProcessRender().getEndTime() - lastJob.getProcessRender().getStartTime())));
}
}
}
}
catch (IOException e) {
System.out.println("Working::showLastRender() exception " + e);
e.printStackTrace();
}
}
}
}
}
private void alignPanel(Container parent, int rows, int cols, Spring width) {
SpringLayout layout;
try {
layout = (SpringLayout) parent.getLayout();
}
catch (ClassCastException exc) {
System.err.println("The first argument to makeCompactGrid must use SpringLayout.");
return;
}
Spring x = Spring.constant(0);
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
constraints.setX(x);
constraints.setWidth(width);
}
x = Spring.sum(x, width);
}
Spring y = Spring.constant(0);
for (int r = 0; r < rows; r++) {
Spring height = Spring.constant(0);
for (int c = 0; c < cols; c++) {
height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight());
}
for (int c = 0; c < cols; c++) {
SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
constraints.setY(y);
constraints.setHeight(height);
}
y = Spring.sum(y, height);
}
SpringLayout.Constraints pCons = layout.getConstraints(parent);
pCons.setConstraint(SpringLayout.SOUTH, y);
pCons.setConstraint(SpringLayout.EAST, x);
}
private Spring getBestWidth(Container parent, int rows, int cols) {
Spring x = Spring.constant(0);
Spring width = Spring.constant(0);
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth());
}
}
return width;
}
private SpringLayout.Constraints getConstraintsForCell(int row, int col, Container parent, int cols) {
SpringLayout layout = (SpringLayout) parent.getLayout();
Component c = parent.getComponent(row * cols + col);
return layout.getConstraints(c);
}
class PauseAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Client client = parent.getClient();
if (client != null) {
if (client.isSuspended()) {
pauseButton.setText("Pause");
client.resume();
}
else {
pauseButton.setText("Resume");
client.suspend();
}
}
}
}
class SettingsAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (parent != null) {
parent.showActivity(ActivityType.SETTINGS);
}
}
}
class ExitAfterAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Client client = parent.getClient();
if (client != null) {
if (client.isRunning()) {
exitAfterFrame.setText("Cancel exit");
client.askForStop();
}
else {
exitAfterFrame.setText("Exit after this frame");
client.cancelStop();
}
}
}
}
class blockJobAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Client client = parent.getClient();
if (client != null) {
Job job = client.getRenderingJob();
if (job != null) {
job.block();
}
}
}
}
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright (C) 2015 Laurent CLOUET
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.swing.components;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
public class CollapsibleJPanel extends JPanel {
private boolean isCompnentsVisible = true;
private int originalHeight;
private String borderTitle = "";
private int COLLAPSED_HEIGHT = 22;
private boolean[] originalVisibilty;
public CollapsibleJPanel(LayoutManager layoutManager) {
setLayout(layoutManager);
addMouseListener(new onClickHandler());
}
public void setCollapsed(boolean aFlag) {
if (aFlag) {
hideComponents();
}
else {
showComponents();
}
}
public void toggleCollapsed() {
if (isCompnentsVisible) {
setCollapsed(true);
}
else {
setCollapsed(false);
}
}
private void hideComponents() {
Component[] components = getComponents();
originalVisibilty = new boolean[components.length];
// Hide all componens on panel
for (int i = 0; i < components.length; i++) {
originalVisibilty[i] = components[i].isVisible();
components[i].setVisible(false);
}
setHeight(COLLAPSED_HEIGHT);
// Add '+' char to end of border title
//setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), borderTitle + " + "));
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), " + " + borderTitle));
// Update flag
isCompnentsVisible = false;
}
private void showComponents() {
Component[] components = getComponents();
// Set all components in panel to visible
for (int i = 0; i < components.length; i++) {
components[i].setVisible(originalVisibilty[i]);
}
setHeight(originalHeight);
// Add '-' char to end of border title
setBorder(BorderFactory.createTitledBorder(" - " + borderTitle));
// Update flag
isCompnentsVisible = true;
}
private void setHeight(int height) {
setPreferredSize(new Dimension(getPreferredSize().width, height));
setMinimumSize(new Dimension(getMinimumSize().width, height));
setMaximumSize(new Dimension(getMaximumSize().width, height));
}
@Override
public Component add(Component component) { // Need this to get the original height of panel
Component returnComponent = super.add(component);
originalHeight = getPreferredSize().height;
return returnComponent;
}
@Override
public void setBorder(Border border) { // Need this to get the border title
if (border instanceof TitledBorder && (borderTitle == "")) {
borderTitle = ((TitledBorder) border).getTitle();
((TitledBorder) border).setTitle(" - " + borderTitle);
}
super.setBorder(border);
}
public class onClickHandler implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (e.getPoint().y < COLLAPSED_HEIGHT) { // Only if click is on top of panel
((CollapsibleJPanel) e.getComponent()).toggleCollapsed();
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright (C) 2017 Laurent CLOUET
* Author Rolf Aretz Lap <rolf.aretz@ottogroup.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.text;
import com.sheepit.client.Client;
import com.sheepit.client.Configuration;
import com.sheepit.client.Job;
public class CLIInputActionHandler implements CLIInputListener {
@Override
public void commandEntered(Client client, String command) {
int priorityLength = "priority".length();
//prevent Null Pointer at next step
if (command == null) {
return;
}
if (client == null) {
return;
}
if (command.equalsIgnoreCase("block")) {
Job job = client.getRenderingJob();
if (job != null) {
job.block();
}
}
else if (command.equalsIgnoreCase("resume")) {
client.resume();
}
else if (command.equalsIgnoreCase("pause")) {
client.suspend();
}
else if (command.equalsIgnoreCase("stop")) {
client.askForStop();
}
else if (command.equalsIgnoreCase("status")) {
displayStatus(client);
}
else if (command.equalsIgnoreCase("cancel")) {
client.cancelStop();
}
else if (command.equalsIgnoreCase("quit")) {
client.stop();
System.exit(0);
}
else if ((command.length() > priorityLength) && (command.substring(0, priorityLength).equalsIgnoreCase("priority"))) {
changePriority(client, command.substring(priorityLength));
}
else {
System.out.println("Unknown command: " + command);
System.out.println("status: display client status");
System.out.println("priority <n>: set the priority for the next renderjob");
System.out.println("block: block project");
System.out.println("pause: pause client requesting new jobs");
System.out.println("resume: resume after client was paused");
System.out.println("stop: exit after frame was finished");
System.out.println("cancel: cancel exit");
System.out.println("quit: exit now");
}
}
void changePriority(Client client, String newPriority) {
Configuration config = client.getConfiguration();
if (config != null) {
try {
config.setUsePriority(Integer.parseInt(newPriority.trim()));
}
catch (NumberFormatException e) {
System.out.println("Invalid priority: " + newPriority);
}
}
}
void displayStatus(Client client) {
if (client.isSuspended()) {
System.out.println("Status: paused");
}
else if (client.isRunning()) {
System.out.println("Status: running");
}
else {
System.out.println("Status: will exit after the current frame");
}
}
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) 2017 Laurent CLOUET
* Author Rolf Aretz Lap <rolf.aretz@ottogroup.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.text;
import com.sheepit.client.Client;
public interface CLIInputListener {
public void commandEntered(Client client, String command);
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2017 Laurent CLOUET
* Author Rolf Aretz Lap <rolf.aretz@ottogroup.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sheepit.client.standalone.text;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import com.sheepit.client.Client;
public class CLIInputObserver implements Runnable {
private BufferedReader in;
private Client client;
public CLIInputObserver(Client client) {
this.client = client;
}
private List<CLIInputListener> listeners = new ArrayList<CLIInputListener>();
public void addListener(CLIInputListener toAdd) {
listeners.add(toAdd);
}
public void run() {
in = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while ((line != null) && (line.equalsIgnoreCase("quit") == false)) {
try {
line = in.readLine();
}
catch (Exception e) {
// TODO: handle exception
}
for (CLIInputListener cliil : listeners)
cliil.commandEntered(client, line);
}
try {
in.close();
}
catch (Exception e) {
// TODO: handle exception
}
}
}