Files @ 12f00f880402
Branch filter:

Location: DistRen/src/server/slave.c

ethanzonca@localhost.localdomain
Added test code for execio, minor edits
/*
  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 "protocol.h"
#include "options.h"
#include "slavefuncs.h"
#include "asprintf.h"
#include "remoteio.h"

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

int main(int argc, char *argv[])
{

  int counter;

  /* Parse arguments */
  for(counter = 0; counter < argc; counter ++)
    if(strcmp(argv[counter], "-h") == 0)
      {
	fprintf(stderr, "Usage: distrenslave [option] \nStarts a distren slave\n\t-h\tshow this help\n"); /* <username> <emailaddr> \t-c\tregisters a user with [username] and [emailaddr] \n */
	return 2;
      }

  /* Get conf data */
  char *username;
  char *datadir;
  cfg_t * my_cfg;
  cfg_opt_t myopts[] = {
    CFG_SIMPLE_STR("username", &username),
    CFG_SIMPLE_STR("datadir", &datadir),
    CFG_END()
  };
  struct options_common *commonopts;
  username = NULL;
  options_init(argc, argv, &my_cfg, myopts, "slave", &commonopts);


  /* Notifies the user if there no username in .conf */
  if(username == NULL || strcmp(username, "!username") == 0 )
    fprintf(stderr, "\nYou didn't register!\nPlease register on the DistRen website.\nIf this error persists, check distrenslave.conf to ensure all items are filled.\n");
  else 
    if( username != NULL || strcmp(username, "!username") != 0 )
      {
	// Log in the user
	if(login_user(username) == 1){
	  fprintf(stderr, "You should now be logged into distren.\n");
	}
	else
	  {
	    fprintf(stderr, "Login failed.\n");
	    return 0;
	  }
      }
    else
      {
	fprintf(stderr, "Something is terribly wrong!");
      }



  /* Code-filled Variables  */
  int jobnum;          /* The job number that we're currently working */
  int framenum;        /* @TODO: Remotio should fill this */

  int busy = 0;        /* Client business 1=busy 0=idle */

  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 *pathtoJobfile; /* Full path to the job's main file */
  char *pathtoXml;     /* Full path to the job's xml file */
  char *pathtoOutput;  /* Full path to the output (rendered) file */
  char *outputExt;     /* Output Extension (e.g., JPG) */

  char *tarcmd;        /* Command to run for tar. Migrate to libtar sometime */
  char *outdir;        /* Output Directory for tar */
  char *jobdatapath;   /* Path to job data */

  struct distrenjob *myjob; /* Structure to hold data gathered from the XML file */

  int cont = 0;
  int framesInLocalQueue = 0;

  while(cont)
    {
    /* If we got a frame */
    if(framesInLocalQueue > 0)
      {
        /* @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 */
        jobnum = 0;
        //framenum = remoteio_read(jobnum); /* Set framenum from remoteio */
        framenum = 0;

        fprintf(stderr, "Preparing to render frame %d in job %d\n", framenum, jobnum);

        /**
           Variable Preparation
           @todo find where to free() all of these
        */
        _distren_asprintf(&jobdatapath, "job%d", jobnum);
        _distren_asprintf(&urltoTar, "http://protofusion.org/distren/stor/job%d/job%d.tar.gz", jobnum); // Prepares URL to download from
        _distren_asprintf(&pathtoTar, "%s/stor/jobdata/job%d.tar.gz", datadir, jobnum); // Prepares destination to save to
        _distren_asprintf(&pathtoJobfile, "%s/%s/job.blend", datadir, jobdatapath ); // Prepares the path to the jobfile
        _distren_asprintf(&urltoOutput, "http://protofusion.org/distren/stor/tmp/", jobdatapath ); // Prepares the URL where output is posted
        _distren_asprintf(&pathtoXml, "%s/job%d/job%d.xml", datadir, jobnum ); // Prepares the path to the job's XML file

        // Downloads the job tar if it isn't  present.
        struct stat buffer;
        int fstatus = stat(pathtoJobfile, &buffer);
        if(fstatus == -1)
          {
            /* Downloads the Tar */
            if( curlget(urltoTar, pathtoTar) == 0)
              fprintf(stderr, "Job data retrieved successfully\n");
            else
              fprintf(stderr, "Downloading job data from server failed. Check your network connection.\n");
          }
        else
          fprintf(stderr, "Using cached job file...\n");

        _distren_asprintf(&outdir, "/tmp/distren/job%d", jobnum); /*< @TODO: free() */
        mkdir("/tmp/distren", 0750); /* @TODO: Make this less *nix-specific */
        mkdir(outdir, 0750);

        _distren_asprintf(&tarcmd, "tar -xvf \"%s\" -C \"%s\"", pathtoTar, outdir); /* @TODO: Make this portable. Libtar or something? */
        system(tarcmd);
        free(tarcmd);

        /* Parses a job's XML file, puts data in the myjob struct */
        if(xml2distrenjob(&myjob, pathtoXml) == 0)
          {
            fprintf(stderr, "Well, the XML craziness may have worked. Maybe. \n");

            /* Frees things up if it was successful. xml2distrenjob() really (usually) only fails if malloc'ing inside it fails */
            distrenjob_free(&myjob);
          }
        else
          {
            fprintf(stderr, "I think the XML craziness may have failed, so I'll terminate just for fun.\n");
            return 1;
          }

        /* Variable-fillers which require XML */
        outputExt = myjob->output_format; /* @TODO: FIXME! <-- I WILL! */
        /* Prepares the path to the jobfile */
        _distren_asprintf(&pathtoOutput, "%s/job%d/output/job%d-frame%d.%s", datadir, jobnum, jobnum, framenum, outputExt );


        /** Series of ifs for jobtype based on xml content */
        while(1 == 1){
          exec_blender(pathtoJobfile, pathtoOutput, framenum); /* @TODO: This warning should be fixed :D */
          break;
        }

        /* When blender is finished, run this... */
        fprintf(stderr, "Finished frame %d in job %d, uploading...", framenum, jobnum);
        curlpost(pathtoOutput, urltoOutput); /* uploads (HTML POST) the output at outputpath to the server at outputurl */
        tell_the_server(DISTREN_REQUEST_DONEFRAME); /* Tells the server that it's finished rendering this frame */
        busy = 0;
        /* Slave now becomes idle, doesn't need to tell the server anything, ssh handles this. */
        framesInLocalQueue--;
      }

    // If the server says that every frame for the last jobnum is finished, OR if the data is getting old
    if(1 == 0){
      delete_jobdata(jobnum, datadir);
    }
  }
/* Test code for execio
  fprintf(stderr,"Testing out execioness");
  exec_blender("/home/ethanzonca/Blender/houses.blend", "/home/ethanzonca/Blender/out.png", 1);
  */
  return 0;
}