/*
Copyright 2010 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 *pathtoTardir;
char *pathtoRenderOutput;
char *urltoOutput; /* Full URL where output is posted */
char *pathtoOutput; /* Full path to the output (rendered) file */
char *pathtoOutdir; /* Full path to output directory */
// Temporary for uncomressed testing
char *urltoJobfile;
char *pathtoJob; /* Full path to job data folder */
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,&pathtoTardir,&pathtoJob, &pathtoJobfile, &urltoJobfile, &urltoOutput, &pathtoOutput, &pathtoRenderOutput, &pathtoOutdir);
free(outputExt);
if(downloadTar(urltoTar, pathtoTar))
return 1;
unpackJob(datadir, pathtoTar);
/* 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;
}