Changeset - 0f74d7c8d753
[Not reviewed]
default
0 2 0
LordOfWar - 16 years ago 2009-09-15 23:02:23

updated and simplified frame_finder()

removed isJobDone from distrenjob structure... since all jobs will be using
2 files changed with 22 insertions and 29 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -239,130 +239,124 @@ void distrenjob_enqueue(struct distrenjo
 
    }
 

	
 
    prev_job = current_job;
 
  } /* for(current_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 == 0){ // if job was not yet started
 
    distrenjob_enqueue(head, job);
 
  }
 
  else{ // if job has already been started then 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;
 
    }
 
  }
 
}
 

	
 
/**
 
  Frame Finder: matches your computer up with a lovely frame to render
 
  TODO: Major issue here, the client needs to know the frame number, AND the job number!
 
  Notice that this function starts by looking at the oldest job first
 

	
 
	TODO: Link this up with the main() function to check if there are frames available or not and provide jobnum/framenum to the client
 

	
 
  @return 0 success, other: error
 
*/
 
/*@TODO: change frame_finder to job_finder */
 
int frame_finder(struct distrenjob *head, struct distrenjob **job, struct frameset **frame)
 
{
 
  int your_frame = 0;  // your_frame is an integer value that will be given to the client as the frame number to render
 
  short int your_job_type = 0;
 
  int your_frame;  // your_frame is an integer value that will be given to the client as the frame number to render
 
  short int your_job_type;
 
  unsigned short int found;
 

	
 
  struct distrenjob *distrenjob_ptr;
 

	
 
  your_frame = 0;
 
  your_job_type = 0;
 
  found = 0;
 

	
 
  while(!found)
 
  {
 
    /* iterate through jobs from first to last */
 
    for(distrenjob_ptr = head->next; !found && !distrenjob_ptr; distrenjob_ptr = distrenjob_ptr->next)
 
      {
 
        if(distrenjob_ptr->is_job_done)
 
          distrenjob_ptr->type = your_job_type;
 
      }
 
  /* iterate through jobs from first to last */
 
  for(distrenjob_ptr = head->next; !found && !distrenjob_ptr; distrenjob_ptr = distrenjob_ptr->next)
 
    {
 
      // while frame hasn't been found, and your_frame is less than the length of the frameset array
 
      for(your_frame; !found && your_frame < distrenjob_ptr->total_frames; your_frame++)
 
        {
 
          if(distrenjob_ptr->frameset[your_frame].status == 0)
 
            {
 
              found = 1;
 
              your_job_type = distrenjob_ptr->type;
 
              distrenjob_ptr->frameset[your_frame].status = 1;
 
              distrenjob_ptr->frameset[your_frame].start_time = clock();
 
              break;
 
            }
 
        }
 
    }
 

	
 
    found = 0;
 
    // check the job type to see if the job is avaliable to be worked on
 
    switch(your_job_type)
 
    {
 
      case 1: // blender
 
        for(your_frame; !found; your_frame++)
 
          {
 
            if(distrenjob_ptr->frameset[your_frame].status == 0)
 
              {
 
                found = 1;
 
                distrenjob_ptr->frameset[your_frame].status = 1;
 
                distrenjob_ptr->frameset[your_frame].start_time = clock();
 
                break;
 
              }
 
          }
 
    }
 
  } // end of while statement... job must be found or linked list must be ended to get out of here
 

	
 
// end of while statement... job must be found or linked list must be ended to get out of here
 
      if(!found)
 
        {
 
          fprintf(stderr, "No more jobs to render\n");
 
          return 1;
 
        }
 

	
 
    // the actual frame number to be rendered by the client is start_frame + your_frame
 
    // @TODO: refine how we want to return data from this
 
    //struct framejob { distrenjob_ptr; distrenjob_ptr->(&frameset[your_frame])};
 

	
 
      /* should the job be removed now? ANSWER: well, if a computer decides not to return their frame then we lost our data... so its not done yet. */
 
      fprintf(stderr, "Job %d is finished, this is probably the place to call the job-removal function\n", distrenjob_ptr->jobnum);
 
      /* @TODO: At this point, all slaves should be instructed to delete the source data for this job. */
 

	
 
  return 0;
 
}
 

	
 
/** Checks for dead, laggy, or stale slaves */
 
void blend_frame_watchdog(struct distrenjob *distrenjob_head)
 
{
 
  unsigned short int watchdog_forgiveness; /*< seconds to wait on a frame before re-assigning it */
 
  struct distrenjob *distrenjob_ptr;
 
  unsigned int counter;
 

	
 
  watchdog_forgiveness = 1; /*< hours of forgiveness before frame is re-assigned @TODO: Make this more user-configurable (maybe per-job), 3 hours is a LONG time */
 
  distrenjob_ptr = distrenjob_head;
 

	
 
  for(distrenjob_ptr = distrenjob_head; distrenjob_ptr; distrenjob_ptr = distrenjob_ptr->next)
 
    /* iterate through jobs */
 

	
 
    for(counter = 0; counter < distrenjob_ptr->total_frames; counter ++)
 
      /* iterate through all frames for this job*/
 
      {
 
        if((distrenjob_ptr->frameset[counter].start_time + (watchdog_forgiveness * 3600)) < clock())
 
          /*
 
            If frame is not completed within the number of hours specified by watchdog_forgiveness
 
            Then change the frame status to unassigned
 
           */
 
          distrenjob_ptr->frameset[counter].status = 0;
 
      }
 

	
 
}
 

	
 
/**
 
   Finds a distrenjob struct based on the jobnum
 
   @arg jobnum job number to search for
 
   @return NULL on job doesn't exist
 
 */
src/server/distrenjob.h
Show inline comments
 
/*
 
  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/>.
 

	
 
*/
 

	
 
#ifndef _DISTREN_DISTRENJOB_H
 
#define _DISTREN_DISTRENJOB_H
 

	
 
/**
 
   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 *next; /*< next will be NULL unless if there is another distrenjob */
 
  short int type; // 1:Blender, 2:something else
 
  short int is_job_done; // so job finder can tell if the job is done no matter what type of job it is
 
  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 priority;  // 1 is lowest, 10 is highest, 0 means the job is done
 
  float percent_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)
 
  int watchdog_forgiveness; // how many hours till the frame is re-assigned (if client computer crashes etc);
 
  time_t avg_render_time; // average seconds it took to render a frame
 
  time_t time_remaining; /*< estimated seconds remaining till render is complete (up to 49, 710 days) */
 
  char *output_format; /*< currently is the file extention of the request output format. @todo make this mime-type based/not a string */
 
  struct frameset *frameset;
 
};
 

	
 

	
 

	
 
/**
 
   Frameset Structure
 
*/
 
struct frameset {
 
  int num; /*< frame number to render */
 
  char slave_name; /*< user that frame is assigned to */
 
  int status; /*< status of frame, 0= unassigned, 1= taken, 2= done */
 
  clock_t start_time; /*< time the frame was started */
 
  int time_to_render; /*< the total seconds it took to render the frame */
 
}; /* Frameset array is generated by status_report_generator() */
 

	
 

	
 
/*
 
related functions
 
*/
 

	
 
/**
 

	
 
   @param distrenjob the address where we will store the pointer of a malloc()ed
 
   distrenjob struct.
 
   @param pathtoxml filename/pathname of the xml file to be read into a distrenjob struct
 
 */
 
int xml2distrenjob(struct distrenjob **distrenjob, char *pathtoxml);
 

	
 
/**
 
   support function for xml2distrenjob() 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);
0 comments (0 inline, 0 general)