diff --git a/src/server/slave.c b/src/server/slave.c --- a/src/server/slave.c +++ b/src/server/slave.c @@ -25,6 +25,7 @@ #include "common/options.h" #include "common/protocol.h" #include "common/remoteio.h" +#include "common/request.h" #include #include @@ -34,11 +35,33 @@ #define DEBUG 0 +struct slave_state +{ + /* whether or not we've gotten past the copyright line */ + short copyright_done; + + /* number of bytes that we need to read before we have a whole packet */ + size_t expectlen; + /* whether or not we should exit */ + int quit; + + /* the server's remoteio handle */ + struct remoteio *rem; +}; + +static void distren_slave_remoteio_close_handle(void *blah, void *data); +static size_t distren_slave_remoteio_read_handle(struct remoteio *rem, + void *blah, + void *buf, + size_t len, + void *data); int main(int argc, char *argv[]) { multiio_context_t multiio; + struct slave_state slave_state; + char *datadir; char *server; char *username; @@ -59,8 +82,6 @@ int main(int argc, char *argv[]) // struct distrenjob *myjob; /* Structure to hold data gathered from the XML file - not needed anymore? */ - struct remoteio *comm_slave; - /** initializations */ @@ -145,14 +166,6 @@ int main(int argc, char *argv[]) return 1; } - fprintf(stderr, "Connecting to server...\n"); - if(remoteio_open_server(&comm_slave, commonopts->remoteio, NULL, NULL, server)) - { - fprintf(stderr, "Error connecting to server; exiting\n"); - return 1; - } - greet_server(comm_slave); - // Variables needed for main loop int jobnum = 0; int framenum = 0; @@ -174,13 +187,25 @@ int main(int argc, char *argv[]) char *outputExt = "jpg"; /* Output Extension (e.g., JPG) */ int haveWork = 0; - int quit = 0; - - fprintf(stderr,"\nDistRen Slave Pre-Alpha %s\n- Experimental build: Use at your own risk!\n\n", PACKAGE_VERSION); int benchmarkTime = 0; int renderPower = 0; + slave_state.copyright_done = 0; + slave_state.expectlen = 0; + slave_state.quit = 0; + + fprintf(stderr, "Connecting to server...\n"); + if(remoteio_open_server(&slave_state.rem, commonopts->remoteio, &distren_slave_remoteio_read_handle, &slave_state, &distren_slave_remoteio_close_handle, server)) + { + fprintf(stderr, "Error connecting to server; exiting\n"); + return 1; + } + greet_server(slave_state.rem); + + + fprintf(stderr,"\nDistRen Slave Pre-Alpha %s\n- Experimental build: Use at your own risk!\n\n", PACKAGE_VERSION); + // @TODO: add call to function to force recalc if $render_power == "" if(runBenchmark) { @@ -203,12 +228,16 @@ int main(int argc, char *argv[]) // Main loop - while(!quit) + while(!slave_state.quit) { + multiio_poll(multiio); + + if(slave_state.quit) + break; // request work fprintf(stderr, "Waiting...\n"); - haveWork = getwork(comm_slave, &jobnum, &framenum); + haveWork = getwork(slave_state.rem, &jobnum, &framenum); /* If we got a frame */ if(haveWork) @@ -223,13 +252,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "Preparing to render frame %d in job %d\n", framenum, jobnum); prepareJobPaths(jobnum, framenum, outputExt, datadir, &urltoTar, &pathtoTar,&pathtoTardir,&pathtoJob, &pathtoJobfile, &urltoJobfile, &urltoOutput, &pathtoOutput, &pathtoRenderOutput, &pathtoOutdir); - free(outputExt); int dlret = downloadTar(urltoTar, pathtoTar); if(dlret == 0) fprintf(stderr,"Data retrieved successfully!\n"); else if(dlret == 3){ - resetframe(comm_slave, jobnum, framenum); // Unassign the frame on the server so other slaves can render it + resetframe(slave_state.rem, jobnum, framenum); // Unassign the frame on the server so other slaves can render it return 0; // ouput dir doesn't exist } else @@ -245,7 +273,7 @@ int main(int argc, char *argv[]) // If error unpacking tarball if(unpackJob(pathtoJob, pathtoTar)){ - resetframe(comm_slave, jobnum, framenum); // Unassign the frame on the server so other slaves can render it + resetframe(slave_state.rem, jobnum, framenum); // Unassign the frame on the server so other slaves can render it fprintf(stderr,"Error decompressing tarball! Exiting.\n"); return 1; } @@ -270,7 +298,7 @@ int main(int argc, char *argv[]) if(exec_blender(pathtoJobfile, pathtoOutput, framenum)) { fprintf(stderr,"Error running Blender. Check your installation and/or your PATH.\n"); - resetframe(comm_slave, jobnum, framenum); // Unassign the frame on the server so other slaves can render it + resetframe(slave_state.rem, jobnum, framenum); // Unassign the frame on the server so other slaves can render it return 1; } free(pathtoJobfile); @@ -280,7 +308,7 @@ int main(int argc, char *argv[]) int fstatus = stat(pathtoOutput, &buffer); if(fstatus == -1){ fprintf(stderr,"*** %s doesn't exist! Scene may not have camera, or your blender installation is not working.\n", pathtoOutput); - resetframe(comm_slave, jobnum, framenum); // Unassign the frame on the server so other slaves can render it + resetframe(slave_state.rem, jobnum, framenum); // Unassign the frame on the server so other slaves can render it return 1; } else{ @@ -297,7 +325,18 @@ int main(int argc, char *argv[]) pathtoOutput = NULL; // Tell the server that rendering and upload are complete of "jobjum.framenum" - finishframe(comm_slave, jobnum, framenum); + finishframe(slave_state.rem, jobnum, framenum); + + free(urltoTar); + free(pathtoTar); + free(pathtoTardir); + free(pathtoJob); + free(pathtoJobfile); + free(urltoJobfile); + free(urltoOutput); + free(pathtoRenderOutput); + free(pathtoOutdir); + } } else{ @@ -323,20 +362,138 @@ int main(int argc, char *argv[]) sleep(5); // Poll 5 seconds. @TODO: Remove all polling } - fprintf(stderr,"Closing connection to server...\n"); - remoteio_close(comm_slave); + fprintf(stderr, "Quitting...\n"); + free(my_cfg); - free(outputExt); free(datadir); - free(urltoTar); - free(pathtoTar); - free(pathtoTardir); - free(pathtoJob); - free(pathtoJobfile); - free(urltoJobfile); - free(urltoOutput); - free(pathtoRenderOutput); - free(pathtoOutdir); - fprintf(stderr,"Goodbye!\n"); + fprintf(stderr, "Goodbye!\n"); return 0; } + +static void distren_slave_remoteio_close_handle(void *blah, void *data) +{ + struct slave_state *slave_state = (struct slave_state *)data; + + fprintf(stderr, "Lost connection to server\n"); + + slave_state->quit = 1; +} + +static size_t distren_slave_remoteio_read_handle(struct remoteio *rem, + void *blah, + void *buf, + size_t len, + void *data) +{ + struct slave_state *slave_state = (struct slave_state *)data; + + struct distren_request *req, *my_req; + void *req_data, *my_req_data; + + size_t to_return; + + size_t counter; + + /* to_return shall record how much of buf we've eaten already */ + to_return = 0; + + if(!slave_state->copyright_done) + { + putchar('\n'); + /* we have to flush through data until we hit a newline */ + for(counter = 0; + counter + slave_state->expectlen < 256 && counter < len && ((char *)buf)[counter] != '\n'; + counter ++) + { + putchar(((char *)buf)[counter]); + } + slave_state->expectlen += counter - 1; + if(slave_state->expectlen == 256) + { + fprintf(stderr, "\nThe server's greeting is too long. Maybe it speaks a foreign language\n"); + slave_state->quit = 1; + } + if(counter < len && ((char *)buf)[counter] == '\n') + { + putchar('\n'); + counter ++; + slave_state->expectlen = 0; + slave_state->copyright_done = 1; + to_return += counter; + buf += counter; + len -= counter; + } + if(!slave_state->copyright_done) + return to_return; + } + + while(1) + { + /* if we haven't read a full header yet: */ + if(!slave_state->expectlen) + { + if(len < sizeof(struct distren_request)) + return 0; + + /* figure out how much we need to read in before we can get anywhere */ + if(distren_request_new_fromdata(&req, buf, len)) + { + fprintf(stderr, "Failing to interpret data from server, exiting\n"); + slave_state->quit = 1; + return 0; + } + slave_state->expectlen = sizeof(struct distren_request) + req->len; + distren_request_free(req); + } + + if(slave_state->expectlen + && slave_state->expectlen <= len) + { + distren_request_new_fromdata(&req, buf, len); + req_data = buf + sizeof(struct distren_request); + + switch((enum distren_request_type)req->type) + { + case DISTREN_REQUEST_VERSION: + fprintf(stderr, "The server runs "); + for(counter = 0; counter < req->len; counter ++) + putc(((char *)req_data)[counter], stderr); + putc('\n', stderr); + break; + + case DISTREN_REQUEST_PING: + fprintf(stderr, "PONG ! :-D\n"); + + distren_request_poing(&my_req, &my_req_data, 0, req_data, req->len); + remoteio_write(slave_state->rem, &my_req, sizeof(struct distren_request)); + remoteio_write(slave_state->rem, &my_req_data, req->len); + distren_request_free_with_data(my_req, my_req_data); + break; + + case DISTREN_REQUEST_DISCONNECT: + /* hopefully this ends up being a useful message... */ + printf("You have been disconnected: \""); + for(counter = 0; counter < req->len; counter ++) + putchar(((char *)buf)[counter]); + putchar('"'); + putchar('\n'); + break; + + default: + fprintf(stderr, "something\n"); + break; + } + + distren_request_free(req); + slave_state->expectlen = 0; + + counter = req->len + sizeof(struct distren_request); + + len -= counter; + buf += counter; + to_return += counter; + } + } + + return to_return; +}