Changeset - f0273ec64281
[Not reviewed]
default
0 3 0
Nathan Brink (binki) - 16 years ago 2010-01-31 00:21:28
ohnobinki@ohnopublishing.net
remove NUMBER_ELEVEN, fix RUNSTATEDIR
3 files changed with 3 insertions and 7 deletions:
0 comments (0 inline, 0 general)
configure.ac
Show inline comments
 
# Copyright 2009 Nathan Phillip Brink, Ethan Zonca
 
#
 
# 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/>.
 

	
 
AC_PREREQ(2.61)
 
AC_INIT([distren],[0.0],[http://bugs.ohnopub.net/])
 
AC_CONFIG_SRCDIR([src/server/distrend.c])
 
AC_CONFIG_MACRO_DIR([m4])
 

	
 
AC_PROG_CC
 
AC_PROG_LIBTOOL
 
#AC_PROG_RANLIB #don't add this even if autoscan says to, because AC_PROG_LIBTOOL is enough
 

	
 
AM_INIT_AUTOMAKE
 
AM_PROG_CC_C_O
 

	
 
#basic low-level checks (suggested by autoscan)
 
AC_CHECK_FUNCS([dup2])
 
AC_CHECK_FUNCS([memset])
 
AC_CHECK_FUNCS([strdup])
 

	
 
AC_CHECK_HEADERS([fcntl.h])
 
AC_CHECK_HEADERS([malloc.h])
 

	
 
AC_FUNC_FORK
 
AC_FUNC_MALLOC
 

	
 
AC_TYPE_PID_T
 
AC_TYPE_SIZE_T
 

	
 
# selective compilation
 
AC_ARG_ENABLE([server],
 
	[AS_HELP_STRING([--disable-server],[Don't build the distren server])],
 
	[enable_server=$enableval],
 
	[enable_server=yes])
 
AM_CONDITIONAL([ENABLE_SERVER],
 
	[test "x$enable_server" = "xyes"])
 

	
 
# to grab GNU-specific function prototypes for the following functions:
 
# getline
 
AC_DEFINE([_GNU_SOURCE], [1])
 

	
 
#package dependencies:
 

	
 
PKG_PROG_PKG_CONFIG(0.17.2)
 

	
 

	
 
PKGCONFIG_OHNOWRAP([DISTLIBS], [libconfuse >= 2.5 libcurl libxml-2.0 liblist >= 2.2.1])
 

	
 
PKGCONFIG_OHNOWRAP([CHECK], [check >= 0.9.3])
 

	
 
# define paths for configuration files:
 

	
 
AC_DEFINE_DIR([LOCALSTATEDIR], [localstatedir], [Default directory for storing state information])
 
AC_DEFINE_DIR([RUNSTATEDIR], [runstatedir], [Default directory for registering runtime information like pid-files])
 
AC_DEFINE_DIR([RUNSTATEDIR], [localstatedir/run], [Default directory for registering runtime information like pid-files])
 

	
 
AC_CONFIG_FILES([Makefile
 
src/Makefile
 
src/tests/Makefile
 
etc/distrendaemon.conf
 
etc/distrenslave.conf
 
])
 

	
 
AC_OUTPUT
src/Makefile.am
Show inline comments
 

	
 
SUBDIRS = . tests
 

	
 
AM_CPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' \
 
	-DLOCALSTATEDIR='"$(localstatedir)"' \
 
	-DRUNSTATEDIR='"$(localstatedir)/run"' \
 
	-I. -I$(top_srcdir)/src/common
 
AM_CFLAGS = $(DISTLIBS_CFLAGS)
 
AM_LDFLAGS = $(DISTLIBS_LDFLAGS)
 
# LIBS, LDFLAGS, Huh!?
 
LIBS = $(DISTLIBS_LDADD)
 
LDADD = libdistrencommon.la
 

	
 
include_HEADERS = client/distren.h
 

	
 
bin_PROGRAMS = distren
 
if ENABLE_SERVER
 
bin_PROGRAMS += distrend distrenslave
 
endif
 

	
 
lib_LTLIBRARIES = libdistren.la
 
pkglib_LTLIBRARIES = libdistrencommon.la
 

	
 
# libdistrencommon.la:
 
libdistrencommon_la_SOURCES = common/options.c \
 
	common/options.h \
 
	common/execio.h \
 
	common/execio.c \
 
	common/remoteio.h \
 
	common/libremoteio.h \
 
	common/remoteio.c \
 
	common/asprintf.h \
 
	common/asprintf.c
 
#see http://sources.redhat.com/autobook/autobook/autobook_91.html
 
# either increase the revision number or the interface number each release!
 
libdistrencommon_la_LDFLAGS = $(AM_LDFLAGS) -version-info 0:0:0
 

	
 
# libdistren.la:
 
libdistren_la_SOURCES = $(include_HEADERS) \
 
	client/libdistren.h \
 
	client/libdistren.c \
 
	client/libdistren_job.c \
 
	client/libdistren_unbias.c \
 
	client/libdistren_config.c
 
libdistren_la_LIBADD = libdistrencommon.la
 
libdistren_la_LDFLAGS = $(AM_LDFLAGS) -version-info 0:0:0
 

	
 
# distren:
 
distren_SOURCES = client/distren.c
 
distren_LDADD = libdistren.la
 

	
 
# shared server sources:
 
SERVER_SOURCES = server/slavefuncs.c \
 
	server/slavefuncs.h \
 
	server/distrenjob.c \
 
	server/distrenjob.h
 
# distrend:
 
distrend_SOURCES = $(SERVER_SOURCES) \
 
	server/distrend.c \
 
	server/distrend.h \
 
	server/user_mgr.c \
 
	server/user_mgr.h \
 
	server/listen.h \
 
	server/listen.c
 
distrend_LDADD = libdistrencommon.la
 
# distrenslave:
 
distrenslave_SOURCES = $(SERVER_SOURCES) \
 
	server/slave.c
 
distrenslave_LDADD = libdistrencommon.la
 

	
src/server/distrend.c
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/>.
 

	
 
*/
 

	
 
/* This file contains the code which both processes (renders) jobs as a slave, and the code which distributes frames to slaves after receiving them from the client portion of the codebase. */
 

	
 
#include "asprintf.h"
 
#include "distrenjob.h"
 
#include "execio.h"
 
#include "listen.h"
 
#include "options.h"
 
#include "protocol.h"
 
#include "slavefuncs.h"
 

	
 
#include <confuse.h>
 
#include <malloc.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <sys/stat.h>
 
#include <sys/types.h>
 
#include <time.h>
 
#include <unistd.h>
 

	
 
#include <libxml/encoding.h>
 
#include <libxml/parser.h>
 
#include <libxml/tree.h>
 
#include <libxml/xmlmemory.h>
 
#include <libxml/xmlreader.h>
 
#include <libxml/xmlwriter.h>
 

	
 
/* local defs */
 
#define NUMBER_ELEVEN 11
 

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

	
 
struct general_info
 
{
 
  struct distrenjob head;
 

	
 
  struct distrend_config *config;
 

	
 
  struct
 
  {
 
    /** general_info.xml */
 
    char *geninfo;
 
    
 
  } files;
 

	
 
  int jobs_in_queue;
 
  unsigned int free_clients;
 
  unsigned int rendering_clients;
 
  unsigned int total_finished_jobs;
 
  unsigned int total_frames_rendered;
 
  unsigned int highest_jobnum;
 
  int hibernate;
 
  time_t timestamp;
 
  unsigned long total_render_power;
 
  unsigned long total_priority_pieces;
 
};
 

	
 

	
 

	
 
/*
 
  internally defined funcs's prototypes @TODO: Make all functions nice and proper 
 
*/
 
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);
 

	
 
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
 
*/
 
int distrend_do()
 
{
 
  return 0;
 
}
 

	
 
/** 
 
    Fill variables at startup from XML dumps or defaults
 
 */
 
int start_data(struct general_info *general_info)
 
{
 
  struct stat buffer;
 

	
 
  /**
 
     defaults
 
   */
 
  memset(&general_info->head, '\0', sizeof(struct distrenjob));
 
  general_info->head.priority = 0;
 

	
 
  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;
 
  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 ``%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");
 
      
 
@@ -430,193 +427,193 @@ int find_jobframe(struct general_info *g
 
  for(distrenjob_ptr = geninfo->head.next; distrenjob_ptr && !distrenjob_ptr->hibernate; distrenjob_ptr = distrenjob_ptr->next)
 
  {
 
    for(frame_counter = (distrenjob_ptr->prev_frame_index + 1); frame_counter < distrenjob_ptr->total_frames; frame_counter ++)
 
    {
 
      if(distrenjob_ptr->frameset[frame_counter].status == FRAMESETSTATUS_UNASSIGNED) // jobframe found
 
      {
 
    	found = 1;
 
    	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)
 
    	break;
 
    }
 

	
 
    if(found)
 
      break;
 
  }
 

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

	
 
int find_jobframe_from_job(struct distrenjob *distrenjob_ptr, struct distrenjob **job, struct frameset **frame)
 
{
 
  unsigned int frame_counter;
 
  unsigned short int found;
 

	
 
  found = 0;
 
  for(frame_counter = (distrenjob_ptr->prev_frame_index + 1); frame_counter < distrenjob_ptr->total_frames; frame_counter ++)
 
  {
 
    if(distrenjob_ptr->frameset[frame_counter].status == FRAMESETSTATUS_UNASSIGNED) // jobframe found
 
      {
 
    	found = 1;
 
		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)
 
      break;
 
  }
 

	
 

	
 
  if(!found)
 
    {
 
      fprintf(stderr, "No more frames in this job number %d", distrenjob_ptr->jobnum);
 
      distrenjob_ptr->prev_frame_index = frame_counter;
 
      return 1;
 
    }
 

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

	
 
  return 0;
 
}
 

	
 
// find a frame to render when the job that the last frame was for no longer exists
 
int find_jobframe_new(struct general_info *geninfo, int rend_pwr, struct distrenjob **job, struct frameset **frame)
 
{
 
  if(geninfo->hibernate)
 
    return 1;
 

	
 
  float power_difference;
 
  float greatest_power_difference;
 
  unsigned short int found;
 
  struct distrenjob *job_to_render;
 

	
 
  struct distrenjob *distrenjob_ptr;
 

	
 
  greatest_power_difference = -10000;
 
  found = 0;
 
  /* iterate through jobs from first to last */
 
  for(distrenjob_ptr = geninfo->head.next;
 
      distrenjob_ptr && !distrenjob_ptr->hibernate;
 
      distrenjob_ptr = distrenjob_ptr->next)
 
  {
 
	  if(distrenjob_ptr->prev_frame_index < (distrenjob_ptr->total_frames - 1))
 
	  {
 
	    /**
 
	       Why is the number 11 found here again? --ohnobinki
 
	     */
 
		  power_difference = (((float)geninfo->total_render_power / (float)geninfo->total_priority_pieces) * (NUMBER_ELEVEN - (float)distrenjob_ptr->priority));
 
		  power_difference = (((float)geninfo->total_render_power / (float)geninfo->total_priority_pieces) * ((float)distrenjob_ptr->priority));
 
		  power_difference = power_difference - (float)distrenjob_ptr->assigned_render_power;
 

	
 
		  fprintf(stderr, "job num %d\npower difference: %f\n", distrenjob_ptr->jobnum, power_difference);
 

	
 
		  if(power_difference > greatest_power_difference)
 
		  {
 
			  job_to_render = distrenjob_ptr;
 
			  greatest_power_difference = power_difference;
 
			  found = 1;
 
		  }
 
	  }
 
  }
 

	
 
  if(!found)
 
    {
 
      fprintf(stderr, "No more jobs to render\n");
 
      return 1;
 
    }
 

	
 
  find_jobframe_from_job(job_to_render, job, frame);
 
  job_to_render->assigned_render_power = job_to_render->assigned_render_power + rend_pwr;
 

	
 
  return 0;
 
}
 

	
 
// gets a frame to render from the same job that the previously rendered frame was from
 
int find_jobframe_again(struct general_info *geninfo, int jobnum, int rend_pwr, struct distrenjob **job, struct frameset **frame)
 
{
 
  if(geninfo->hibernate)
 
    return 1;
 

	
 
  short int found;
 
  struct distrenjob *distrenjob_ptr;
 

	
 
  distrenjob_ptr = distrenjob_get(&geninfo->head, jobnum);
 

	
 
  // if the job was not found or there are no frames left in the job...
 
  if(!distrenjob_ptr || distrenjob_ptr->prev_frame_index >= (distrenjob_ptr->total_frames - 1))
 
    {
 
      fprintf(stderr, "Job number %d has been finished, finding new job\n", jobnum);
 

	
 
      // if previous job isn't yet finished the render power of the slave is removed from it
 
      if(distrenjob_ptr)
 
    	  distrenjob_ptr->assigned_render_power = distrenjob_ptr->assigned_render_power - rend_pwr;
 

	
 
      return find_jobframe_new(geninfo, rend_pwr, job, frame);
 
    }
 

	
 
  found = 0;
 
  found = find_jobframe_from_job(distrenjob_ptr, job, frame);
 

	
 
  if(found)
 
	  find_jobframe_new(geninfo, rend_pwr, job, frame);
 

	
 
  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.
 
@@ -803,193 +800,193 @@ int restore_distrenjob(struct general_in
 
  
 
  free(file_name);
 
  return tmp;
 
}
 

	
 
int updateJobStatsXML(struct distrenjob *job)
 
{
 
	  xmlTextWriterPtr writer;
 
	  char *tmp;
 

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

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

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

	
 
	  _distren_asprintf(&tmp, "%d", job->completed_frames);
 
	  xmlTextWriterWriteAttribute(writer, (xmlChar*)"completed_frames", (xmlChar*)tmp);
 
	  free(tmp);
 

	
 
	  _distren_asprintf(&tmp, "%d", job->total_render_time);
 
	  xmlTextWriterWriteAttribute(writer, (xmlChar*)"total_render_time", (xmlChar*)tmp);
 
	  free(tmp);
 

	
 
	  /**
 
	     end document
 
	  */
 
	  xmlTextWriterEndDocument(writer);
 
	  /**
 
	     free writer and save xml file to disk
 
	     @TODO confirma that calling xmlFreeTextWriter calls
 
	           write() and close(), respectively.
 
		   (close() causes asynchronous writes to be
 
		   completed).
 
	  */
 
	  xmlFreeTextWriter(writer);
 

	
 
	  return 1;
 
}
 

	
 

	
 
/**
 
   updates job_list.xml which lists all the jobs in the queue
 
   @return 0 means success
 
*/
 
int update_xml_joblist(struct general_info *geninfo)
 
{
 
  struct distrenjob *job;
 
  xmlTextWriterPtr writer;
 
  char *tmp;
 
  int counter;
 

	
 
  /**
 
     update timestamp
 
  */
 
  geninfo->timestamp ++;
 
  if(geninfo->timestamp > 65530)
 
    geninfo->timestamp = 0;
 

	
 
  _distren_asprintf(&tmp, "%s/job_list.xml",
 
		    geninfo->config->datadir);
 
  writer = xmlNewTextWriterFilename(tmp, 0);
 
  free(tmp);
 

	
 
  xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL);
 

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

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

	
 
  geninfo->total_priority_pieces = 0;
 
  counter = 0;
 
  for(job = geninfo->head.next; job; job = job->next)
 
    {
 
      _distren_asprintf(&tmp, "%d", job->jobnum);
 
      xmlTextWriterWriteElement(writer, (xmlChar*)"jobnum", (xmlChar*)tmp);
 
      free(tmp);
 

	
 
      /**
 
	this is needed for the new frame finder to work 
 
      
 
	Why the random constant numeral 11? --ohnobinki
 
      */
 
      geninfo->total_priority_pieces = geninfo->total_priority_pieces + (NUMBER_ELEVEN - job->priority);
 
      geninfo->total_priority_pieces = geninfo->total_priority_pieces + job->priority;
 

	
 
      counter++;
 
    }
 

	
 
  xmlTextWriterEndElement(writer);
 

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

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

	
 
/**
 
 returns 0 if completed successfully
 
 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 general_info *geninfo)
 
{
 
  int tmp;
 

	
 
  xmlDocPtr doc;
 
  xmlNodePtr cur;
 

	
 
  char *xmllist_path;
 

	
 
  /**
 
     load xml document
 
  */
 

	
 
  _distren_asprintf(&xmllist_path, "%s/job_list.xml", geninfo->config->datadir);
 
  doc = xmlParseFile(xmllist_path);
 
  if(doc == NULL)
 
    {
 
      fprintf(stderr, "createQueueFromXML: ``%s'' could not be not loaded\n",
 
	      xmllist_path);
 

	
 
      free(xmllist_path);
 
      return 1;
 
    }
 
  free(xmllist_path);
 

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

	
 
  if(xmlStrcmp(cur->name, (const xmlChar*)"job_list"))
 
    {
 
      fprintf(stderr, "createQueueFromXML: incorrect root element (%s)", (char*)cur->name);
 
    }
 
  else
 
    fprintf(stderr, "USING %s\n", cur->name);
 

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

	
 
  tmp = reCreateQueueFromXML(geninfo, doc, cur);
 

	
 
  xmlFreeDoc(doc);
 

	
 
  return tmp;
 
}
 

	
 
/**
 
   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 general_info *geninfo, 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;
 
  jobnum_t 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
 
  */
 
  if(reCreateQueueFromXML(geninfo, doc, current->next))
0 comments (0 inline, 0 general)