Files @ 5908e352e267
Branch filter:

Location: DistRen/src/server/simpleslave.c - annotation

ethanzonca
Fixed other hanging pointer issue
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
7d056f57c29a
3c5489e556ae
7d056f57c29a
3c5489e556ae
3c5489e556ae
7d056f57c29a
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
7d056f57c29a
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
4ec01e2efee7
7d056f57c29a
7d056f57c29a
7d056f57c29a
7d056f57c29a
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
6331e72e3889
3c5489e556ae
78516a1d1aee
78516a1d1aee
78516a1d1aee
3c5489e556ae
3c5489e556ae
df7e1f917a6d
78516a1d1aee
3c5489e556ae
4ec01e2efee7
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
d0f64b1f3376
d0f64b1f3376
d0f64b1f3376
d0f64b1f3376
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
195048ceb561
d0f64b1f3376
d0f64b1f3376
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
78516a1d1aee
6331e72e3889
6331e72e3889
78516a1d1aee
78516a1d1aee
4e072ce1165f
78516a1d1aee
78516a1d1aee
0307f7fcc410
0307f7fcc410
4e072ce1165f
0307f7fcc410
e0266092c553
78516a1d1aee
78516a1d1aee
3c5489e556ae
78516a1d1aee
6331e72e3889
6331e72e3889
6331e72e3889
6331e72e3889
6331e72e3889
6331e72e3889
0307f7fcc410
0307f7fcc410
6331e72e3889
0307f7fcc410
6331e72e3889
78516a1d1aee
3c5489e556ae
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
4ec01e2efee7
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
4ec01e2efee7
78516a1d1aee
3c5489e556ae
3c5489e556ae
0307f7fcc410
3c5489e556ae
3c5489e556ae
3c5489e556ae
7f610e2808f2
3c5489e556ae
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
78516a1d1aee
0307f7fcc410
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
3c5489e556ae
df7e1f917a6d
df7e1f917a6d
7f610e2808f2
7f610e2808f2
df7e1f917a6d
df7e1f917a6d
df7e1f917a6d
3c5489e556ae
4f1cbf0f8f32
3c5489e556ae
4f1cbf0f8f32
4f1cbf0f8f32
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
3c5489e556ae
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
7f610e2808f2
3c5489e556ae
3c5489e556ae
3c5489e556ae
/*
  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 <http://www.gnu.org/licenses/>.

*/

#include "slavefuncs.h"

#include "common/asprintf.h"
#include "common/options.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>


int main(int argc, char *argv[])
{
  char *datadir;
  char *server;
  char *username;
  char *password;
  char *hostname;

  cfg_opt_t myopts[] = {
    CFG_SIMPLE_STR("username", &username),
    CFG_SIMPLE_STR("password", &password),
    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;

  /**
     initializations
  */
  datadir = NULL;
  server = NULL;
  username = NULL;
  password = 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;
  if(!strncmp(password, "!password",10))
    {
      fprintf(stderr, "You haven't specified a password. Please edit your distrenslave.conf file appropriately\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;

  // Temporary for uncomressed testing
  char *urltoJobfile;

  char *urltoOutput;   /* Full URL where output is posted */
  char *pathtoOutput;  /* Full path to the output (rendered) file */
  char *pathtoOutdir;  /* Full path to output directory */
  char *pathtoRenderOutput; /* Contains blender framenum placeholder */

  char *pathtoJob; /* Path to job data folder */
  char *pathtoJobfile; /* Full path to the job's main file */
  char *outputExt = "jpg";     /* Output Extension (e.g., JPG) */

  int haveWork = 0;
  int quit = 0;

  fprintf(stderr,"DistRenSimpleSlave Pre-Alpha\n\t- this version of DistRen is still experimental\n\t  so things might go horribly wrong!\n");

  int benchmarkTime = 0;
  int renderPower = 0;

  char option[1] = "";
  fprintf(stderr,"Do you want to recalculate render power? (y/n): ");
  scanf("%s", option);
  if(!strcmp(option, "y")){
    if(slaveBenchmark(datadir, &benchmarkTime, &renderPower)){
      fprintf(stderr,"Benchmark failed! Exiting.\n");
      return 1;
    }
    else{
      fprintf(stderr,"Benchmark successful, time taken was %d seconds, giving you a render power of %d.\n", benchmarkTime, renderPower);
      _web_setrenderpower(slavekey, password, renderPower);
    }
  }

  // Main loop
  while(!quit)
    {

    // request work
    fprintf(stderr,"Requesting work...\n");
    haveWork = _web_getwork(slavekey, password, &jobnum, &framenum);

    /* 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);
        mkdir(pathtoTardir, 0700);
        // int dlret = downloadTar(urltoTar, pathtoTar);
        int dlret = downloadTar(urltoJobfile, pathtoJobfile);
        if(dlret == 0)
          // fprintf(stderr,"Got data tarball\n");
          fprintf(stderr,"Got uncompressed data!\n");
        else if(dlret == 3){
          _web_resetframe(slavekey, password, jobnum, framenum);  // Unassign the frame on the server so other slaves can render it
          return 0; // ouput dir doesn't exist
        }
        else
          fprintf(stderr,"Using existing uncompressed data %s...\n", pathtoJobfile);
          //fprintf(stderr,"Using existing tarball %s...\n", pathtoTar);

        /* // Commented for decompression
        struct stat jbuffer;
        int jstatus = stat(pathtoJobfile, &jbuffer);
        if(jstatus == -1){
          fprintf(stderr,"Main job file does not exist, extracting...\n");

          // If error unpacking tarball
          if(unpackJob(pathtoJob, pathtoTar)){
            _web_resetframe(slavekey, password, jobnum, framenum);  // Unassign the frame on the server so other slaves can render it
            return 1;
          }
        }
        */

        /* ignore return because directory may exist already */
        fprintf(stderr,"Creating output directory %s\n", pathtoOutdir);
        mkdir(pathtoOutdir, 0700);
        fprintf(stderr,"Marking frame started on server... ");
        _web_startframe(slavekey, password, jobnum, framenum);

        /* Execute blender */
        fprintf(stderr,"Executing blender on file %s\n", pathtoJobfile);
        fprintf(stderr,"Directing output to file %s\n", pathtoOutput);

        if(exec_blender(pathtoJobfile, pathtoRenderOutput, framenum))
          {
            fprintf(stderr,"Error running Blender. Check your installation and/or your PATH.\n");
            _web_resetframe(slavekey, password, jobnum, framenum);  // Unassign the frame on the server so other slaves can render it
            return 1;
          }
        free(pathtoJobfile);
        pathtoJobfile = NULL;

        struct stat buffer;
        int fstatus = stat(pathtoOutput, &buffer);
        if(fstatus == -1){
          fprintf(stderr,"*** %s doesn't exist! Scene may not have camera, or your blender installation is not working.\n", pathtoOutput);
          _web_resetframe(slavekey, password, jobnum, framenum);  // Unassign the frame on the server so other slaves can render it
          return 1;
        }
        else{
          /* 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);
          urltoOutput = NULL;
          pathtoOutput = NULL;
          // Tell the server that rendering and upload are complete
          _web_finishframe(slavekey, password, jobnum, framenum);
        }
      }
    else{
      fprintf(stderr,"Nothing to do. Idling...\n");
      sleep(300); // Poll every 300 seconds @TODO: remove polling
    }

    // @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);
      }
  }

  free(my_cfg);
  free(outputExt);
  free(datadir);
  free(urltoTar);
  free(pathtoTar);
  free(pathtoTardir);
  free(pathtoJob);
  free(pathtoJobfile);
  free(urltoJobfile);
  free(urltoOutput);
  free(pathtoRenderOutput);
  free(pathtoOutdir);
  fprintf(stderr,"Goodbye!\n");
  return 0;
}