Changeset - 6a550a53b903
[Not reviewed]
default
0 1 0
LordOfWar - 16 years ago 2009-10-13 22:01:38

updated createJobFromXML()
1 file changed with 12 insertions and 10 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -177,193 +177,193 @@ void finish_frame(struct distrenjob *hea
 
    }
 

	
 
  updateGeneralInfo();
 
  updateJobStatsXML(distrenjob);
 
}
 

	
 
/** "mortition" check to see if a job is actually done by scanning the folder of the job to make sure all frames are present*/
 
void mortition(struct distrenjob *head, struct distrenjob *job)
 
{
 
  short int isJobDone;
 
  int counter;
 
  char *path_and_number;
 
  struct stat buffer;
 

	
 
  isJobDone = 1; // set isJobDone to true
 
  for(counter = 0; counter < job->total_frames; counter++)
 
    {
 
      _distren_asprintf(&path_and_number, "stor/job%d/out/%d.%s", job->jobnum, job->frameset[counter].num, job->output_format);
 
      if(stat(path_and_number, &buffer) == -1)
 
        {
 
          job->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 
          job->completed_frames--;
 
          general_info.total_frames_rendered--;
 
          isJobDone = 0; // if a missing frame is found, set isJobDone to false
 
        }
 
    }
 

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

	
 
  updateGeneralInfo();
 
}
 

	
 
/** scans the frames of a job to initialize a job after server */
 
/* returns 1 if the job is completely done and there are no missing frames */
 
/* returns 0 if a missing frame is found */
 
int restoreJobState(struct distrenjob *job)
 
{
 
  short int isJobDone;
 
  int counter;
 
  char *path_and_number;
 
  struct stat buffer;
 

	
 
  isJobDone = 1;
 
  for(counter = 0; counter < job->total_frames; counter++)
 
    {
 
      _distren_asprintf(&path_and_number, "stor/job%d/out/%d.%s", job->jobnum, job->frameset[counter].num, job->output_format);
 
      if(stat(path_and_number, &buffer) == 0)
 
        {
 
          job->frameset[counter].status = FRAMESETSTATUS_ASSIGNED;
 
          job->completed_frames++;
 
        }
 
      else
 
        isJobDone = 0;
 
    }
 

	
 
  return isJobDone;
 
}
 

	
 
/** creates a structure from starting data, then calls another function to actually add that struct to the queue */
 
int prepare_distrenjob(struct distrenjob *head, int type, char *name, char *submitter, char *email, int priority, int start_frame, int end_frame, int width, int height)
 
{
 
  int counter2;
 
  int counter;
 
  int tmp;
 

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

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

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

	
 
    counter2++;
 
  }
 

	
 
  /* add job to queue */
 
  makeJobDataXML(distrenjob);
 
  distrenjob_enqueue(head, distrenjob);
 

	
 
  general_info.jobs_in_queue++;
 
  updateJobListXML(head);
 
  updateGeneralInfo();
 
  updateJobStatsXML(distrenjob);
 

	
 
  return 0;
 
}
 

	
 

	
 
/** distrenjob_enqueue: This function adds the job to the queue based on its priority */
 
void distrenjob_enqueue(struct distrenjob *head, struct distrenjob *job) {
 
  struct distrenjob *prev_job = head; // create pointer to previous job
 
  struct distrenjob *current_job;     // create pointer to current_job (which job is being compared to)
 

	
 
  // iterate through linked list of jobs
 
  for(current_job = head; current_job != NULL; current_job = current_job->next){
 
    if(current_job == NULL){ // if it has reached the end of the list, add job there
 
      current_job = job;
 
      break;
 
    }
 
    else if(job->priority < current_job->priority){ // if job's priority is less than current_job's priority, insert job
 
      prev_job->next = job;                        // keep in mind 1 is the highest priority given to jobs, head has a
 
      job->next = current_job;                     // priority of zero so it will always be before other jobs
 
      break;
 
    }
 

	
 
    prev_job = current_job;
 
  } /* for(current_job) */
 
}
 

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

	
 
  if(job->frameset[0].status == FRAMESETSTATUS_UNASSIGNED)
 
    /* if job was not yet started */
 
    distrenjob_enqueue(head, job);
 
  else{ // if job has already been started, place it before the jobs with the same priority
 
    // iterate through linked list of jobs
 
    for(current_job = head; current_job != NULL; current_job = current_job->next){
 
      if(current_job == NULL){ // if it has reached the end of the list, add job there
 
        current_job = job;
 
        break;
 
      }
 
      else if(job->priority <= current_job->priority){ // if job's priority is less than or equal to current_job's priority, insert job
 
        prev_job->next = job;                        // keep in mind 1 is the highest priority given to jobs, head has a
 
        job->next = current_job;                     // priority of zero so it will always be before other jobs
 
        break;
 
      }
 

	
 
      prev_job = current_job;
 
    }
 
  }
 
  updateJobListXML(head);
 
  makeJobDataXML(job); // because priority is changed
 
}
 

	
 
/**
 
  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
 
*/
 
int find_jobframe(struct distrenjob *head, struct distrenjob **job, struct frameset **frame)
 
{
 
  if(general_info.hibernate)
 
    return 1;
 

	
 
  unsigned int frame_counter;
 
  short int your_job_type;
 
  unsigned short int found;
 

	
 
  struct distrenjob *distrenjob_ptr;
 

	
 
  your_job_type = 0;
 
  found = 0;
 
  /* iterate through jobs from first to last */
 
  for(distrenjob_ptr = head->next; (!found && !distrenjob_ptr) && !distrenjob_ptr->hibernate; distrenjob_ptr = distrenjob_ptr->next)
 
    for(frame_counter = (distrenjob_ptr->prev_frame_index + 1); !found && frame_counter < distrenjob_ptr->total_frames; frame_counter ++)
 
      if(distrenjob_ptr->frameset[frame_counter].status == FRAMESETSTATUS_UNASSIGNED) // jobframe found
 
	{
 
	  found = 1;
 
	  your_job_type = distrenjob_ptr->type;
 
@@ -559,216 +559,218 @@ void importGeneralInfo()
 
  cur = cur->next;
 
  general_info.total_finished_jobs = atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
 
  cur = cur->next;
 
  general_info.total_frames_rendered = atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
 
  cur = cur->next;
 
  general_info.highest_jobnum = atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
 

	
 
  general_info.hibernate = 0;
 
  general_info.free_clients = 0;
 
  general_info.rendering_clients = 0;
 

	
 
  xmlFreeDoc(doc);
 
}
 

	
 
// returns 1 on successful completion of xml file
 
// creates the xml file that slaves read from, and is used to restart distren
 
int makeJobDataXML(struct distrenjob *job)
 
{
 
  xmlTextWriterPtr writer;
 
  char *tmp; // temporarily holds strings to be given to the xml writer
 

	
 
  _distren_asprintf(&tmp, "stor/job%d/job_info.xml", job->jobnum);
 

	
 
  // create xml document at the location tmp with no compression
 
  writer = xmlNewTextWriterFilename(tmp, 0);
 
  xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL);
 

	
 
  // write distrenjob element and add its attributes
 
  xmlTextWriterStartElement(writer, (xmlChar*)"job");
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"name", (xmlChar*)job->name);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"submitter", (xmlChar*)job->submitter);
 
  _distren_asprintf(&tmp, "%d", job->priority);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"priority", (xmlChar*)tmp);
 

	
 
  // write resolution element and add its attributes
 
  xmlTextWriterStartElement(writer, (xmlChar*)"resolution");
 
  _distren_asprintf(&tmp, "%d", job->width);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"width", (xmlChar*)tmp);
 
  _distren_asprintf(&tmp, "%d", job->height);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"height", (xmlChar*)tmp);
 
  xmlTextWriterEndElement(writer);
 

	
 
  // write video element and its attributes
 
  xmlTextWriterStartElement(writer, (xmlChar*)"video");
 
  _distren_asprintf(&tmp, "%d", job->frameset[0].num);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"start_frame", (xmlChar*)tmp);
 
  _distren_asprintf(&tmp, "%d", job->frameset[(job->total_frames - 1)].num);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"end_fame", (xmlChar*)tmp);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"output_format", (xmlChar*)job->output_format);
 
  xmlTextWriterEndElement(writer);
 

	
 
  // write watchdog forgiveness element
 
  _distren_asprintf(&tmp, "%d", job->watchdog_forgiveness);
 
  xmlTextWriterWriteElement(writer, (xmlChar*)"wd_forgiveness", (xmlChar*)tmp);
 

	
 
  // end document
 
  xmlTextWriterEndDocument(writer);
 

	
 
  // free writer and save xml file to disk
 
  xmlFreeTextWriter(writer);
 

	
 
  return 1;
 
}
 

	
 
// 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(int job_number)
 
{
 
  xmlDocPtr doc;
 
  xmlNodePtr cur;
 
  char *file_name;
 
  struct distrenjob *distrenjob;
 
  int start_frame;
 
  int counter;
 
  int counter2;
 

	
 
  distrenjob_new(&distrenjob);
 

	
 
  _distren_asprintf(&file_name, "stor/job%d/job_info.xml", job_number);
 

	
 
  doc = xmlParseFile(file_name);
 
  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"));
 

	
 
  cur = cur->xmlChildrenNode;
 
  distrenjob->width = atoi((char*)xmlGetProp(cur, (xmlChar*)"width"));
 
  distrenjob->height = atoi((char*)xmlGetProp(cur, (xmlChar*)"number"));
 

	
 
  cur = cur->next;
 
  start_frame = atoi((char*)xmlGetProp(cur, (xmlChar*)"start_frame"));
 
  distrenjob->total_frames = atoi((char*)xmlGetProp(cur, (xmlChar*)"end_frame")) - start_frame + 1;
 
  distrenjob->output_format = (char*)xmlGetProp(cur, (xmlChar*)"output_format");
 

	
 
  counter2 = start_frame;
 
  for(counter = 0; counter <= distrenjob->total_frames; counter++)
 
    {
 
      distrenjob->frameset[counter].num = counter2;
 
      distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 

	
 
      counter2++;
 
    }
 

	
 
  cur = cur->next;
 
  distrenjob->watchdog_forgiveness = atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
 

	
 
  xmlFreeDoc(doc);
 

	
 
  // load up stats.xml file to retrieve data
 
  _distren_asprintf(&file_name, "stor/job%d/stats.xml", job_number);
 

	
 
  doc = xmlParseFile(file_name);
 
  cur = xmlDocGetRootElement(doc);
 

	
 
  distrenjob->total_render_time = (time_t)atol((char*)xmlGetProp(cur, (xmlChar*)"total_render_time"));
 

	
 
  xmlFreeDoc(doc);
 

	
 
  distrenjob->frameset = malloc(sizeof(struct frameset) * distrenjob->total_frames);
 

	
 
  // change the status of all frames to "unassigned"
 
  counter2 = start_frame;
 
  for(counter = 0; counter <= (end_frame- start_frame + 1); counter++){
 
    distrenjob->frameset[counter].num = counter2;
 
    distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 

	
 
    counter2++;
 
  }
 

	
 
  restoreJobState(distrenjob);
 
  return distrenjob;
 
}
 

	
 
int updateJobStatsXML(struct distrenjob *job)
 
{
 
	  xmlTextWriterPtr writer;
 
	  char *tmp; // temporarily holds strings to be given to the xml writer
 

	
 
	  _distren_asprintf(&tmp, "stor/job%d/stats.xml", job->jobnum);
 

	
 
	  // create xml document at the location tmp with no compression
 
	  writer = xmlNewTextWriterFilename(tmp, 0);
 
	  xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL);
 

	
 
	  xmlTextWriterStartElement(writer, (xmlChar*)"stats");
 
	  _distren_asprintf(&tmp, "%d", job->assigned_frames);
 
	  xmlTextWriterWriteAttribute(writer, (xmlChar*)"assigned_frames", (xmlChar*)tmp);
 
	  _distren_asprintf(&tmp, "%d", job->completed_frames);
 
	  xmlTextWriterWriteAttribute(writer, (xmlChar*)"completed_frames", (xmlChar*)tmp);
 
	  _distren_asprintf(&tmp, "%d", job->total_render_time);
 
	  xmlTextWriterWriteAttribute(writer, (xmlChar*)"total_render_time", (xmlChar*)tmp);
 

	
 
	  // end document
 
	  xmlTextWriterEndDocument(writer);
 
	  // free writer and save xml file to disk
 
	  xmlFreeTextWriter(writer);
 

	
 
	  return 1;
 
}
 

	
 
// returns 1 if successful
 
// updates job_list.xml which lists all the jobs in the queue
 
int updateJobListXML(struct distrenjob *head)
 
{
 
  struct distrenjob *job;
 
  xmlTextWriterPtr writer;
 
  char *tmp;
 
  char *tmp2;
 
  int counter;
 

	
 
  _distren_asprintf(&tmp, "job_list.xml");
 
  writer = xmlNewTextWriterFilename(tmp, 0);
 
  xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL);
 

	
 
  // create root element job_list
 
  xmlTextWriterStartElement(writer, (xmlChar*)"job_list");
 

	
 
  _distren_asprintf(&tmp, "%d", general_info.jobs_in_queue);
 
  xmlTextWriterWriteAttribute(writer, (xmlChar*)"amount", (xmlChar*)tmp);
 

	
 
  counter = 0;
 
  for(job = head->next; !job; job = job->next)
 
    {
 
      _distren_asprintf(&tmp, "jobnum%d", counter);
 
      _distren_asprintf(&tmp2, "%d", job->jobnum);
 
      xmlTextWriterWriteElement(writer, (xmlChar*)tmp, (xmlChar*)tmp2);
 
      counter++;
 
    }
 

	
 
  // close elements and end document
 
  xmlTextWriterEndDocument(writer);
 

	
 
  // free writer and save xml file to disk
 
  xmlFreeTextWriter(writer);
 
  return 1;
 
}
 

	
 
// returns 1 if completed successfully, 0 if not
 
// this reads a list of jobs in the queue before DistRen was shut down
 
// and then adds the jobs to the queue, as if it were never shut down
 
int createQueueFromXML(struct distrenjob *head)
 
{
 
  xmlDocPtr doc;  // holds xml document in memory
 
  xmlNodePtr cur; // points to the current xml element node
 

	
 
  // load xml document
 
  doc = xmlParseFile("job_list.xml");
 
  if(doc == NULL)
 
    {
 
      fprintf(stderr, "createQueueFromXML: document not found\n");
 
      return 0;
 
    }
 

	
 
  // have cur point to the root element of the xml document pointed to by doc
 
  cur = xmlDocGetRootElement(doc);
 
  if(cur == NULL)
 
    {
 
      fprintf(stderr, "createQueueFromXML: document empty\n");
 
      return 0;
 
    }
 

	
 
  if(xmlStrcmp(cur->name, (const xmlChar*)"job_list"))
 
    {
 
      fprintf(stderr, "createQueueFromXML: incorrect root element (%s)", (char*)cur->name);
 
    }
0 comments (0 inline, 0 general)