diff --git a/src/server/distrend.c b/src/server/distrend.c --- a/src/server/distrend.c +++ b/src/server/distrend.c @@ -84,15 +84,7 @@ struct general_info int distrend_do(); int start_data(struct general_info *general_info); int mortition(struct general_info *geninfo, struct distrenjob *job); -// int restoreJobState(struct distrenjob *job); -// int prepare_distrenjob(struct general_info *geninfo, int type, char *name, char *submitter, int priority, int start_frame, int end_frame, int width, int height); -// int distrenjob_enqueue(struct general_info *geninfo, struct distrenjob *job); -// int find_jobframe_from_job(struct distrenjob *distrenjob_ptr, struct distrenjob **job, struct frameset **frame); -// int find_jobframe_new(struct general_info *geninfo, int rend_pwr, struct distrenjob **job, struct frameset **frame); -// int find_jobframe_again(struct general_info *geninfo, int jobnum, int rend_pwr, struct distrenjob **job, struct frameset **frame); void frame_watchdog(struct distrenjob *distrenjob_head); -// struct distrenjob *distrenjob_get(struct distrenjob *head, jobnum_t jobnum); -// void distrenjob_remove(struct general_info *geninfo, struct distrenjob *bj); int distrend_do_config(int argc, char *argv[], struct distrend_config **config); int distrend_config_free(struct distrend_config *config); @@ -155,14 +147,6 @@ int main(int argc, char *argv[]) _distren_asprintf(&general_info.files.geninfo, "%s/general_info.xml", general_info.config->datadir); - /* @QUERY: Obselete? - if(start_data(&general_info)) - { - fprintf(stderr, "%s:%d: start_data() failed\n", __FILE__, __LINE__); - return 1; - } - */ - /** MySQL Connection */ if(mysqlConnect(&general_info.conn)) { @@ -170,10 +154,6 @@ int main(int argc, char *argv[]) return 1; } - /** pre-loaded jobs for testing */ - // prepare_distrenjob(&general_info, 1, "awesome", "LordOfWar", 8, 1, 100, 640, 480); - // prepare_distrenjob(&general_info, 1, "hamburger", "ohnobinki", 3, 1, 50, 1280, 720); - /** Execute test function */ // interactiveTest(test, general_info); @@ -226,16 +206,6 @@ int main(int argc, char *argv[]) /* ********************** 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*/ -// @QUERY: Obselete function, get rid of me! -/* -int xml_dump() -{ - return 0; -} -*/ - - /** Performs command stored in a client's request. @TODO: Fill stub */ @@ -244,486 +214,20 @@ int distrend_do() return 0; } -/** - Fill variables at startup from XML dumps or defaults - */ -// @QUERY: Obselete function, as data is stored in sql now. - -/* -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"); - - fprintf(stderr, "Restoring queue...\n"); - if(createQueueFromXML(general_info)) - fprintf(stderr, "FAILURE\n"); - - fprintf(stderr, "done\n"); - } - - return 0; -} -*/ - -/** - checks to see if a job is actually done. - - scans the folder of the job to make sure all output files are present -*/ -// @QUERY: Needs some complex query work - -/* -int mortition(struct general_info *geninfo, 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, "%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) - { - - // missing frame found - - job->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED; - job->completed_frames--; - geninfo->total_frames_rendered--; - isJobDone = 0; - } - free(path_and_number); - } - - if(isJobDone) - { - - // all frames were accounted for - - distrenjob_remove(geninfo, job); - distrenjob_free(&job); - update_xml_joblist(geninfo); - } - 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); - - return 0; -} -*/ - -/** - scans the frames of a job to initialize a job after server - @return 0 if the job is completely done and there are no missing frames, - 1 if missing frames are found. -*/ -// @QUERY: Obselete with mysql job/frame storage - -/* -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); //< @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; - job->completed_frames++; - } - else - isJobDone = 0; - free(path_and_number); - } - - return !isJobDone; -} -*/ - - -/** - creates a structure from starting data, then calls another - function to actually add that struct to the queue. - - Passed strings must be free()d by the caller. -*/ -// @QUERY: Likely obselete, as jobs are submitted via the web - -/* -int prepare_distrenjob(struct general_info *geninfo, int type, char *name, char *submitter, int priority, int start_frame, int end_frame, int width, int height) -{ - int counter; - int counter2; - int tmp; - char *serialfile; - - struct distrenjob *distrenjob; - tmp = distrenjob_new(&distrenjob); - if(tmp) - return 1; - - geninfo->highest_jobnum ++; - distrenjob->jobnum = geninfo->highest_jobnum; - - distrenjob->type = 1; - distrenjob->name = strdup(name); - distrenjob->submitter = strdup(submitter); - distrenjob->priority = priority; - distrenjob->width = width; - distrenjob->height = height; - // sets the total number of frames in animation for status purposes - distrenjob->total_frames = (end_frame - start_frame + 1); - distrenjob->frameset = malloc(sizeof(struct frameset) * distrenjob->total_frames); - if(!distrenjob->frameset) - { - distrenjob_free(&distrenjob); - fprintf(stderr, "OOM\n"); - - return 1; - } - - - - // initialize frameset - counter2 = start_frame; - for(counter = 0; counter < distrenjob->total_frames; counter++) - { - distrenjob->frameset[counter].num = counter2; - distrenjob->frameset[counter].status = FRAMESETSTATUS_UNASSIGNED; - - counter2 ++; - } - - job_getserialfilename(&serialfile, geninfo, distrenjob->jobnum, 1); - - -// add job to queue - - fprintf(stderr, "prepare_distrenjob(): attempting distrenjob_serialize(%d, \"%s\")\n", - distrenjob->jobnum, serialfile); - distrenjob_serialize(distrenjob, serialfile); - free(serialfile); - - fprintf(stderr, "prepare_distrenjob(): attempting distrenjob_enqueue()\n"); - distrenjob_enqueue(geninfo, distrenjob); - - fprintf(stderr, "prepare_distrenjob(): attempting update_xml_joblist()\n"); - update_xml_joblist(geninfo); - fprintf(stderr, "prepare_distrenjob(): attempting update_general_info()\n"); - update_general_info(geninfo); - fprintf(stderr, "prepare_distrenjob(): attempting updateJobStatsXML()\n"); - updateJobStatsXML(distrenjob); - - return 0; -} -*/ - - - -/** - Adds the job to the queue based on its priority. - Updates geninfo->jobs_in_queue. -*/ -// @QUERY: Likely obselete, enqueueing is done via web interface - -/* -int distrenjob_enqueue(struct general_info *geninfo, struct distrenjob *job) -{ - struct distrenjob *prev_job; - struct distrenjob *current_job; - struct distrenjob *head; - - head = &geninfo->head; - prev_job = head; - - -// iterate through linked jobs - - for(current_job = head->next; current_job; current_job = current_job->next) - { - fprintf(stderr, "enqueue loop iteration\n"); - if(job->priority < current_job->priority) - { - - // if job's priority is less than current_job's priority, insert job - // keep in mind 1 is the highest priority given to jobs, head has a - // priority of zero so it will always be before other jobs - - prev_job->next = job; - job->next = current_job; - fprintf(stderr, "added job before jobname: ``%s''\n", current_job->name); - - geninfo->jobs_in_queue ++; - return 0; - } - - prev_job = current_job; - } - - - // if it has reached the end of the list, add job there - - prev_job->next = job; - fprintf(stderr, "added job at end of queue\n"); - - geninfo->jobs_in_queue ++; - return 0; -} -*/ - - - -// @QUERY: Obselete? -/* -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 -// @QUERY: Obselete? -/* -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) * ((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 -// @QUERY: Obselete? -/* -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); - } + // Replace with mysqlness, maybe + // iterate through jobs + // if the job has been started, checks by seeing if either to first or second frame has been started + // FRAMESETSTATUS_UNASSIGNED + // iterate through all frames for this job: + //watchdog_forgiveness = seconds of forgiveness before frame is re-assigned: + // If frame is not completed within the number of seconds specified by watchdog_forgiveness + // Then change the frame status to unassigned } -/** - Finds a distrenjob struct based on the jobnum - @arg jobnum job number to search for - @return NULL on job doesn't exist - */ -// @QUERY: Obselete -/* -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. - Updates geninfo->jobs_in_queue. - - @arg head pointer to the head of the linkedlist of distrenjobs - */ -// @QUERY: Obselete: removal done via web interface -/* -void distrenjob_remove(struct general_info *geninfo, struct distrenjob *bj) -{ - struct distrenjob *previous_distrenjob; - - for(previous_distrenjob = &geninfo->head; - previous_distrenjob - && previous_distrenjob->next != bj; //< stop on the distrenjob that comes before bj - previous_distrenjob = previous_distrenjob->next) - ; - - - // 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; - - geninfo->jobs_in_queue --; -} -*/ - /* Grabs config info from confs */ int distrend_do_config(int argc, char *argv[], struct distrend_config **config) @@ -852,73 +356,6 @@ int import_general_info(struct general_i return 0; } -/** - determines path to the distenjob XML file and - calls distrenjob_unserialize() - */ -// @QUERY: Likely obselete (don't remove at request of ohnobinki) -int restore_distrenjob(struct general_info *geninfo, struct distrenjob **distrenjob, jobnum_t jobnum) -{ - int tmp; - char *file_name; - - tmp = job_getserialfilename(&file_name, geninfo, jobnum, 0); - if(tmp) - return tmp; - - tmp = distrenjob_unserialize(distrenjob, file_name); - if(tmp) - fprintf(stderr, "failed to load job %d from ``%s''\n", - jobnum, file_name); - - free(file_name); - return tmp; -} - -// @QUERY: Likely obselete (don't remove at request of ohnobinki) -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 @@ -987,112 +424,6 @@ int update_xml_joblist(struct general_in 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 -*/ -// @QUERY: Likely obselete (don't remove at request of ohnobinki) -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 -*/ -// @QUERY: Likely obselete (don't remove at request of ohnobinki) -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)) - /** - bail if failure recursevely - ^-- is this the best thing to do in this case? - @TODO bail-out cleanup - */ - return 1; - - /** 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); - - if(restore_distrenjob(geninfo, &job, job_num)) - return 1; - - /** - insert job at front of the queue - */ - geninfo->head.next = job; - job->next = holder; - - return 0; -} - /* ************************** Test Functions ************************* */ /** Prints info about frames in a frameset */ @@ -1270,7 +601,9 @@ int interactiveTest(int test, struct gen } */ + /** + @TODO: reuse for constructing data paths? constructs the filename for a distrenjob's serialized XML to be stored/retrieved from/in. @arg filename pointer to filename allocated using something @@ -1292,23 +625,3 @@ int job_getserialfilename(char **filenam return 0; } -/** Creates directories recursively */ -int distren_mkdir_recurse(char *dirname) -{ - size_t counter; - char *nextdir; - - nextdir = strdup(dirname); - for(counter = 0; nextdir[counter]; counter ++) - { - /** @TODO OS-portabalize the path-separators */ - if(nextdir[counter] == '/') - { - nextdir[counter] = '\0'; - mkdir(nextdir, S_IRWXU | S_IRGRP | S_IROTH); - nextdir[counter] = '/'; - } - } - - return 0; -}