Changeset - 393ab8fcf2ee
[Not reviewed]
default
0 2 0
Ethan Zonca (ethanzonca) - 15 years ago 2010-09-13 23:00:23
e@ethanzonca.com
Fixed doublefree
2 files changed with 3 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/server/simpleslave.c
Show inline comments
 
/*
 
  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 <http://www.gnu.org/licenses/>.
 

	
 
*/
 

	
 
#include "common/config.h"
 

	
 
#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>
 

	
 
#define DEBUG 0
 

	
 

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

	
 
  multiio_context_t multiio;
 

	
 
  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;
 
  hostname = NULL;
 

	
 
  char curopt;
 
  int runBenchmark = 0;
 
  int updateConf = 0;
 
  multiio = multiio_context_new();
 

	
 
  while(((char)-1) != (curopt = getopt(argc, argv, "u:p:rh")))
 
     {
 
       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: distrensimpleslave [option] \nStarts a distren slave\n\t-u\tset Slave ID/Username (run after fresh install)\n\t-p\tset Slave Passphrase (run after fresh install)\n\t-r\tRecalculate render power (benchmark)\n\t-h\tshow this help\n");
 
           return 2;
 
         }
 
       else if(curopt == 'r')
 
         {
 
           runBenchmark = 1;
 
           break;
 
         }
 
       else if(curopt == 'u'){
 
         username = strdup(optarg);
 
         updateConf = 1;
 
       }
 
       else if(curopt == 'p'){
 
         password = strdup(optarg);
 
         updateConf = 1;
 
       }
 
     }
 

	
 
if(updateConf){
 
  if(DEBUG)
 
    fprintf(stderr, "Putting Slave ID \"%s\" and Slave Passphrase \"%s\" in distrenslave.conf\n", username, password);
 
  if(username != NULL)
 
    conf_replace("distrenslave.conf", "!username", username);
 
  if(password != NULL)
 
    conf_replace("distrenslave.conf", "!password", password);
 

	
 
  fprintf(stderr, "Please invoke distrensimpleslave with no arguments to run with the slave ID and/or passphrase you just set\n");
 
  return 0;
 
}
 
  /* Get conf data */
 
 options_init(argc, argv, &my_cfg, myopts, "slave", &commonopts, multiio);
 

	
 
  if(!datadir)
 
    {
 
      fprintf(stderr, "datadir not set\n");
 
      return 1;
 
    }
 
  if(!server)
 
    {
 
      fprintf(stderr, "server not set\n");
 
      return 1;
 
    }
 
  if(!username)
 
    {
 
      fprintf(stderr, "username not set, try the -u flag \n");
 
      return 1;
 
    }
 
  if(!password)
 
    {
 
      fprintf(stderr, "password not set, try the -p flag\n");
 
      return 1;
 
    }
 
  if(!hostname)
 
    {
 
      fprintf(stderr, "hostname not set\n");
 
      return 1;
 
    }
 

	
 
  
 
  /* 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 distrenslave.conf or try the -p flag!\n");
 
      return 1;
 
    }
 

	
 
  // Variables needed for main loop
 
  int jobnum = 0;
 
  int framenum = 0;
 
  int xres = 0;
 
  int yres = 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 uncompressed 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 *urltoJobfile; /* Used if we aren't using compression */
 
  char *pathtoJob; /* 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;
 

	
 
  fprintf(stderr,"\nDistRen SimpleSlave Pre-Alpha %s\n- Experimental build: Use at your own risk!\n\n", PACKAGE_VERSION);
 

	
 
  /* @TODO @FIXME create datadir (/var/distren/) if it doesn't exist, or notify the user */
 

	
 
  int benchmarkTime = 0;
 
  int renderPower = 0;
 

	
 
  outputExt = NULL;
 

	
 
  // @TODO: create _web function to force recalc if !isset($render_power) on server
 
  if(runBenchmark)
 
    {
 
      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);
 
	  return 0;
 
	}
 
    }
 

	
 
  if(!DEBUG)
 
    fprintf(stderr, "Running...");
 
  // Main loop
 
  while(!quit)
 
    {
 

	
 
    // request work
 
    if(DEBUG)
 
      fprintf(stderr,"Requesting work from %s...\n", hostname);
 
    haveWork = _web_getwork(slavekey, password, &jobnum, &framenum, &xres, &yres, &outputExt);
 

	
 
    /* If we got a frame */
 
    if(haveWork)
 
      {
 
        fprintf(stderr,"\nGot work from server...\n");
 
        if(DEBUG)
 
          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,"Data retrieved successfully!\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
 
          if(DEBUG)
 
            //fprintf(stderr,"Using existing uncompressed data %s...\n", pathtoJobfile);
 
            fprintf(stderr,"Using existing tarball %s...\n", pathtoTar);
 

	
 
        // Check if tar exists already
 
        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
 
            fprintf(stderr,"Extraction failed, exiting.\n");
 
            return 1;
 
          }
 
	  else
 
	    if(DEBUG)
 
              fprintf(stderr,"Whatever happened in the unpackjob() function supposedly worked.\n");
 
        }
 
	else{
 
	  if(DEBUG)
 
	    fprintf(stderr,"Using already extracted data.\n");
 
        }
 

	
 
        struct stat tbuffer;
 
        int tstatus = stat(pathtoJobfile, &tbuffer);
 
	if(tstatus == -1){
 
          fprintf(stderr,"The main job file does not exist! Data may be corrupt, or the archive is malformatted.\n");
 
          return 1;
 
        }
 

	
 
        /* ignore return because directory may exist already */
 
        if(DEBUG)
 
          fprintf(stderr,"Creating output directory %s\n", pathtoOutdir);
 
        mkdir(pathtoOutdir, 0700);
 

	
 
        if(DEBUG)
 
          fprintf(stderr,"Marking frame started on server... ");
 
        _web_startframe(slavekey, password, jobnum, framenum);
 

	
 
        /* Execute blender */
 
        if(DEBUG){
 
          fprintf(stderr,"Executing blender on file %s\n", pathtoJobfile);
 
          fprintf(stderr,"Directing output to file %s\n", pathtoOutput);
 
        }
 
        if(exec_blender(pathtoJobfile, pathtoRenderOutput, outputExt, xres, yres, 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 */
 
          if(DEBUG)
 
            fprintf(stderr, "Finished frame %d in job %d, uploading...\n", framenum, jobnum);
 
          else
 
            fprintf(stderr,"Finished.\n");
 
          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);
 
        }
 

	
 
        free(outputExt);
 
      }
 
    else{
 
      if(DEBUG)
 
        fprintf(stderr,"No work to do. Idling...\n");
 
      else
 
        fprintf(stderr,".");
 
      sleep(60); // 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(outputExt);
 
  }
 

	
 
  free(my_cfg);
 
  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;
 
}
src/server/slavefuncs.c
Show inline comments
 
/*
 
  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 <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include "common/config.h"
 

	
 
#include "distrenjob.h"
 
#include "slavefuncs.h"
 

	
 
#include "common/asprintf.h"
 
#include "common/execio.h"
 
#include "common/protocol.h"
 
#include "common/remoteio.h"
 

	
 
#include <curl/curl.h>
 
#include <curl/easy.h>
 
#include <curl/types.h>
 

	
 
#include <archive.h>
 
#include <archive_entry.h>
 

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

	
 
#include <time.h>
 

	
 
// Function debug
 
#define DEBUG 1
 
#define DEBUG 0
 

	
 
/*
 
void stringToUpper(char *string){
 
  while(*string != '\0') {
 
    *string = toupper((unsigned char)*string);
 
  }
 
}
 
*/
 

	
 
void stringToUpper(char *buffer){
 
    for(; *buffer; buffer ++)
 
      *buffer = toupper(*buffer);
 
}
 

	
 

	
 
/**
 
   Grabs the xml DOM node reached by an XPath.
 

	
 
   @param path an XPath that lead to DOM node
 
   @return the first node associated with the path or NULL if there is no match
 
 */
 
xmlNodePtr xml_quickxpath(xmlXPathContextPtr xpathctxt, xmlChar *path)
 
{
 
  xmlNodePtr toreturn;
 

	
 
  xmlXPathObjectPtr xmlxpathobjptr;
 
  xmlxpathobjptr = xmlXPathEval(path, xpathctxt);
 
  if(!xmlxpathobjptr
 
     || !xmlxpathobjptr->nodesetval->nodeNr)
 
    {
 
      fprintf(stderr, "XPath resolution failed for ``%s'' in ``%s'' (``%s'')\n", path, xpathctxt->doc->name, xpathctxt->doc->URL);
 
      return (xmlNodePtr)NULL;
 
    }
 

	
 
  toreturn = *(xmlxpathobjptr->nodesetval->nodeTab);
 

	
 
  xmlXPathFreeObject(xmlxpathobjptr);
 

	
 
  return toreturn;
 
}
 

	
 

	
 
/** Deletes job data from the disk. @TODO: add error checking! */
 
int delete_jobdata(int jobnum, char *datadir)
 
{
 
  char *jobpath;
 
  char *jobcont;
 
  _distren_asprintf(&jobpath, "%s/%d", datadir, jobnum);
 
  _distren_asprintf(&jobcont, "%s/%d/*", datadir, jobnum);
 
  remove(jobcont);
 
  rmdir(jobpath);
 
  fprintf(stderr, "Removed files in %s/%d/ if everything was successful\n", jobpath, jobnum);
 
  free(jobpath);
 
  free(jobcont);
 
  return 0;
 
}
 

	
 
/** Function referenced by curlget() to write data to disk. */
 
size_t curl_writetodisk(void *ptr, size_t size, size_t nmemb, FILE *stream)
 
 {
 
    return fwrite(ptr, size, nmemb, stream);
 
  }
 

	
 
/** Helper function for cURL's progress display */
 
int curl_progress(char *Bar, double t, double d, double ultotal, double ulnow)
 
{
 
fprintf(stderr,"Downloading: %f%% complete\r",d/t*100);
 
return 0;
 
}
 

	
 
/** Retrieves a URL with cURL and saves it to disk */
 
CURLcode curlget(char *url, char *out){
 
  fprintf(stderr,"Preparing to download %s\n",url);
 
  double *Bar; // Stores cURL progress display info
 
  CURL *curl;
 
  CURLcode res;
 
  FILE *outfile;
 

	
 
  res = CURLE_FAILED_INIT;
 
  curl = curl_easy_init();
 
  if(curl)
 
    {
 
    outfile = fopen(out, "w"); // Open where we're writing to
 
    if(outfile == NULL)
 
      return 2; // Output dir doesn't exist
 
    curl_easy_setopt(curl, CURLOPT_URL, url);
 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writetodisk); // this MUST be set for win32 compat.
 
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
 
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&curl_progress);
 
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &Bar);
 
    res = curl_easy_perform(curl);
 
    curl_easy_cleanup(curl);
 
    fclose(outfile);
 
  }
 
  fprintf(stderr,"\n"); // Clears out he progressbar's carriage return
 
  return res; // 0 is OK, 1 is 404 or other error
 
}
 

	
 
/** Posts a file to a url with cUrl */
 
CURLcode curlpost(char *filename, char *url, int jobnum, int framenum, int slavekey)
 
{
 
  char *targetname = "uploadedfile"; // Name of the target in the php file on the server (Don't change me unless you have different PHP code)
 
  CURL *curl;
 
  CURLcode res;
 
  struct curl_httppost *formpost=NULL;
 
  struct curl_httppost *lastptr=NULL;
 
  struct curl_slist *headerlist=NULL;
 
  static const char buf[] = "Expect:";
 

	
 
  char *sjobnum;
 
  char *sframenum;
 
  char *sslavekey;
 

	
 
  if(DEBUG)
 
    fprintf(stderr,"Uploading to %s\n", url);
 

	
 
  _distren_asprintf(&sjobnum,"%d",jobnum);
 
  _distren_asprintf(&sframenum,"%d",framenum);
 
  _distren_asprintf(&sslavekey,"%d",slavekey);
 

	
 
  curl_global_init(CURL_GLOBAL_ALL);
 

	
 
  /* jobnum field... */
 
   curl_formadd(&formpost,
 
                &lastptr,
 
                CURLFORM_COPYNAME, "jobnum",
 
                CURLFORM_COPYCONTENTS, sjobnum, CURLFORM_END);
 
  /* framenum field... */
 
  curl_formadd(&formpost,
 
               &lastptr,
 
               CURLFORM_COPYNAME, "framenum",
 
               CURLFORM_COPYCONTENTS, sframenum, CURLFORM_END);
 
  /* slavekey field... */
 
  curl_formadd(&formpost,
 
               &lastptr,
 
               CURLFORM_COPYNAME, "slavekey",
 
               CURLFORM_COPYCONTENTS, sslavekey, CURLFORM_END);
 
  /* upload field... */
 
  curl_formadd(&formpost,
 
               &lastptr,
 
               CURLFORM_COPYNAME, targetname,
 
               CURLFORM_FILE, filename,
 
               CURLFORM_END);
 
  /* filename field... */
 
  curl_formadd(&formpost,
 
               &lastptr,
 
               CURLFORM_COPYNAME, "filename",
 
               CURLFORM_COPYCONTENTS, filename,
 
               CURLFORM_END);
 
  /* submit field, not usually needed, just in case... */
 
  curl_formadd(&formpost,
 
               &lastptr,
 
               CURLFORM_COPYNAME, "submit",
 
               CURLFORM_COPYCONTENTS, "send",
 
               CURLFORM_END);
 

	
 
  res = CURLE_FAILED_INIT;
 
  curl = curl_easy_init();
 
  headerlist = curl_slist_append(headerlist, buf);
 
  if(curl)
 
    {
 
    /* Setting the URL to get the post, and the contents of the post */
 
    curl_easy_setopt(curl, CURLOPT_URL, url);
 
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
 
    res = curl_easy_perform(curl);
 

	
 
    curl_easy_cleanup(curl);
 
    /* cleanup the formpost junk */
 
    curl_formfree(formpost);
 
    curl_slist_free_all (headerlist);
 
    free(sjobnum);
 
    free(sframenum);
 
    free(sslavekey);
 
    }
 
  return res;
 
}
 

	
 
/** Replaces wordtoreplace with replacewith in conffile (relative to SYSCONFDIR) */
 
int conf_replace(char *conffile, char *wordtoreplace, char *replacewith){
 
  int maxlinelen = 120;
 
  char *fileOrig;
 
  char *fileRepl;
 
  _distren_asprintf(&fileOrig, "%s/%s", SYSCONFDIR, conffile);
 
  _distren_asprintf(&fileRepl, "%s%s.edited", SYSCONFDIR, conffile);
 
  char buffer[maxlinelen+2];
 
  char *buff_ptr, *find_ptr;
 
  FILE *fp1, *fp2;
 
  size_t find_len = strlen(wordtoreplace);
 
  fp1 = fopen(fileOrig,"r");
 
  fp2 = fopen(fileRepl,"w");
 
  if (fp1 ==NULL){
 
    fprintf(stderr, "%s doesn't exist\n",fileOrig);
 
    return 0;
 
  }
 
  else if(fp2 ==NULL){
 
    fprintf(stderr, "Can't write a file to disk! Check permissions.\n");
 
    return 0;
 
  }
 
  else{
 
    while(fgets(buffer,maxlinelen+2,fp1))
 
      {
 
        buff_ptr = buffer;
 
        while ((find_ptr = strstr(buff_ptr,wordtoreplace)))
 
        {
 
           while(buff_ptr < find_ptr)
 
             fputc((int)*buff_ptr++,fp2);
 
           fputs(replacewith,fp2);
 
           buff_ptr += find_len;
 
         }
 
         fputs(buff_ptr,fp2);
 
      }
 
    rename(fileRepl, fileOrig);
 
  }
 
  fclose(fp2);
 
  fclose(fp1);
 
  fprintf(stderr,"Wrote conf file...\n");
 
return 1; // Success
 
}
 

	
 

	
 
/* Executors */
 

	
 
/** Executor function for Blender operations */
 
int exec_blender(char *input, char *output, char *outputExt, int xres, int yres, int frame)
 
{
 
  int ret;
 

	
 
  stringToUpper(outputExt);
 

	
 
  char *frame_str;
 
  _distren_asprintf(&frame_str, "%i", frame);
 

	
 
  char *xres_str;
 
  _distren_asprintf(&xres_str, "%i", xres);
 

	
 
  char *yres_str;
 
  _distren_asprintf(&yres_str, "%i", yres);
 

	
 
  char *command = "blender"; // @TODO: We currently expect this to be in PATH
 
  char *cmd[] = { command, "-b", input, "-o", output, "-F", outputExt, "-f", frame_str, "-t", "0", (char *)NULL }; // arguments for blender
 

	
 
  if(DEBUG)
 
    fprintf(stderr,"Preparing to execute command: %s -b %s -o %s -f %s\n", command, input, output, frame_str);
 

	
 
  char buf[20];
 
  struct execio *testrem;
 
  size_t readlen;
 

	
 
  if(DEBUG)
 
    fprintf(stderr,"Executing: %s\n", frame_str);
 

	
 
  ret = execio_open(&testrem, command, cmd);
 
  if(ret)
 
    {
 
      fprintf(stderr, "Error running blender\n");
 
      return 1;
 
    }
 
  buf[19] = '\0';
 
  while(!execio_read(testrem, buf, 19, &readlen))
 
    {
 
       buf[readlen] = '\0';
 
       if(DEBUG)
 
         fprintf(stderr, "read \"%s\"\n", buf);
 
    }
 
  execio_close(testrem);
 
  free(frame_str);
 
  return ret;
 
}
 

	
 
void xmlinit()
 
{
 
  xmlInitParser();
 
  xmlXPathInit();
 
}
 

	
 
void xmlcleanup()
 
{
 
  xmlCleanupParser();
 
}
 

	
 

	
 
/** Creates directories recursively */
 
int distren_mkdir_recurse(const char *dirname)
 
{
 
  size_t counter;
 
  char *nextdir;
 
  int ret;
 

	
 
  nextdir = strdup(dirname);
 
  /* skip preficing slashes */
 
  for(counter = 0; nextdir[counter] == '/'; counter ++)
 
    ;
 
  for(; nextdir[counter]; counter ++)
 
    {
 
      /** @TODO OS-portabalize the path-separators */
 
      if(nextdir[counter] == '/')
 
        {
 
          nextdir[counter] = '\0';
 
          ret = mkdir(nextdir, S_IRWXU | S_IRGRP | S_IROTH);
 
	  if(ret == -1
 
	     && errno != EEXIST)
 
	    {
 
	      perror("mkdir");
 
	      free(nextdir);
 
	      return 1;
 
	    }
 
          nextdir[counter] = '/';
 
        }
 
    }
 
  ret = mkdir(nextdir, S_IRWXU | S_IRGRP | S_IROTH);
 
  if(ret == -1
 
     && errno != EEXIST)
 
    {
 
      perror("mkdir");
 
      free(nextdir);
 
      return 1;
 
    }
 
  free(nextdir);
 

	
 
  return 0;
 
}
 

	
 
/**
 
 @TODO: Use for constructing path to job data locally and/or on data.distren.org
 
 */
 
int job_build_path(char *filename, unsigned int jobnum)
 
{
 
  return 0;
 
}
 

	
 

	
 
int downloadTar(char *url, char *destinationPath){
 
  // Prepare to download the job tar if it isn't  present
 
  struct stat buffer;
 
  int fstatus = stat(destinationPath, &buffer);
 
  if(fstatus == -1)
 
    {
 
      // Download the Tar
 
      int ret = curlget(url, destinationPath);
 
      if(ret == 0){
 
        fprintf(stderr, "Job data retrieved successfully\n");
 
        // free(url); @FIXME: causes doublefree! Curl must free the url?
 
        return 0;
 
      }
 
      else if(ret == 1){
 
        fprintf(stderr, "Downloading job data from %s failed. Check your network connection.\n",url);
 
        free(url);
 
        return 1; // Eventually make a retry loop
 
      }
 
    }
 
  if(DEBUG)
 
    fprintf(stderr, "Tar at %s already exists! Download cancelled.\n", destinationPath);
 
  return 2;
 
}
 

	
 

	
 
int uploadOutput(char *pathtoOutput, char *urltoOutput, int jobnum, int framenum, int slavekey){
 
  //fprintf(stderr,"Uploading output %s to url %s for job %d and frame %d for slavekey %d", pathtoOutput, urltoOutput, jobnum, framenum, slavekey);
 
  if( !curlpost(pathtoOutput, urltoOutput, jobnum, framenum, slavekey)) // Uploads output
 
    {
 
      if(DEBUG)
 
        fprintf(stderr,"Upload successful, removing old output...\n");
 
      else
 
        fprintf(stderr,"Uploaded.\n");
 

	
 
      remove(pathtoOutput); // Delete the file after its uploaded
 
      return 0;
 
    }
 
  else
 
    {
 
      fprintf(stderr,"Upload failed. Check your network connection. Retrying upload...\n");
 
      int tries=1;
 
      while(tries<=10 && curlpost(pathtoOutput, urltoOutput, jobnum, framenum, slavekey))
 
        {
 
          fprintf(stderr, "Upload failed. Trying again in 10 seconds... (attempt %d of 10)\n", tries);
 
          tries++;
 
          sleep(10);
 
        }
 
      return 1; // Upload failed after multiple tries
 
      // @FUTURE: Keep track of files that we were unable to upload, and upload them later
 
    }
 
}
 

	
0 comments (0 inline, 0 general)