Changeset - b8b84581af27
[Not reviewed]
default
0 1 0
LordOfWar - 16 years ago 2009-10-14 01:14:03

initialized variables, prepare_distrenjob gives out a jobnumber now, added fprintfs to identify areas of error
1 file changed with 16 insertions and 0 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -69,415 +69,423 @@ struct general_info {
 
  short int hibernate;
 
} general_info;
 

	
 

	
 

	
 
/*
 
  internally defined funcs's prototypes @TODO: Make all functions nice and proper */
 
void distrenjob_remove(struct distrenjob *head, struct distrenjob *bj);
 

	
 
struct distrenjob *distrenjob_get(struct distrenjob *head, jobnum_t jobnum);
 
void distrenjob_enqueue(struct distrenjob *head, struct distrenjob *job);
 
void mortition(struct distrenjob *head, struct distrenjob *job);
 
int makeJobDataXML(struct distrenjob *job);
 
int updateJobListXML(struct distrenjob *head);
 
int createQueueFromXML(struct distrenjob *head);
 
int reCreateQueueFromXML(struct distrenjob *head, xmlDocPtr doc, xmlNodePtr current);
 
void updateGeneralInfo();
 
void importGeneralInfo();
 
int updateJobStatsXML(struct distrenjob *job);
 

	
 

	
 
/* Global Vars, eliminate these */
 
jobnum_t jobnum = 0; // The next job number to create in the queue
 
int hcfjob; // Highest consecutively finished job
 
int highest_jobnum; // The job number of the most recently created job, this is used when creating new jobs
 

	
 

	
 
/* ********************** 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! */
 
int xml_dump()
 
{
 
  return 0;
 
}
 
/**
 
   Performs command stored in a client's request.
 
*/
 
int distrend_do()
 
{
 
  return 0;
 
}
 
/**
 
   Accepts a client's connection
 
 */
 
void distrend_accept()
 
{
 

	
 
}
 
/**
 
   Frees the action
 
*/
 
void distrend_action_free()
 
{
 

	
 
}
 
/**
 
   Start listening
 
*/
 
void distrend_listen()
 
{
 

	
 
}
 
/**
 
   Stop listening
 
*/
 
void distrend_unlisten()
 
{
 

	
 
}
 
/**
 
   This is probably just a placeholder for remotio
 
*/
 
void remotio_send_to_client()
 
{
 
	// I am futile!
 
}
 

	
 
/** Fill variables after crash / shutdown from XML dumps */
 
int start_data(struct distrenjob *head)
 
{
 
  struct stat buffer;
 
  if(stat("general_info.xml", &buffer) == 0){
 
    importGeneralInfo();
 

	
 
    fprintf(stderr,"Parsing XML files and restoring previous state...\n");
 
    createQueueFromXML(head);
 
    return 1;
 
  }
 
  else{
 
    general_info.total_finished_jobs = 0;
 
    general_info.total_frames_rendered = 0;
 
    general_info.free_clients = 0;
 
    general_info.highest_jobnum = 0;
 
    general_info.jobs_in_queue = 0;
 
    general_info.rendering_clients = 0;
 
    general_info.hibernate = 0;
 
    fprintf(stderr,"Couldn't find XML dump, starting up fresh.\n");
 
    return 2;
 
  }
 
}
 

	
 
/** Finish-Setter: Sets a frame to the "completed" status.*/
 
void finish_frame(struct distrenjob *head, struct distrenjob *distrenjob, int frame)
 
{
 
  distrenjob->frameset[frame].status = FRAMESETSTATUS_DONE;
 
  distrenjob->total_render_time = distrenjob->total_render_time + (clock() - distrenjob[jobnum].frameset[frame].start_time);
 
  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);
 
    }
 

	
 
  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;
 

	
 
  general_info.highest_jobnum++;
 

	
 
  distrenjob->jobnum = general_info.highest_jobnum;
 
  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 < distrenjob->total_frames; counter++){
 
    distrenjob->frameset[counter].num = counter2;
 
    distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 

	
 
    counter2++;
 
  }
 

	
 
  /* add job to queue */
 
  fprintf(stderr, "\nprepare_distrenjob: attempting makeJobDataXML()\n");
 
  makeJobDataXML(distrenjob);
 
  fprintf(stderr, "\nprepare_distrenjob: attempting distrenjob_enqueue()\n");
 
  distrenjob_enqueue(head, distrenjob);
 

	
 
  general_info.jobs_in_queue++;
 
  fprintf(stderr, "\nprepare_distrenjob: attempting updateJobListXML()\n");
 
  updateJobListXML(head);
 
  fprintf(stderr, "\nprepare_distrenjob: attempting updateGeneralInfo()\n");
 
  updateGeneralInfo();
 
  fprintf(stderr, "\nprepare_distrenjob: attempting updateJobStatsXML()\n");
 
  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;
 
	  distrenjob_ptr->frameset[frame_counter].status = FRAMESETSTATUS_ASSIGNED;
 
	  distrenjob_ptr->frameset[frame_counter].start_time = clock();
 
	  distrenjob_ptr->assigned_frames++;
 
	  distrenjob_ptr->prev_frame_index = frame_counter;
 
	  updateJobStatsXML(distrenjob_ptr);
 
	}
 

	
 
  if(!found)
 
    {
 
      fprintf(stderr, "No more jobs to render\n");
 
      sleep(1); /*< @todo eliminate the need for this line*/
 
      return 1;
 
    }
 

	
 
  *job = distrenjob_ptr;
 
  *frame = &distrenjob_ptr->frameset[frame_counter];
 

	
 
  return 0;
 
}
 

	
 
/** Checks for dead, latent, or stale slaves */
 
void frame_watchdog(struct distrenjob *distrenjob_head)
 
{
 
  struct distrenjob *distrenjob_ptr;
 
  unsigned int counter;
 

	
 
  for(distrenjob_ptr = distrenjob_head->next; distrenjob_ptr; distrenjob_ptr = distrenjob_ptr->next)
 
  /* iterate through jobs */
 
  {
 
    /* if the job has been started, checks by seeing if either to first or second frame has been started */
 
    if(distrenjob_ptr->frameset[0].status != FRAMESETSTATUS_UNASSIGNED || distrenjob_ptr->frameset[1].status != FRAMESETSTATUS_UNASSIGNED)
 
      /* iterate through all frames for this job: */
 
      for(counter = 0; counter < distrenjob_ptr->total_frames; counter ++)
 
	    /*watchdog_forgiveness = seconds of forgiveness before frame is re-assigned: */
 
        if((distrenjob_ptr->frameset[counter].start_time + distrenjob_ptr->watchdog_forgiveness) < clock())
 
        {
 
            /*
 
            If frame is not completed within the number of seconds specified by watchdog_forgiveness
 
            Then change the frame status to unassigned
 
            */
 
            distrenjob_ptr->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED;
 
            distrenjob_ptr->assigned_frames--;
 
        }
 

	
 
    updateJobStatsXML(distrenjob_ptr);
 
  }
 
}
 

	
 
/**
 
   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;
 

	
 
  /*
 
    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
 

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

	
 
  for(previous_distrenjob = head;
 
      previous_distrenjob
 
	&& previous_distrenjob->next != bj; /*< stop on the distrenjob that comes before bj */
 
      previous_distrenjob = previous_distrenjob->next)
 
    /* all of the action is in the definition of the for loop itself */;
 

	
 
  /*
 
    This removes references to bj from the linked list. I.E., we now skip bj when iterating through the list
 
  */
 
  previous_distrenjob->next = bj->next;
 

	
 
  general_info.jobs_in_queue--;
 
}
 

	
 

	
 
/* Grabs config info from confs */
 
int distrend_do_config(int argc, char *argv[], struct distrend_config **config)
 
{
 
  cfg_opt_t myopts_listen[] =
 
    {
 
      CFG_SIMPLE_STR("type", NULL),
 
      CFG_SIMPLE_STR("path", NULL),
 
      CFG_SIMPLE_INT("port", NULL),
 
      CFG_END()
 
    };
 
  cfg_opt_t myopts[] =
 
    {
 
      CFG_SEC("listen",  /* this must be imported into struct listens (which must still be declared) */
 
          myopts_listen,
 
          CFGF_MULTI),
 
      CFG_SIMPLE_STR("datadir", NULL),
 
@@ -727,343 +735,351 @@ int updateJobListXML(struct distrenjob *
 

	
 
  // 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);
 
    }
 

	
 
  // moves into the children elements of job_list
 
  cur = cur->xmlChildrenNode;
 

	
 
  reCreateQueueFromXML(head, doc, cur);
 
  /* scans the list of all jobs that were in queue before DistRen shutdown
 
  while(cur != NULL)
 
    {
 
      tmp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 
      fprintf(stderr, "adding job: %s", tmp);
 
      // add job from job number @TODO create function with parameters (struct distrenjob *head, int job_number)
 
      // LordOfWar calls dibs on above todo
 

	
 

	
 
      xmlFree(tmp);
 
      cur = cur->next; // go to next child element of job_list element
 
    }*/
 

	
 
  xmlFreeDoc(doc);
 

	
 
  return 1;
 
}
 

	
 
// inserts jobs at front of queue, starting with the last job in the job_list xml file
 
// to preserve the order of the queue
 
int reCreateQueueFromXML(struct distrenjob *head, xmlDocPtr doc, xmlNodePtr current)
 
{
 
  struct distrenjob *holder; // holds the job that "was" after head, so that the new struct can be inserted after head
 
  struct distrenjob *job; // job to be added
 
  xmlChar *tmp;
 
  int job_num;
 
  if(current == NULL) // base case, if element doesn't exist then don't do anything
 
    return 0;
 

	
 
  // recursively call itself so that the next job in the queue is added to the front before the current one
 
  reCreateQueueFromXML(head, doc, current->next);
 

	
 
  // now actual work is done, adding the job to the front of the queue
 
  holder = head->next; // initialize holder
 
  tmp = xmlNodeListGetString(doc, current->xmlChildrenNode, 1); // get job number
 
  job_num = atoi((char*)tmp);
 
  job = createJobFromXML(job_num);
 
  xmlFree(tmp); // free xml char (that holds the job number)
 

	
 
  // insert job at front of the queue
 
  head->next = job;
 
  job->next = holder;
 

	
 
  return 1;
 
}
 

	
 
/* ************************** Test Functions ************************* */
 
void printFrameInfo(struct frameset *frame)
 
{
 
  char *status;
 

	
 
  status = NULL;
 

	
 
  switch(frame->status)
 
  {
 
    case FRAMESETSTATUS_UNASSIGNED:
 
      _distren_asprintf(&status, "%s", "unassigned");
 
      break;
 
    case FRAMESETSTATUS_ASSIGNED:
 
      _distren_asprintf(&status, "%s", "assigned");
 
      break;
 
    case FRAMESETSTATUS_DONE:
 
      _distren_asprintf(&status, "%s", "completed");
 
      break;
 
    case FRAMESETSTATUS_CANCELED:
 
      _distren_asprintf(&status, "%s", "canceled");
 
  }
 

	
 
  printf("frame #: %d --> %s", frame->num, status);
 
}
 

	
 
void printJob(struct distrenjob *job)
 
{
 
  int counter;
 
  printf("frame_num: status");
 
  for(counter = 0; counter < job->total_frames; counter++)
 
    {
 
      printFrameInfo(&job->frameset[counter]);
 
    }
 
}
 

	
 
void printJobInfo(struct distrenjob *job)
 
{
 
  printf("type: %d", job->type);
 
  printf("name: %s", job->email);
 
  printf("submitter: %s", job->submitter);
 
  printf("e-mail: %s", job->email);
 
  printf("priority, %d", job->priority);
 
  printf("completed: %d", job->completed_frames);
 
  printf("assigned: %d", job->assigned_frames);
 
  printf("total: %d", job->total_frames);
 
  printf("watchdog: %d", job->watchdog_forgiveness);
 
  printf("hibernate: %d", job->hibernate);
 
  printf("prev_frame: %d", job->prev_frame_index);
 
}
 

	
 
void printAllJobnums(struct distrenjob *head)
 
{
 
  struct distrenjob *current_job;
 
  int total_jobs;
 
  printf("job numbers in the order they will be processed:");
 

	
 
  total_jobs = 0;
 
  for(current_job = head; !current_job; current_job = current_job->next)
 
    {
 
      printf("%d", current_job->jobnum);
 
      total_jobs++;
 
    }
 

	
 
  printf("%d jobs in queue", total_jobs);
 
}
 

	
 
/* ************************** Main ************************* */
 

	
 
int main(int argc, char *argv[])
 
{
 

	
 
  /* Argument-parser */
 
  int counter;
 
  int test; // Have some fun if-ness that does fun stuff when this is 1
 

	
 

	
 
  struct distrenjob head;
 

	
 
  int cont;
 
  struct distrend_listenset *listenset;
 
  struct distrend_config *config;
 

	
 
  enum clientstatus
 
  {
 
    CLIENTSTATUS_UNINITIALIZED = 0,
 
    CLIENTSTATUS_BUSY = 1,
 
    CLIENTSTATUS_IDLE = 2
 
  } clientstatus;
 

	
 
  // initialize general_info struct, this should be done by start_data()
 
  general_info.jobs_in_queue = 0;
 
  general_info.free_clients = 0;
 
  general_info.rendering_clients = 0;
 
  general_info.total_finished_jobs = 0;
 
  general_info.total_frames_rendered = 0;
 
  general_info.highest_jobnum = 0;
 
  general_info.hibernate = 0;
 

	
 
  int command;
 
  jobnum_t jobnum;
 
  struct distrenjob *tmp_job;
 
  struct frameset *tmp_frame;
 
  int type;
 
  char *name;
 
  char *submitter;
 
  char *email;
 
  int priority;
 
  int width;
 
  int height;
 
  int start_frame;
 
  int end_frame;
 
  size_t read_buf;
 

	
 
  head.priority = 0; // make head have the highest priority
 

	
 
  xmlinit();
 

	
 
  test = 0;
 
  for(counter = 0; counter < argc; counter ++)
 
    {
 
      if(strcmp(argv[counter], "-h") == 0)
 
	{
 
	  fprintf(stderr, "Usage: distrend [option] \nStarts the distrend server\n\t-h\tshow this help\n\t-t\tlaunches queue testing interface \n");
 
	  return 2;
 
	}
 

	
 
      else if(strcmp(argv[counter], "-t") == 0)
 
	{
 
	  fprintf(stderr, "Entering into test mode...\n\n");
 
	  test=1;
 
	}
 
    }
 
  cont = 1;
 
  memset(&head, '\0', sizeof(struct distrenjob));
 

	
 
  start_data(&head); // Starts fresh or loads data from xml dump. Should we grab the return?
 

	
 
  distrend_do_config(argc, argv, &config);
 

	
 

	
 

	
 
  while(test == 1)
 
  {
 
    fprintf(stderr, "Welcome to DistRen Alpha Interactive Test Mode\n\n");
 
    fprintf(stderr, "\t1 \tPrint all frames in a job\n");
 
    fprintf(stderr, "\t2 \tExamine certain job\n");
 
    fprintf(stderr, "\t3 \tGet a frame to render\n");
 
    fprintf(stderr, "\t4 \tAdd a job\n");
 
    fprintf(stderr, "\t5 \tDelete a job\n");
 
    fprintf(stderr, "\t6 \tPrint jobnums in queue\n");
 
    fprintf(stderr, "\t7 \tQuit\n");
 

	
 
    scanf("%d", &command);
 

	
 
    switch(command)
 
    {
 
    case 1:
 
      fprintf(stderr, "Job number: ");
 
      scanf("%d", &jobnum);
 
      printJob(distrenjob_get(&head, jobnum));
 
      break;
 
    case 2:
 
      fprintf(stderr, "Job number: ");
 
      scanf("%d", &jobnum);
 
      printJobInfo(distrenjob_get(&head, jobnum));
 
      break;
 
    case 3:
 
      find_jobframe(&head, &tmp_job, &tmp_frame);
 
      fprintf(stderr, "Job#:%d\n", tmp_job->jobnum);
 
      fprintf(stderr, "Frame#:%d\n", tmp_frame->num);
 
      break;
 
    case 4:
 
      name = NULL;
 
      submitter = NULL;
 
      email = NULL;
 

	
 
      fprintf(stderr, "\nType: \n\t 1 \t blender\n\t 2 \t povray\n"); scanf("%d", &type);
 
      fprintf(stderr, "\nName: ");        scanf("\n"); getline(&name, &read_buf, stdin);
 
      fprintf(stderr, "\nSubmitter: ");                getline(&submitter, &read_buf, stdin);
 
      fprintf(stderr, "\nEmail: ");                    getline(&email, &read_buf, stdin);
 
      fprintf(stderr, "\nPriority: ");                 scanf("%d", &priority);
 
      fprintf(stderr, "\nStart frame: ");              scanf("%d", &start_frame);
 
      fprintf(stderr, "\nEnd frame: ");                scanf("%d", &end_frame);
 
      fprintf(stderr, "\nWidth: ");                    scanf("%d", &width);
 
      fprintf(stderr, "\nHeight: ");                   scanf("%d", &height);
 
      prepare_distrenjob(&head, type, name, submitter, email, priority, start_frame, end_frame, width, height);
 
      break;
 
    case 5:
 
      fprintf(stderr, "\nJob number: ");
 
      scanf("%d", &jobnum);
 
      distrenjob_remove(&head, distrenjob_get(&head, jobnum));
 
      break;
 
    case 6:
 
      printAllJobnums(&head);
 
      break;
 
    case 7:
 
      fprintf(stderr,"Goodbye.\n");
 
      return 0;
 
    default:
 
      fprintf(stderr, "Invalid input, please try again.\n");
 
    }
 
  }
 

	
 
  distrend_listen(&listenset, config);
 
  /* This is called the "main loop" */
 
  while(cont)
 
    {
 
      struct distren_action *action;
 
      int clientsays = 0; /*< temporary example variable, will be replaced when we can handle messages */
 

	
 
      distrend_accept(&action);
 
      cont = distrend_do(action);
 

	
 
      /* Make the following code more event-driven */
 
      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 = 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
 
	    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){
 
      	  clientstatus = CLIENTSTATUS_IDLE; // Sets the client back to idle
 
      	  finish_frame(&head, job, frame->num); // @TODO: Make sure this actually works.
 
      	}
 

	
 
      distrend_action_free(action);
 
    }
 

	
 
  distrend_unlisten(listenset);
 
  distrend_config_free(config);
 

	
 
  xmlcleanup();
 

	
 
  return 0;
 
}
0 comments (0 inline, 0 general)