diff --git a/etc/Makefile.am b/etc/Makefile.am --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -1,1 +1,1 @@ -sysconf_DATA = distrenclient.conf distrencommon.conf distrenserver.conf distrenslave.conf +sysconf_DATA = distrenclient.conf distrencommon.conf distrendaemon.conf distrenslave.conf diff --git a/etc/distrenserver.conf b/etc/distrendaemon.conf rename from etc/distrenserver.conf rename to etc/distrendaemon.conf --- a/etc/distrenserver.conf +++ b/etc/distrendaemon.conf @@ -1,14 +1,14 @@ /* configuration for _this_ server */ -me +daemon { + datadir = "/var/lib/distren" render_types = {"povray", "blender", "inkscape", "imagemagick", "dcraw"} } include("distrencommon.conf") -datadir = "/var/lib/distren" listen { type = "unix" diff --git a/src/server/distrend.c b/src/server/distrend.c --- a/src/server/distrend.c +++ b/src/server/distrend.c @@ -77,7 +77,8 @@ int makeJobDataXML(struct distrenjob *jo int updateJobListXML(struct distrenjob *head); int createQueueFromXML(struct distrenjob *head); int reCreateQueueFromXML(struct distrenjob *head, xmlDocPtr doc, xmlNodePtr current); - +void updateGeneralInfo(); +void importGeneralInfo(); /* Global Vars, eliminate these */ jobnum_t jobnum = 0; // The next job number to create in the queue @@ -138,11 +139,9 @@ void remotio_send_to_client() /** Fill variables after crash / shutdown from XML dumps */ int start_data(struct distrenjob *head) { - general_info.hibernate = 0; struct stat buffer; - if(stat(SYSCONFDIR "/data.xml", &buffer) == 0){ - - // @TODO: retrieve total_finished_jobs and total_finished_frames from xml file + if(stat("general_info.xml", &buffer) == 0){ + importGeneralInfo(); fprintf(stderr,"Parsing XML files and restoring previous state...\n"); createQueueFromXML(head); @@ -151,6 +150,11 @@ int start_data(struct distrenjob *head) 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; } @@ -169,6 +173,8 @@ void finish_frame(struct distrenjob *hea { mortition(head, distrenjob); } + + updateGeneralInfo(); } /** "mortition" check to see if a job is actually done by scanning the folder of the job to make sure all frames are present*/ @@ -187,6 +193,7 @@ void mortition(struct distrenjob *head, { 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 } } @@ -201,6 +208,8 @@ void mortition(struct distrenjob *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 */ @@ -230,13 +239,16 @@ int restoreJobState(struct distrenjob *j } /** creates a structure from starting data, then calls another function to actually add that struct to the queue */ -void 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 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; - distrenjob_new(&distrenjob); + tmp = distrenjob_new(&distrenjob); + if(tmp) + return 1; distrenjob->type = 1; distrenjob->name = name; @@ -245,7 +257,13 @@ void prepare_distrenjob(struct distrenjo 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->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; @@ -259,9 +277,12 @@ void prepare_distrenjob(struct distrenjo /* add job to queue */ makeJobDataXML(distrenjob); distrenjob_enqueue(head, distrenjob); - updateJobListXML(head); general_info.jobs_in_queue++; + updateJobListXML(head); + updateGeneralInfo(); + + return 0; } @@ -366,17 +387,14 @@ void frame_watchdog(struct distrenjob *d struct distrenjob *distrenjob_ptr; unsigned int counter; - /*watchdog_forgiveness = seconds of forgiveness before frame is re-assigned */ - distrenjob_ptr = distrenjob_head; - - for(distrenjob_ptr = distrenjob_head; distrenjob_ptr; distrenjob_ptr = distrenjob_ptr->next) + 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 ++) - /* iterate through all frames for this job*/ - + /*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 @@ -468,7 +486,7 @@ int distrend_do_config(int argc, char *a *config = malloc(sizeof(struct distrend_config)); myopts[1].simple_value = &(*config)->datadir; - options_init(argc, argv, &(*config)->mycfg, myopts, "server", &(*config)->options); + options_init(argc, argv, &(*config)->mycfg, myopts, "daemon", &(*config)->options); fprintf(stderr, "using %s as datadir\n", (*config)->datadir); @@ -484,6 +502,62 @@ int distrend_config_free(struct distrend } /* ************************** XML Functions ************************* */ +// writes the general_info.xml file which is a copy of the general_info structure +// except that it doesn't hold free_clients and rendering_clients +void updateGeneralInfo() +{ + xmlTextWriterPtr writer; + char *tmp; + + writer = xmlNewTextWriterFilename("general_info.xml", 0); + xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); + + xmlTextWriterStartElement(writer, (xmlChar*)"general_info"); + + _distren_asprintf(&tmp, "%d", general_info.jobs_in_queue); + xmlTextWriterWriteElement(writer, (xmlChar*)"jobs_in_queue", (xmlChar*)tmp); + _distren_asprintf(&tmp, "%d", general_info.total_finished_jobs); + xmlTextWriterWriteElement(writer, (xmlChar*)"total_finished_jobs", (xmlChar*)tmp); + _distren_asprintf(&tmp, "%d", general_info.total_frames_rendered); + xmlTextWriterWriteElement(writer, (xmlChar*)"total_frames_rendered", (xmlChar*)tmp); + _distren_asprintf(&tmp, "%d", general_info.highest_jobnum); + xmlTextWriterWriteElement(writer, (xmlChar*)"highest_jobnum", (xmlChar*)tmp); + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); +} + +// this reads the information from general_info.xml to the general_info structure +void importGeneralInfo() +{ + xmlDocPtr doc; + xmlNodePtr cur; + + doc = xmlParseFile("general_info.xml"); + cur = xmlDocGetRootElement(doc); + if (xmlStrcmp(cur->name, (xmlChar*)"general_info")) + { + fprintf(stderr, "xml document is wrong type"); + xmlFreeDoc(doc); + return; + } + + cur = cur->xmlChildrenNode; + general_info.jobs_in_queue = atoi((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); + 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) @@ -495,10 +569,10 @@ int makeJobDataXML(struct distrenjob *jo // create xml document at the location tmp with no compression writer = xmlNewTextWriterFilename(tmp, 0); - xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL); + xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); - // write resolution element and add its attributes - xmlTextWriterStartElement(writer, (xmlChar*)"distrenjob"); + // 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); @@ -512,6 +586,23 @@ int makeJobDataXML(struct distrenjob *jo 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); + + // write total_render_time element + _distren_asprintf(&tmp, "%d", job->total_render_time); + xmlTextWriterWriteElement(writer, (xmlChar*)"total_render_time", (xmlChar*)tmp); + // end document xmlTextWriterEndDocument(writer); @@ -529,6 +620,9 @@ struct distrenjob *createJobFromXML(int xmlNodePtr cur; char *file_name; struct distrenjob *distrenjob; + int start_frame; + int counter; + int counter2; distrenjob_new(&distrenjob); @@ -545,6 +639,28 @@ struct distrenjob *createJobFromXML(int 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)); + + cur = cur->next; + distrenjob->total_render_time = (time_t)atol((char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); + + xmlFreeDoc(doc); + restoreJobState(distrenjob); return distrenjob; }