# HG changeset patch # User Binki # Date 2009-12-20 16:13:12 # Node ID 5b7ab20c5306f8aee008d27e44de0cf0222f7f05 # Parent 0433cb92a00c2ae8c98d6292fe8197247182f21f style fixes, move distrenjob_unserialize() to distrenjob.*, more struct geninfo use diff --git a/src/server/distrend.c b/src/server/distrend.c --- a/src/server/distrend.c +++ b/src/server/distrend.c @@ -38,12 +38,12 @@ #include #include -#include +#include #include #include -#include +#include +#include #include -#include /* local defs */ #define NUMBER_ELEVEN 11 @@ -78,14 +78,14 @@ void distrenjob_remove(struct general_in 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 distrenjob_serialize(struct general_info *geninfo, struct distrenjob *job); int update_xml_joblist(struct general_info *); -int createQueueFromXML(struct distrenjob *head); -int reCreateQueueFromXML(struct distrenjob *head, xmlDocPtr doc, xmlNodePtr current); +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); +char *job_getserialfilename(struct general_info *, unsigned int jobnum); /* ********************** Functions ************************* */ @@ -144,7 +144,7 @@ int start_data(struct general_info *gene fprintf(stderr, "FAILURE\n"); fprintf(stderr, "Restoring queue...\n"); - if(createQueueFromXML(&general_info->head)) + if(createQueueFromXML(general_info)) fprintf(stderr, "FAILURE\n"); fprintf(stderr, "done\n"); @@ -180,26 +180,35 @@ int mortition(struct general_info *genin 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); + _distren_asprintf(&path_and_number, "%s/stor/job%d/out/%d.%s", + geninfo->config->datadir, + 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--; geninfo->total_frames_rendered--; - isJobDone = 0; // if a missing frame is found, set isJobDone to false + /** if a missing frame is found, set isJobDone to false */ + isJobDone = 0; } + free(path_and_number); } - if(isJobDone) // if all frames were accounted for + /** if all frames were accounted for */ + if(isJobDone) { distrenjob_remove(geninfo, job); distrenjob_free(&job); geninfo->jobs_in_queue --; update_xml_joblist(geninfo); } - else{ - job->prev_frame_index = -1; // if the job isn't done, have frame_finder() start from the first frame, allowing it to see the frames that are now unassigned - } + else + /** + if the job isn't done, have frame_finder() start from the first frame, allowing it to see the frames that are now unassigned + */ + job->prev_frame_index = -1; update_general_info(geninfo); @@ -219,7 +228,7 @@ int restoreJobState(struct distrenjob *j 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); + _distren_asprintf(&path_and_number, "stor/job%d/out/%d.%s", job->jobnum, job->frameset[counter].num, job->output_format); /*< @TODO this path is used in multiple places, construct/build/determine it in a central function */ if(stat(path_and_number, &buffer) == 0) { job->frameset[counter].status = FRAMESETSTATUS_ASSIGNED; @@ -227,6 +236,7 @@ int restoreJobState(struct distrenjob *j } else isJobDone = 0; + free(path_and_number); } return isJobDone; @@ -239,6 +249,7 @@ int prepare_distrenjob(struct general_in int counter; int tmp; char *path_with_num; + char *serialfile; struct distrenjob *distrenjob; tmp = distrenjob_new(&distrenjob); @@ -273,11 +284,16 @@ int prepare_distrenjob(struct general_in } _distren_asprintf(&path_with_num, "stor/job%d/out/", distrenjob->jobnum); - fprintf(stderr, "creating dir '%s'", path_with_num); + fprintf(stderr, ">>NOT<< creating dir ``%s''\n", path_with_num); /*< @TODO recursively create job directory */ + serialfile = job_getserialfilename(geninfo, distrenjob->jobnum); + + free(path_with_num); /* add job to queue */ fprintf(stderr, "\nprepare_distrenjob: attempting distrenjob_serialize()\n"); - distrenjob_serialize(geninfo, distrenjob); + distrenjob_serialize(distrenjob, serialfile); + free(serialfile); + fprintf(stderr, "\nprepare_distrenjob: attempting distrenjob_enqueue()\n"); distrenjob_enqueue(geninfo, distrenjob); @@ -327,10 +343,12 @@ int distrenjob_enqueue(struct general_in /** Changes the priority of an existing (and maybe running) job. @arg head I may end up changing the head if job == head */ int change_job_priority(struct general_info *geninfo, struct distrenjob *job, int new_priority){ + struct distrenjob *current_job; + struct distrenjob *prev_job; + char *serialname; + distrenjob_remove(geninfo, job); job->priority = new_priority; - struct distrenjob *current_job; - struct distrenjob *prev_job; prev_job = &geninfo->head; @@ -357,7 +375,10 @@ int change_job_priority(struct general_i update_xml_joblist(geninfo); - distrenjob_serialize(geninfo, job); // because priority is changed + /** reserialize after changes */ + serialname = job_getserialfilename(geninfo, job->jobnum); + distrenjob_serialize(job, serialname); + free(serialname); return 0; } @@ -634,11 +655,11 @@ int distrend_do_config(int argc, char *a int tmp; /* - * test xml2distrenjob() + * test distrenjob_unserialize() */ - tmp = xml2distrenjob(&distrenjob, "distrenjob.xml.example"); + tmp = distrenjob_unserialize(&distrenjob, "distrenjob.xml.example"); if(tmp) - fprintf(stderr, "xml2distrenjob() returned %d. Try to cd to distren/doc if you want to test out the xml2distrenjob() function. (This will only fix this error if the error is due to an inability of the xml library to access distrenjob.xml.example)\n\n", tmp); + fprintf(stderr, "distrenjob_unserialize() returned %d. Try to cd to distren/doc if you want to test out the distrenjob_unserialize() function. (This will only fix this error if the error is due to an inability of the xml library to access distrenjob.xml.example)\n\n", tmp); else fprintf(stderr, "using email ``%s'' for user ``%s'' -- reading in XML files and pulling data from them using libxml2+XPath works!!!\n", distrenjob->email, distrenjob->submitter); @@ -736,92 +757,10 @@ int import_general_info(struct general_i return 0; } -/** - serializes a distrenjob into XML -*/ -int distrenjob_serialize(struct general_info *geninfo, struct distrenjob *job) -{ - xmlTextWriterPtr writer; - char *tmp; - char *tmpfile; - char *outfile; - int tmprtn; - - _distren_asprintf(&tmpfile, "%s/stor/job%d/.job_info.xml", geninfo->config->datadir, job->jobnum); - - /* create xml document at the location tmp with no compression */ - writer = xmlNewTextWriterFilename(tmpfile, 0); - xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); - - /** - 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); - xmlTextWriterWriteAttribute(writer, (xmlChar*)"priority", (xmlChar*)tmp); - free(tmp); - - /** - write resolution element and add its attributes */ - xmlTextWriterStartElement(writer, (xmlChar*)"resolution"); - _distren_asprintf(&tmp, "%d", job->width); - xmlTextWriterWriteAttribute(writer, (xmlChar*)"width", (xmlChar*)tmp); - free(tmp); - - _distren_asprintf(&tmp, "%d", job->height); - xmlTextWriterWriteAttribute(writer, (xmlChar*)"height", (xmlChar*)tmp); - free(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); - free(tmp); - - _distren_asprintf(&tmp, "%d", job->frameset[(job->total_frames - 1)].num); - xmlTextWriterWriteAttribute(writer, (xmlChar*)"end_fame", (xmlChar*)tmp); - free(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); - free(tmp); - - /** - end document */ - xmlTextWriterEndDocument(writer); - - /** - free writer and save xml file to disk */ - xmlFreeTextWriter(writer); - - _distren_asprintf(&outfile, "%s/stor/job%d/job_info.xml", geninfo->config->datadir, job->jobnum); - tmprtn = rename(tmpfile, outfile); - if(tmprtn == -1) - { - fprintf(stderr, "%s:%d: Error renaming ``%s'' to ``%s''\n", - __FILE__, __LINE__, - tmpfile, outfile); - perror("rename"); - tmprtn = 1; - } - free(tmpfile); - free(outfile); - - return tmprtn; -} // extracts data from the xml created by above function and creates a job from it // it returns a pointer to the created job -struct distrenjob *createJobFromXML(int job_number) +struct distrenjob *createJobFromXML(struct general_info *geninfo, unsigned int jobnum) { xmlDocPtr doc; xmlNodePtr cur; @@ -831,7 +770,7 @@ struct distrenjob *createJobFromXML(int int counter; int counter2; - _distren_asprintf(&file_name, "stor/job%d/job_info.xml", job_number); + file_name = job_getserialfilename(geninfo, jobnum); doc = xmlParseFile(file_name); if(!doc) @@ -859,8 +798,8 @@ struct distrenjob *createJobFromXML(int xmlFreeDoc(doc); - // load up stats.xml file to retrieve data - _distren_asprintf(&file_name, "stor/job%d/stats.xml", job_number); + /** load up stats.xml file to retrieve data */ + _distren_asprintf(&file_name, "stor/job%d/stats.xml", jobnum); doc = xmlParseFile(file_name); cur = xmlDocGetRootElement(doc); @@ -966,7 +905,7 @@ int update_xml_joblist(struct general_in 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) +int createQueueFromXML(struct general_info *geninfo) { int tmp; @@ -997,16 +936,19 @@ int createQueueFromXML(struct distrenjob // moves into the children elements of job_list cur = cur->xmlChildrenNode; - tmp = reCreateQueueFromXML(head, doc, cur); + 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 distrenjob *head, xmlDocPtr doc, xmlNodePtr current) +/** + 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 @@ -1015,23 +957,33 @@ int reCreateQueueFromXML(struct distrenj 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(head, doc, current->next)) + /** + 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)) + /** + bail if failure recursevely + ^-- is this the best thing to do in this case? + @TODO bail-out cleanup + */ return 1; - // now actual work is done, adding the job to the front of the queue - holder = head->next; // initialize holder + /** actual work is done now: add the job to the front of the queue */ + holder = geninfo->head.next; tmp = xmlNodeListGetString(doc, current->xmlChildrenNode, 1); // get job number job_num = atoi((char*)tmp); xmlFree(tmp); - job = createJobFromXML(job_num); + job = createJobFromXML(geninfo, job_num); if(job == NULL) return 1; - // insert job at front of the queue - head->next = job; + /** + insert job at front of the queue + */ + geninfo->head.next = job; job->next = holder; return 0; @@ -1301,3 +1253,18 @@ int main(int argc, char *argv[]) return 0; } + +/** + constructs the filename for a distrenjob's serialized XML + to be stored/retrieved from/in. + */ +char *job_getserialfilename(struct general_info *geninfo, unsigned int jobnum) +{ + char *filename; + + _distren_asprintf(&filename, "%s/stor/job/%d/distrenjob.xml", + geninfo->config->datadir, + jobnum); + + return filename; +} diff --git a/src/server/distrenjob.c b/src/server/distrenjob.c --- a/src/server/distrenjob.c +++ b/src/server/distrenjob.c @@ -23,6 +23,7 @@ #include #include +#include void distrenjob_free(struct distrenjob **distrenjob) { @@ -76,7 +77,7 @@ int distrenjob_new(struct distrenjob **d /** writes struct from xml */ -int xml2distrenjob(struct distrenjob **distrenjob, char *pathtoxml) +int distrenjob_unserialize(struct distrenjob **distrenjob, char *pathtoxml) { struct distrenjob *dj; @@ -155,3 +156,87 @@ int xml2distrenjob(struct distrenjob **d return 0; } +int distrenjob_serialize(struct distrenjob *job, char *outfile) +{ + xmlTextWriterPtr writer; + char *tmp; + char *tmpfile; + int tmprtn; + + /** + transactional FS access for POSIX systems... + (probably not implemented correctly) + */ + _distren_asprintf(&tmpfile, "%s_", outfile); + + /* create xml document at the location tmp with no compression */ + writer = xmlNewTextWriterFilename(tmpfile, 0); + xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); + + /** + 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); + xmlTextWriterWriteAttribute(writer, (xmlChar*)"priority", (xmlChar*)tmp); + free(tmp); + + /** + write resolution element and add its attributes */ + xmlTextWriterStartElement(writer, (xmlChar*)"resolution"); + _distren_asprintf(&tmp, "%d", job->width); + xmlTextWriterWriteAttribute(writer, (xmlChar*)"width", (xmlChar*)tmp); + free(tmp); + + _distren_asprintf(&tmp, "%d", job->height); + xmlTextWriterWriteAttribute(writer, (xmlChar*)"height", (xmlChar*)tmp); + free(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); + free(tmp); + + _distren_asprintf(&tmp, "%d", job->frameset[(job->total_frames - 1)].num); + xmlTextWriterWriteAttribute(writer, (xmlChar*)"end_fame", (xmlChar*)tmp); + free(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); + free(tmp); + + /** + end document */ + xmlTextWriterEndDocument(writer); + + /** + free writer and save xml file to disk */ + xmlFreeTextWriter(writer); + + /** + This is the key to transactioanl POSIX + FS programming. + */ + tmprtn = rename(tmpfile, outfile); + if(tmprtn == -1) + { + fprintf(stderr, "%s:%d: Error renaming ``%s'' to ``%s''\n", + __FILE__, __LINE__, + tmpfile, outfile); + perror("rename"); + tmprtn = 1; + } + free(tmpfile); + + return tmprtn; +} diff --git a/src/server/distrenjob.h b/src/server/distrenjob.h --- a/src/server/distrenjob.h +++ b/src/server/distrenjob.h @@ -84,10 +84,19 @@ struct frameset { distrenjob struct. @param pathtoxml filename/pathname of the xml file to be read into a distrenjob struct */ -int xml2distrenjob(struct distrenjob **distrenjob, char *pathtoxml); +int distrenjob_unserialize(struct distrenjob **distrenjob, char *pathtoxml); /** - support function for xml2distrenjob() to help cleaning up a + serialize a distrenjob into XML + @param distrenjob the address where we will store the pointer of a malloc()ed + distrenjob struct. + @param xmloutput filename/pathname of the xml file to be written + */ +int distrenjob_serialize(struct distrenjob *distrenjob, char *xmloutputpath); + + +/** + support function for distrenjob_unserialize() to help cleaning up a struct distrenjob when it is incompletely initialized. Also acts as a general-purpose struct distrenjob free()er ;-) */ diff --git a/src/server/slave.c b/src/server/slave.c --- a/src/server/slave.c +++ b/src/server/slave.c @@ -204,12 +204,12 @@ int main(int argc, char *argv[]) free(outdir); /* Parses a job's XML file, puts data in the myjob struct */ - if(xml2distrenjob(&myjob, pathtoXml) == 0) + if(distrenjob_unserialize(&myjob, pathtoXml) == 0) { fprintf(stderr, "Well, the XML craziness may have worked. Maybe. \n"); free(pathtoXml); - /* Frees things up if it was successful. xml2distrenjob() really (usually) only fails if malloc'ing inside it fails */ + /* Frees things up if it was successful. distrenjob_unserialize() really (usually) only fails if malloc'ing inside it fails */ distrenjob_free(&myjob); } else