Changeset - 2a5a620b64ea
[Not reviewed]
default
0 2 0
Nathan Brink (binki) - 16 years ago 2009-09-17 16:28:34
ohnobinki@ohnopublishing.net
frame_finder()=>find_jobfram(), enum framesetstatus, misc
2 files changed with 38 insertions and 46 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -36,35 +36,24 @@
 

	
 
/* ******************* Structs ************************ */
 

	
 
// Gets config info from confs
 
struct distrend_config
 
{
 
  cfg_t *mycfg;
 
  struct options_common *options;
 
  struct distrend_listen **listens; /*< Null terminated array of structs */
 
  char *datadir;
 
};
 

	
 

	
 

	
 
/*
 
 frame[frame] Status Assignments:
 
  "NULL" - don't render me
 
  "0" - canceled
 
  "1" - unassigned
 
  "2" - assigned to slave
 
  "3" - completed by slave and uploaded
 
*/
 

	
 
struct general_info {
 
  short int jobs_in_queue; //
 
  unsigned short int free_clients;
 
  unsigned short int rendering_clients;//
 
  unsigned short int total_finished_jobs; //
 
  unsigned int total_frames_rendered; //
 
  unsigned int highest_jobnum;
 
} general_info;
 

	
 

	
 

	
 
/*
 
@@ -144,25 +133,25 @@ int start_data(){
 
  }
 
  else{
 
    general_info.total_finished_jobs = 0;
 
    general_info.total_frames_rendered = 0;
 
    fprintf(stderr,"Can't find XML dump, starting up fresh.\n");
 
    return 2;
 
  }
 
  free(&buffer); // @TODO: Is this pointless?
 
}
 

	
 
/** Finish-Setter: Sets a frame to the "completed" status.*/
 
void finish_frame(struct distrenjob *head, struct distrenjob *distrenjob, int frame){
 
  distrenjob->frameset[frame].status = 2;
 
  distrenjob->frameset[frame].status = FRAMESETSTATUS_DONE;
 
  distrenjob->frameset[frame].time_to_render = (clock() - distrenjob[jobnum].frameset[frame].start_time); // Consider changing time-to-render to time-for-frame or something?
 
  /* TODO: calculating the average render time like this may have a small amount of error, because the number is truncated to an integer of seconds every time... does it matter? */
 
  /* we could keep track of the total render time... would make calculation a lot easier and more accurate */
 
  distrenjob->avg_render_time = ((distrenjob->avg_render_time*(distrenjob->completed_frames)) + distrenjob->frameset[frame].time_to_render)/(distrenjob->completed_frames + 1);
 
  distrenjob->completed_frames++;
 
  distrenjob->assigned_frames--;
 
  general_info.total_frames_rendered++; // Increase total frames var for stats
 

	
 
  if(distrenjob->completed_frames == distrenjob->total_frames)
 
    {
 
      mortition(head, distrenjob);
 
    }
 
@@ -173,25 +162,25 @@ void finish_frame(struct distrenjob *hea
 
void mortition(struct distrenjob *head, struct distrenjob *job){
 
  short int isJobDone;
 
  int counter;
 
  char path_and_number[20];
 
  struct stat buffer;
 

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

	
 
  if(isJobDone)
 
    {
 
      distrenjob_remove(&head, job);
 
      general_info.jobs_in_queue--;
 
    }
 
}
 

	
 
@@ -218,25 +207,25 @@ void prepare_distrenjob(struct frameset 
 

	
 
  /* @TODO: should the aove be malloc(sizeof(struct frameset) * distrenjob->total_frames? */
 
  /*
 
  distrenjob->frameset = malloc(sizeof(struct frameset) * numframes);
 
  if(!job->frameset)
 
    fprintf(stderr, "Error allocating memory\n");
 
  */
 

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

	
 
    counter2++;
 
  }
 

	
 
  distrenjob_enqueue(head, distrenjob);
 

	
 
  general_info.jobs_in_queue++;
 
}
 

	
 

	
 
/* distrenjob_enqueue: This function adds the job to the queue based on its priority */
 
void distrenjob_enqueue(struct distrenjob *head, struct distrenjob *job) {
 
@@ -259,27 +248,27 @@ void distrenjob_enqueue(struct distrenjo
 
  } /* 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
 
  if(job->frameset[0].status == FRAMESETSTATUS_UNASSIGNED)
 
    /* 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;
 
      }
 
@@ -289,65 +278,60 @@ void change_job_priority(struct distrenj
 
  }
 
}
 

	
 
/**
 
  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 find_jobframe(struct distrenjob *head, struct distrenjob **job, struct frameset **frame)
 
{
 
  int your_frame;  // your_frame is an integer value that will be given to the client as the frame number to render
 
  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 = distrenjob_ptr->next)
 
    for(frame_counter = 0; !found && frame_counter < distrenjob_ptr->total_frames; frame_counter ++)
 
      if(distrenjob_ptr->frameset[frame_counter].status == FRAMESETSTATUS_UNASSIGNED)
 
	{
 
	  found = 1;
 
	  your_job_type = distrenjob_ptr->type;
 
	  distrenjob_ptr->frameset[frame_counter].status = FRAMESETSTATUS_ASSIGNED;
 
	  distrenjob_ptr->frameset[frame_counter].start_time = clock();
 
	  distrenjob_ptr->assigned_frames++;
 
	}
 

	
 
  // end of while statement... job must be found or linked list must be ended to get out of here
 
  if(!found)
 
    {
 
      // while frame hasn't been found, and your_frame is less than the length of the frameset array
 
      for(your_frame = 0; !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();
 
              distrenjob_ptr->assigned_frames++;
 
              break;
 
            }
 
      fprintf(stderr, "No more jobs to render\n");
 
      return 1;
 
    }
 

	
 
// 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
 
  *job = distrenjob_ptr;
 
  *frame = &distrenjob_ptr->frameset[frame_counter];
 

	
 
    // the actual frame number to be rendered by the client is start_frame + your_frame
 
    *job = distrenjob_ptr;
 
    *frame = &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. */
 
  /* 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 */
 
@@ -355,25 +339,25 @@ void blend_frame_watchdog(struct distren
 

	
 
  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;
 
          distrenjob_ptr->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 
      }
 

	
 
}
 

	
 
/**
 
   Finds a distrenjob struct based on the jobnum
 
   @arg jobnum job number to search for
 
   @return NULL on job doesn't exist
 
 */
 
struct distrenjob *distrenjob_get(struct distrenjob *head, jobnum_t jobnum)
 
{
 
  struct distrenjob *distrenjob_ptr;
 
@@ -512,25 +496,25 @@ int main(int argc, char *argv[])
 
      cont = distrend_do(action);
 

	
 
      /* Make the following code more event-driven */
 
      blend_frame_watchdog(&head);
 

	
 

	
 
      struct frameset *frame;
 
      struct distrenjob *job;
 

	
 
      /* If the client is idle, must be modified for climbing through linked list of clients (client->clientnum) */
 
      if(clientstatus == CLIENTSTATUS_IDLE)
 
	{
 
	  int returnnum = frame_finder(&head, &job, &frame); // Finds a frame to render
 
	  int returnnum = find_jobframe(&head, &job, &frame); // Finds a frame to render
 
	  if(returnnum)
 
	    {
 
	      fprintf(stderr,"No frames are available to render at this time. Idling...\n");
 
	      sleep(10);
 
	    }
 
	  else
 
	    /* returnnum == 0 */
 
	    remotio_send_to_client(frame->num, job->jobnum); // Pseudo-sends data to client
 
	}
 

	
 
      /* If the client states that they finished the frame */
 
      	if(clientsays == DISTREN_REQUEST_DONEFRAME){
src/server/distrenjob.h
Show inline comments
 
@@ -47,28 +47,36 @@ struct distrenjob {
 
  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
 
*/
 
enum framesetstatus
 
  {
 
    FRAMESETSTATUS_CANCELED, /*< The use has canceled this frame */
 
    FRAMESETSTATUS_UNASSIGNED, /*< The frame has not been assigned */
 
    FRAMESETSTATUS_ASSIGNED, /*< The frame has been assigned */
 
    FRAMESETSTATUS_DONE /*< The frame has completed rendering and the slave has returned the product to me */
 
  };
 

	
 
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 */
 
  enum framesetstatus 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
0 comments (0 inline, 0 general)