2014-11-20 13:21:19 +00:00
/ *
* 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 ;
2015-04-08 20:45:54 +01:00
import com.sheepit.client.SettingsLoader ;
2014-11-20 13:21:19 +00:00
import com.sheepit.client.ShutdownHook ;
2019-02-20 13:53:18 +01:00
import com.sheepit.client.Utils ;
2014-11-20 13:21:19 +00:00
import com.sheepit.client.hardware.gpu.GPU ;
import com.sheepit.client.hardware.gpu.GPUDevice ;
2018-08-24 19:46:03 +02:00
import com.sheepit.client.hardware.gpu.nvidia.Nvidia ;
import com.sheepit.client.hardware.gpu.opencl.OpenCL ;
2015-07-06 18:41:28 +01:00
import com.sheepit.client.network.Proxy ;
2014-11-20 13:21:19 +00:00
public class Worker {
2016-03-14 23:59:11 +01:00
@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 " ;
2014-11-20 13:21:19 +00:00
2015-01-15 23:34:58 +01:00
@Option ( name = " -login " , usage = " User's login " , metaVar = " LOGIN " , required = false )
2014-11-20 13:21:19 +00:00
private String login = " " ;
2015-01-15 23:34:58 +01:00
@Option ( name = " -password " , usage = " User's password " , metaVar = " PASSWORD " , required = false )
2014-11-20 13:21:19 +00:00
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 ;
2018-08-24 19:46:03 +02:00
@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 )
2014-11-20 13:21:19 +00:00
private String gpu_device = null ;
2018-08-24 19:46:03 +02:00
@Option ( name = " --no-gpu " , usage = " Don't detect GPUs " , required = false )
private boolean no_gpu_detection = false ;
2014-12-02 20:21:12 +00:00
@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 )
2014-11-20 13:21:19 +00:00
private String method = null ;
2014-12-23 20:05:29 +01:00
@Option ( name = " -cores " , usage = " Number of cores/threads to use for the render " , metaVar = " 3 " , required = false )
2014-11-20 13:21:19 +00:00
private int nb_cores = - 1 ;
2019-02-20 13:53:18 +01:00
@Option ( name = " -memory " , usage = " Maximum memory allow to be used by renderer, number with unit (800M, 2G, ...) " , required = false )
private String max_ram = null ;
2017-04-04 23:06:31 +02:00
2017-04-25 13:06:23 +02:00
@Option ( name = " -rendertime " , usage = " Maximum time allow for each frame (in minute) " , required = false )
private int max_rendertime = - 1 ;
2014-11-20 13:21:19 +00:00
@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 ;
2015-05-10 12:35:37 +01:00
@Option ( name = " -ui " , usage = " Specify the user interface to use, default ' " + GuiSwing . type + " ', available ' " + GuiTextOneLine . type + " ', ' " + GuiText . type + " ', ' " + GuiSwing . type + " ' (graphical) " , required = false )
2015-04-08 20:37:53 +01:00
private String ui_type = null ;
2014-11-20 17:50:23 +00:00
2015-04-07 20:07:53 +01:00
@Option ( name = " -config " , usage = " Specify the configuration file " , required = false )
private String config_file = null ;
2015-01-12 23:09:34 +01:00
@Option ( name = " --version " , usage = " Display application version " , required = false , handler = VersionParameterHandler . class )
private VersionParameterHandler versionHandler ;
2014-11-20 13:21:19 +00:00
2017-01-19 18:08:26 +01:00
@Option ( name = " --show-gpu " , usage = " Print available CUDA devices and exit " , required = false , handler = ListGpuParameterHandler . class )
private ListGpuParameterHandler listGpuParameterHandler ;
2016-04-28 19:37:05 +02:00
@Option ( name = " --no-systray " , usage = " Don't use systray " , required = false )
private boolean no_systray = false ;
2017-01-05 09:58:27 +01:00
@Option ( name = " -priority " , usage = " Set render process priority (19 lowest to -19 highest) " , required = false )
private int priority = 19 ;
2018-06-14 23:07:06 +02:00
@Option ( name = " -title " , usage = " Custom title for the GUI Client " , required = false )
private String title = " SheepIt Render Farm " ;
2017-01-05 09:58:27 +01:00
2014-11-20 13:21:19 +00:00
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 ;
}
2015-04-07 20:05:48 +01:00
ComputeType compute_method = ComputeType . CPU ;
2014-11-20 13:21:19 +00:00
Configuration config = new Configuration ( null , login , password ) ;
config . setPrintLog ( print_log ) ;
2017-01-05 09:58:27 +01:00
config . setUsePriority ( priority ) ;
2018-08-24 19:46:03 +02:00
config . setDetectGPUs ( ! no_gpu_detection ) ;
2014-11-20 13:21:19 +00:00
if ( cache_dir ! = null ) {
File a_dir = new File ( cache_dir ) ;
2016-11-26 20:42:45 +01:00
a_dir . mkdirs ( ) ;
2014-11-20 13:21:19 +00:00
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 ) {
2018-08-24 19:46:03 +02:00
if ( gpu_device . startsWith ( Nvidia . TYPE ) = = false & & gpu_device . startsWith ( OpenCL . TYPE ) = = false ) {
2019-07-09 17:55:00 +02:00
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 ) ;
2014-11-20 13:21:19 +00:00
}
2018-08-24 19:46:03 +02:00
String family = " " ;
2019-07-09 17:55:00 +02:00
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 " ) ;
2014-11-20 13:21:19 +00:00
return ;
}
GPUDevice gpu = GPU . getGPUDevice ( gpu_device ) ;
if ( gpu = = null ) {
2019-07-09 17:55:00 +02:00
System . err . println ( " GPU unknown, list of available gpus can be display with --show-gpu " ) ;
2014-11-20 13:21:19 +00:00
System . exit ( 2 ) ;
}
2019-08-07 22:17:59 +02:00
config . setGPUDevice ( gpu ) ;
2014-11-20 13:21:19 +00:00
}
if ( request_time ! = null ) {
String [ ] intervals = request_time . split ( " , " ) ;
if ( intervals ! = null ) {
2019-08-07 22:17:59 +02:00
config . setRequestTime ( new LinkedList < Pair < Calendar , Calendar > > ( ) ) ;
2014-11-20 13:21:19 +00:00
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 ) ) {
2019-08-07 22:17:59 +02:00
config . getRequestTime ( ) . add ( new Pair < Calendar , Calendar > ( start , end ) ) ;
2014-11-20 13:21:19 +00:00
}
else {
System . err . println ( " Error: wrong request time " + times [ 0 ] + " is after " + times [ 1 ] ) ;
System . exit ( 2 ) ;
}
}
}
}
}
2014-11-30 23:49:17 +00:00
if ( nb_cores < - 1 | | nb_cores = = 0 ) { // -1 is the default
2014-11-20 13:21:19 +00:00
System . err . println ( " Error: use-number-core should be a greater than zero " ) ;
return ;
}
else {
2019-08-07 22:17:59 +02:00
config . setNbCores ( nb_cores ) ;
2014-11-20 13:21:19 +00:00
}
2019-02-20 13:53:18 +01:00
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 ;
}
2017-04-04 23:06:31 +02:00
}
2017-04-25 13:06:23 +02:00
if ( max_rendertime > 0 ) {
config . setMaxRenderTime ( max_rendertime * 60 ) ;
}
2014-11-20 13:21:19 +00:00
if ( method ! = null ) {
2015-03-31 22:04:09 +01:00
try {
compute_method = ComputeType . valueOf ( method ) ;
2014-11-20 13:21:19 +00:00
}
2015-03-31 22:04:09 +01:00
catch ( IllegalArgumentException e ) {
2014-11-20 13:21:19 +00:00
System . err . println ( " Error: compute-method unknown " ) ;
System . exit ( 2 ) ;
}
}
2014-12-02 20:21:12 +00:00
else {
if ( config . getGPUDevice ( ) = = null ) {
2015-04-07 20:05:48 +01:00
compute_method = ComputeType . CPU ;
2014-12-02 20:21:12 +00:00
}
else {
2015-04-07 20:05:48 +01:00
compute_method = ComputeType . GPU ;
2014-12-02 20:21:12 +00:00
}
}
2014-11-20 13:21:19 +00:00
if ( proxy ! = null ) {
try {
2015-07-06 18:41:28 +01:00
Proxy . set ( proxy ) ;
2014-11-20 13:21:19 +00:00
}
catch ( MalformedURLException e ) {
System . err . println ( " Error: wrong url for proxy " ) ;
System . err . println ( e ) ;
System . exit ( 2 ) ;
}
}
if ( extras ! = null ) {
config . setExtras ( extras ) ;
}
2015-04-07 20:05:48 +01:00
if ( compute_method = = ComputeType . CPU & & config . getGPUDevice ( ) ! = null ) {
2014-12-23 20:05:29 +01:00
System . err . println ( " You choose to only use the CPU but a GPU was also provided. You can not do both. " ) ;
2014-12-02 20:21:12 +00:00
System . err . println ( " Aborting " ) ;
System . exit ( 2 ) ;
2014-11-20 13:21:19 +00:00
}
2014-12-02 20:21:12 +00:00
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 ) ;
}
2015-04-07 20:05:48 +01:00
else if ( compute_method = = ComputeType . GPU & & config . getGPUDevice ( ) = = null ) {
2014-12-02 20:21:12 +00:00
System . err . println ( " You choose to only use the GPU but no GPU device was provided. " ) ;
System . err . println ( " Aborting " ) ;
System . exit ( 2 ) ;
2014-11-20 13:21:19 +00:00
}
2015-04-07 20:05:48 +01:00
else if ( compute_method = = ComputeType . CPU ) {
2019-08-07 22:17:59 +02:00
config . setGPUDevice ( null ) ; // remove the GPU
2014-12-02 20:21:12 +00:00
}
config . setComputeMethod ( compute_method ) ;
2014-11-20 13:21:19 +00:00
2015-04-08 20:37:53 +01:00
if ( ui_type ! = null ) {
config . setUIType ( ui_type ) ;
}
2015-04-07 20:07:53 +01:00
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 ) ;
}
2019-08-07 22:17:59 +02:00
config . setConfigFilePath ( config_file ) ;
2015-04-07 20:07:53 +01:00
new SettingsLoader ( config_file ) . merge ( config ) ;
}
2014-11-20 13:21:19 +00:00
Log . getInstance ( config ) . debug ( " client version " + config . getJarVersion ( ) ) ;
2014-11-20 17:50:23 +00:00
Gui gui ;
2015-04-08 20:37:53 +01:00
String type = config . getUIType ( ) ;
if ( type = = null ) {
type = " swing " ;
}
switch ( type ) {
2015-04-08 20:32:24 +01:00
case GuiTextOneLine . type :
2019-08-07 22:17:59 +02:00
if ( config . isPrintLog ( ) ) {
2015-01-28 20:11:57 +00:00
System . out . println ( " OneLine UI can not be used if verbose mode is enabled " ) ;
System . exit ( 2 ) ;
}
gui = new GuiTextOneLine ( ) ;
break ;
2015-04-08 20:37:53 +01:00
case GuiText . type :
gui = new GuiText ( ) ;
break ;
default :
2015-04-08 20:32:24 +01:00
case GuiSwing . type :
2015-01-28 20:11:57 +00:00
if ( java . awt . GraphicsEnvironment . isHeadless ( ) ) {
System . out . println ( " Graphical ui can not be launch. " ) ;
2015-05-16 22:35:16 +01:00
System . out . println ( " You should set a DISPLAY or use a text ui (with -ui " + GuiTextOneLine . type + " or -ui " + GuiText . type + " ). " ) ;
2015-01-28 20:11:57 +00:00
System . exit ( 3 ) ;
}
2018-06-14 23:07:06 +02:00
gui = new GuiSwing ( no_systray = = false , title ) ;
2015-01-28 20:11:57 +00:00
break ;
2014-11-20 17:50:23 +00:00
}
2014-11-20 13:21:19 +00:00
Client cli = new Client ( gui , config , server ) ;
2015-01-15 23:20:17 +01:00
gui . setClient ( cli ) ;
2014-11-20 13:21:19 +00:00
ShutdownHook hook = new ShutdownHook ( cli ) ;
hook . attachShutDownHook ( ) ;
2015-01-15 23:20:17 +01:00
gui . start ( ) ;
2014-11-20 13:21:19 +00:00
}
}