Changeset - 9a7f470708e2
[Not reviewed]
default
0 2 0
Nathan Brink (binki) - 16 years ago 2010-01-11 15:06:46
ohnobinki@ohnopublishing.net
improve vardir support
cleanup prepare_distrenjob()
fix jobs_in_queue consistency
2 files changed with 54 insertions and 40 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -83,25 +83,25 @@ struct general_info
 
void distrenjob_remove(struct general_info *, struct distrenjob *bj);
 

	
 
struct distrenjob *distrenjob_get(struct distrenjob *head, jobnum_t jobnum);
 
int distrenjob_enqueue(struct general_info *, struct distrenjob *job);
 
int mortition(struct general_info *, struct distrenjob *job);
 
int update_xml_joblist(struct general_info *);
 
int createQueueFromXML(struct general_info*);
 
int reCreateQueueFromXML(struct general_info*, xmlDocPtr doc, xmlNodePtr current);
 
void update_general_info(struct general_info*);
 
int import_general_info(struct general_info*);
 
int updateJobStatsXML(struct distrenjob *job);
 

	
 
char *job_getserialfilename(struct general_info *, unsigned int jobnum);
 
int job_getserialfilename(char **filename, struct general_info *, unsigned int jobnum, int createdir);
 
int distren_mkdir_recurse(char *fname);
 

	
 
/* ********************** Functions ************************* */
 

	
 
/** Dumps all data in RAM to an xml file (such as current jobs, etc) which is parsed by start_data. Remember to invoke this before shutting down! @TODO: Fill this stub*/
 
int xml_dump()
 
{
 
  return 0;
 
}
 
/**
 
   Performs command stored in a client's request. @TODO: Fill stub
 
*/
 
@@ -129,25 +129,25 @@ int start_data(struct general_info *gene
 
  general_info->total_finished_jobs = 0;
 
  general_info->total_frames_rendered = 0;
 
  general_info->highest_jobnum = 0;
 
  general_info->hibernate = 0;
 
  general_info->timestamp = 0;
 
  general_info->total_render_power = 0;
 
  general_info->total_priority_pieces = 0;
 

	
 
  fprintf(stderr, "Initialized default global and queue states\n");
 

	
 
  if(stat(general_info->files.geninfo, &buffer) == 0)
 
    {
 
      fprintf(stderr, "Previous state file found, loading:\n");
 
      fprintf(stderr, "Previous state file found; loading ``%s'':\n", general_info->files.geninfo);
 

	
 
      fprintf(stderr, "Parsing XML files and restoring previous state...\n");
 
      if(import_general_info(general_info))
 
	fprintf(stderr, "FAILURE\n");
 
      
 
      fprintf(stderr, "Restoring queue...\n");
 
      if(createQueueFromXML(general_info))
 
	fprintf(stderr, "FAILURE\n");
 
      
 
      fprintf(stderr, "done\n");
 
    }
 
  
 
@@ -197,25 +197,24 @@ int mortition(struct general_info *genin
 
          isJobDone = 0;
 
        }
 
      free(path_and_number);
 
    }
 

	
 
  if(isJobDone)
 
    {
 
      /**
 
	 all frames were accounted for
 
      */
 
      distrenjob_remove(geninfo, job);
 
      distrenjob_free(&job);
 
      geninfo->jobs_in_queue --;
 
      update_xml_joblist(geninfo);
 
    }
 
  else
 
    /**
 
       if the job isn't done, have frame_finder() start from the first frame, allowing it to see the frames that are now unassigned 
 
    */
 
    job->prev_frame_index = -1;
 

	
 
  update_general_info(geninfo);
 

	
 
  return 0;
 
}
 
@@ -243,96 +242,97 @@ int restoreJobState(struct distrenjob *j
 
        }
 
      else
 
        isJobDone = 0;
 
      free(path_and_number);
 
    }
 

	
 
  return !isJobDone;
 
}
 

	
 
/**
 
   creates a structure from starting data, then calls another
 
   function to actually add that struct to the queue.
 

	
 
   Passed strings must be free()d by the caller.
 
*/
 
int prepare_distrenjob(struct general_info *geninfo, int type, char *name, char *submitter, char *email, int priority, int start_frame, int end_frame, int width, int height)
 
{
 
  int counter;
 
  int counter2;
 
  int tmp;
 
  char *path_with_num;
 
  char *serialfile;
 

	
 
  struct distrenjob *distrenjob;
 
  tmp = distrenjob_new(&distrenjob);
 
  if(tmp)
 
    return 1;
 

	
 
  geninfo->highest_jobnum ++;
 
  distrenjob->jobnum = geninfo->highest_jobnum;
 

	
 
  distrenjob->type = 1;
 
  distrenjob->name = name;
 
  distrenjob->submitter = submitter;
 
  distrenjob->email = email;
 
  distrenjob->name = strdup(name);
 
  distrenjob->submitter = strdup(submitter);
 
  distrenjob->email = strdup(email);
 
  distrenjob->priority = priority;
 
  distrenjob->width = width;
 
  distrenjob->height = height;
 
  /** sets the total number of frames in animation for status purposes */
 
  distrenjob->total_frames = (end_frame - start_frame + 1);
 
  distrenjob->frameset = malloc(sizeof(struct frameset) * distrenjob->total_frames);
 
  if(!distrenjob->frameset)
 
    {
 
      distrenjob_free(&distrenjob);
 
      fprintf(stderr, "OOM\n");
 
      
 
      return 1;
 
    }
 

	
 
  /** prepares all the frames by setting that status to "unassigned" */
 
  /** initialize frameset */
 
  counter2 = start_frame;
 
  for(counter = 0; counter < distrenjob->total_frames; counter++){
 
    distrenjob->frameset[counter].num = counter2;
 
    distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 
  for(counter = 0; counter < distrenjob->total_frames; counter++)
 
    {
 
      distrenjob->frameset[counter].num = counter2;
 
      distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 
      
 
      counter2 ++;
 
    }
 

	
 
    counter2++;
 
  }
 

	
 
  _distren_asprintf(&path_with_num, "stor/job%d/out/", distrenjob->jobnum);
 
  distren_mkdir_recurse(path_with_num);
 
  serialfile = job_getserialfilename(geninfo, distrenjob->jobnum);
 

	
 
  free(path_with_num);
 
  job_getserialfilename(&serialfile, geninfo, distrenjob->jobnum, 1);
 

	
 
  /**
 
     add job to queue
 
  */
 
  fprintf(stderr, "\nprepare_distrenjob: attempting distrenjob_serialize()\n");
 
  fprintf(stderr, "prepare_distrenjob(): attempting distrenjob_serialize(%d, \"%s\")\n",
 
	  distrenjob->jobnum, serialfile);
 
  distrenjob_serialize(distrenjob, serialfile);
 
  free(serialfile);
 

	
 
  fprintf(stderr, "\nprepare_distrenjob: attempting distrenjob_enqueue()\n");
 
  fprintf(stderr, "prepare_distrenjob(): attempting distrenjob_enqueue()\n");
 
  distrenjob_enqueue(geninfo, distrenjob);
 

	
 
  geninfo->jobs_in_queue ++;
 
  fprintf(stderr, "\nprepare_distrenjob: attempting update_xml_joblist()\n");
 
  fprintf(stderr, "prepare_distrenjob(): attempting update_xml_joblist()\n");
 
  update_xml_joblist(geninfo);
 
  fprintf(stderr, "\nprepare_distrenjob: attempting update_general_info()\n");
 
  fprintf(stderr, "prepare_distrenjob(): attempting update_general_info()\n");
 
  update_general_info(geninfo);
 
  fprintf(stderr, "\nprepare_distrenjob: attempting updateJobStatsXML()\n");
 
  fprintf(stderr, "prepare_distrenjob(): attempting updateJobStatsXML()\n");
 
  updateJobStatsXML(distrenjob);
 

	
 
  return 0;
 
}
 

	
 

	
 
/**
 
   distrenjob_enqueue: This function adds the job to the queue based on its priority
 
   Adds the job to the queue based on its priority.
 
   Updates geninfo->jobs_in_queue.
 
*/
 
int distrenjob_enqueue(struct general_info *geninfo, struct distrenjob *job)
 
{
 
  struct distrenjob *prev_job;
 
  struct distrenjob *current_job;
 
  struct distrenjob *head;
 

	
 
  head = &geninfo->head;
 
  prev_job = head;
 

	
 
  /**
 
     iterate through linked jobs
 
@@ -340,38 +340,40 @@ int distrenjob_enqueue(struct general_in
 
  for(current_job = head->next; current_job; current_job = current_job->next)
 
  {
 
    fprintf(stderr, "enqueue loop iteration\n");
 
    if(job->priority < current_job->priority)
 
      {
 
	/**
 
	   if job's priority is less than current_job's priority, insert job
 
	   keep in mind 1 is the highest priority given to jobs, head has a
 
	   priority of zero so it will always be before other jobs
 
	*/
 
	prev_job->next = job;
 
	job->next = current_job;
 
	fprintf(stderr, "adding job before jobname: %s\n", current_job->name);
 
	fprintf(stderr, "added job before jobname: ``%s''\n", current_job->name);
 

	
 
	geninfo->jobs_in_queue ++;
 
	return 0;
 
      }
 

	
 
    prev_job = current_job;
 
  }
 

	
 
  /**
 
     if it has reached the end of the list, add job there
 
  */
 
  prev_job->next = job;
 
  fprintf(stderr, "adding job at end of queue\n");
 
  fprintf(stderr, "added job at end of queue\n");
 

	
 
  geninfo->jobs_in_queue ++;
 
  return 0;
 
}
 

	
 
/** Changes the priority of an existing (and maybe running) job. @arg head I may end up changing the head if job == head */
 
int change_job_priority(struct general_info *geninfo, struct distrenjob *job, int new_priority){
 
  struct distrenjob *current_job;
 
  struct distrenjob *prev_job;
 
  char *serialname;
 

	
 
  distrenjob_remove(geninfo, job);
 
  job->priority = new_priority;
 

	
 
@@ -392,25 +394,25 @@ int change_job_priority(struct general_i
 
    for(current_job = &geninfo->head;
 
	current_job != NULL
 
	  && job->priority > current_job->priority;
 
	current_job = current_job->next)
 
      prev_job = current_job;
 

	
 
    prev_job->next = job;
 
    job->next = current_job;
 

	
 

	
 
  update_xml_joblist(geninfo);
 
  /** reserialize after changes */
 
  serialname = job_getserialfilename(geninfo, job->jobnum);
 
  job_getserialfilename(&serialname, geninfo, job->jobnum, 0);
 
  distrenjob_serialize(job, serialname);
 
  free(serialname);
 

	
 
  return 0;
 
}
 

	
 
/**
 
  Frame Finder: matches your computer up with a lovely frame to render, starts looking at oldest job first
 
  @TODO: We must return both jobnum and framenum
 
  @TODO: Add calls in main()
 
  @return 0 success, other: error
 
*/
 
@@ -621,25 +623,27 @@ struct distrenjob *distrenjob_get(struct
 
    The conditions of the for loop will leave distrenjob_ptr at NULL if the end of the list is reached. It will leave it pointing to the correct job if it is found.
 
   */
 
  for(distrenjob_ptr = head;
 
      distrenjob_ptr
 
        && distrenjob_ptr->jobnum != jobnum;
 
      distrenjob_ptr = distrenjob_ptr->next);
 

	
 
  return distrenjob_ptr;
 
}
 

	
 

	
 
/**
 
   Removes a distrenjob from the distrenjob linked list. It does not free the distrenjob, however. You should do that with distrenjob_free() from distrenjob.h
 
   Removes a distrenjob from the distrenjob linked list. It does not free the
 
   distrenjob, however. You should do that with distrenjob_free() from distrenjob.h.
 
   Updates geninfo->jobs_in_queue.
 

	
 
   @arg head pointer to the head of the linkedlist of distrenjobs
 
 */
 
void distrenjob_remove(struct general_info *geninfo, struct distrenjob *bj)
 
{
 
  struct distrenjob *previous_distrenjob;
 

	
 
  for(previous_distrenjob = &geninfo->head;
 
      previous_distrenjob
 
	&& previous_distrenjob->next != bj; /*< stop on the distrenjob that comes before bj */
 
      previous_distrenjob = previous_distrenjob->next)
 
    ;
 
@@ -732,25 +736,28 @@ void update_general_info(struct general_
 
  _distren_asprintf(&tmp, "%d", geninfo->total_frames_rendered);
 
  xmlTextWriterWriteElement(writer, (xmlChar*)"total_frames_rendered", (xmlChar*)tmp);
 
  free(tmp);
 

	
 
  _distren_asprintf(&tmp, "%d", geninfo->highest_jobnum);
 
  xmlTextWriterWriteElement(writer, (xmlChar*)"highest_jobnum", (xmlChar*)tmp);
 
  free(tmp);
 

	
 
  xmlTextWriterEndDocument(writer);
 
  xmlFreeTextWriter(writer);
 
}
 

	
 
// this reads the information from general_info.xml to the general_info structure
 
/**
 
   Reads general state information from general_info.xml
 
   into the general_info structure.
 
*/
 
int import_general_info(struct general_info *general_info)
 
{
 
  xmlDocPtr doc;
 
  xmlNodePtr cur;
 

	
 
  doc = xmlParseFile(general_info->files.geninfo);
 
  cur = xmlDocGetRootElement(doc);
 
  if (xmlStrcmp(cur->name, (xmlChar*)"general_info"))
 
    {
 
      fprintf(stderr, "xml document is wrong type");
 
      xmlFreeDoc(doc);
 
      return 1;
 
@@ -781,25 +788,25 @@ int import_general_info(struct general_i
 
// extracts data from the xml created by above function and creates a job from it
 
// it returns a pointer to the created job
 
struct distrenjob *createJobFromXML(struct general_info *geninfo, unsigned int jobnum)
 
{
 
  xmlDocPtr doc;
 
  xmlNodePtr cur;
 
  char *file_name;
 
  struct distrenjob *distrenjob;
 
  int start_frame;
 
  int counter;
 
  int counter2;
 

	
 
  file_name = job_getserialfilename(geninfo, jobnum);
 
  job_getserialfilename(&file_name, geninfo, jobnum, 0);
 

	
 
  doc = xmlParseFile(file_name);
 
  if(!doc)
 
    return NULL;
 

	
 
  distrenjob_new(&distrenjob);
 

	
 
  cur = xmlDocGetRootElement(doc);
 

	
 
  distrenjob->name = (char*)xmlGetProp(cur, (xmlChar*)"name");
 
  distrenjob->submitter = (char*)xmlGetProp(cur, (xmlChar*)"submitter");
 
  distrenjob->priority = atoi((char*)xmlGetProp(cur, (xmlChar*)"priority"));
 
@@ -1309,37 +1316,41 @@ int main(int argc, char *argv[])
 

	
 
  xmlcleanup();
 

	
 
  /** free() paths */
 
  free(general_info.files.geninfo);
 

	
 
  return 0;
 
}
 

	
 
/**
 
   constructs the filename for a distrenjob's serialized XML
 
   to be stored/retrieved from/in.
 
   @return pointer to filename allocated using something
 
   @arg filename pointer to filename allocated using something
 
           malloc() and free() compatible. Must be free()ed by the
 
	   caller
 
   @return 0 on success
 
 */
 
char *job_getserialfilename(struct general_info *geninfo, unsigned int jobnum)
 
int job_getserialfilename(char **filename, struct general_info *geninfo, unsigned int jobnum, int createdir)
 
{
 
  char *filename;
 

	
 
  _distren_asprintf(&filename, "%s/stor/job/%d/distrenjob.xml",
 
  _distren_asprintf(filename, "%s/stor/job/%d/distrenjob.xml",
 
		    geninfo->config->datadir,
 
		    jobnum);
 

	
 
  return filename;
 
  if(!*filename)
 
    return 1;
 
  
 
  if(createdir)
 
    return distren_mkdir_recurse(*filename);
 
  
 
  return 0;
 
}
 

	
 
int distren_mkdir_recurse(char *dirname)
 
{
 
  size_t counter;
 
  char *nextdir;
 

	
 
  nextdir = strdup(dirname);
 
  for(counter = 0; nextdir[counter]; counter ++)
 
    {
 
      /** @TODO OS-portabalize the path-separators */
 
      if(nextdir[counter] == '/')
src/server/distrenjob.h
Show inline comments
 
@@ -23,25 +23,26 @@
 

	
 
/**
 
   This file stores the distrenjob and frameset structs and prototypes for some functions to manipulate/use these.
 
 */
 

	
 
#include <time.h> /*< clock_t, time_t */
 

	
 
typedef unsigned int jobnum_t;
 

	
 
/**
 
   Stores Blender Job Info
 
*/
 
struct distrenjob {
 
struct distrenjob
 
{
 
  struct distrenjob *next; /*< next will be NULL unless if there is another distrenjob */
 
  short int type; /*< 1:Blender, 2:something else */
 
  char *name;
 
  char *submitter;
 
  char *email; /*< This should be looked up based on the value of submitter, not stored in this struct */
 
  jobnum_t jobnum;
 
  int width; /*< width in pixels of the frames to be rendered */
 
  int height; /*< height in pixels of the frames to be rendered */
 
  int priority;  /*< 1 is lowest, 10 is highest, 0 means the job is done */
 
  int completed_frames; /*< number of completed frames for stats/etc */
 
  int assigned_frames; /*< number of assigned frames (that are not yet completed) for stats/etc */
 
  int total_frames; /*< how many frames are in the animation for stats/etc (unassigned frames) */
 
@@ -98,16 +99,18 @@ int distrenjob_serialize(struct distrenj
 
/**
 
   support function for distrenjob_unserialize() to help cleaning up a
 
   struct distrenjob when it is incompletely initialized.
 
   Also acts as a general-purpose struct distrenjob free()er ;-)
 
 */
 
void distrenjob_free(struct distrenjob **distrenjob);
 

	
 
/**
 
   initializes an empty, pointless struct distrenjob. This
 
   DOES run malloc() for you. It could return nonzero on error,
 
   but there are no errors to have yet (except for nomem). This
 
   sets all char* to NULL.
 

	
 
   You have to initialize your own frameset.
 
 */
 
int distrenjob_new(struct distrenjob **distrenjob);
 

	
 
#endif
0 comments (0 inline, 0 general)