/* Copyright 2009 Nathan Phillip Brink, Ethan Zonca, Matthew Orlando This file is a part of DistRen. DistRen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. DistRen 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with DistRen. If not, see . */ #include "slavefuncs.h" #include "common/asprintf.h" #include "common/options.h" #include "common/protocol.h" #include "common/remoteio.h" #include #include #include #include #include int main(int argc, char *argv[]) { char *datadir; char *server; char *username; char *hostname; cfg_opt_t myopts[] = { CFG_SIMPLE_STR("username", &username), CFG_SIMPLE_STR("datadir", &datadir), CFG_SIMPLE_STR("server", &server), CFG_SIMPLE_STR("hostname", &hostname), CFG_END() }; cfg_t * my_cfg; struct options_common *commonopts; struct distrenjob *myjob; /* Structure to hold data gathered from the XML file */ struct remoteio *comm_slave; /** initializations */ datadir = NULL; server = NULL; username = NULL; char curopt; while(((char)-1) != (curopt = getopt(argc, argv, "u:th"))) { if(curopt == ':') { fprintf(stderr, "-%c: is missing an argument\n", optopt); return 1; } else if(curopt == '?') { fprintf(stderr, "-%c: invalid option specified\n", optopt); return 1; } else if(curopt == 'h') { fprintf(stderr, "Usage: distrenslave [option] \nStarts a distren slave\n\t-u\tset username (run after fresh install)\n\t-t\tEnter test mode\n\t-h\tshow this help\n"); return 2; } else if(curopt == 't') { slaveTest(); return 0; } else if(curopt == 'u') username = strdup(optarg); fprintf(stderr, "Putting username \"%s\" in distrenslave.conf\n", username); conf_replace("distrenslave.conf", "!username", username); fprintf(stderr, "Please invoke distrenslave with no arguments to run with the username you just set\n"); return 0; } /* Get conf data */ options_init(argc, argv, &my_cfg, myopts, "slave", &commonopts); /* Notifies the user if there no username in .conf */ if(checkUsername(username)) return 1; fprintf(stderr, "Connecting to server...\n"); if(remoteio_open(&comm_slave, commonopts->remoteio, server)) { fprintf(stderr, "Error connecting to server; exiting\n"); return 1; } // Variables needed for main loop int jobnum = 0; int framenum = 0; int slavekey = atoi(username); // @TODO: Make this more friendly char *urltoTar; /* Full URL to the server-side location of job#.tgz */ char *pathtoTar; /* Full path to the location of the job#.tgz */ char *urltoOutput; /* Full URL where output is posted */ char *pathtoOutput; /* Full path to the output (rendered) file */ char *pathtoJobfile; /* Full path to the job's main file */ char *outputExt; /* Output Extension (e.g., JPG) */ int haveWork = 0; int quit = 0; // Main loop while(!quit) { // request work fprintf(stderr,"Requesting work...\n"); sendSignal(comm_slave, DISTREN_REQUEST_GETWORK); /* If we got a frame */ if(haveWork) { fprintf(stderr,"Got work from server...\n"); /* @TODO: Add remotio hooks */ // jobnum = remoteio_read(jobnum); /* Set jobnum from remoteio (we could use info from struct, but we need this info to download the xmlfile */ // framenum = remoteio_read(jobnum); /* Set framenum from remoteio */ // outputExt = remotio)read(outputExt); /* Set output extension from remotio */ fprintf(stderr, "Preparing to render frame %d in job %d\n", framenum, jobnum); prepareJobPaths(jobnum, framenum, outputExt, datadir, &urltoTar, &pathtoTar, &pathtoJobfile, &urltoOutput, &pathtoOutput); free(outputExt); if(downloadTar(urltoTar, pathtoTar)) return 1; unpackJob(pathtoTar, jobnum); /* Execute blender */ if(exec_blender(pathtoJobfile, pathtoOutput, framenum)) { fprintf(stderr,"Error running Blender. Check your installation and/or your PATH.\n"); return 1; } free(pathtoJobfile); /* Post-execution */ fprintf(stderr, "Finished frame %d in job %d, uploading...\n", framenum, jobnum); uploadOutput(pathtoOutput, urltoOutput, jobnum, framenum, slavekey); // @TODO: Handle return value free(urltoOutput); free(pathtoOutput); // Tell the server that rendering and upload are complete of "jobjum.framenum" char *jobFrame; _distren_asprintf(&jobFrame, "%s.%s", jobnum, framenum); sendExtSignal(comm_slave, DISTREN_REQUEST_DONEFRAME, jobFrame); free(jobFrame); } else fprintf(stderr,"Nothing to do. Idling...\n"); // @TODO: If the server says that every frame for the last jobnum is finished, OR if the data is getting old if(1 == 0) { // Note: individual frames are already deleted after uploading, // except for ones that couldn't be uploaded delete_jobdata(jobnum, datadir); } sleep(5); // Poll 5 seconds. @TODO: Remove all polling } fprintf(stderr,"Closing connection to server...\n"); remoteio_close(comm_slave); fprintf(stderr,"Goodbye!\n"); return 0; }