# HG changeset patch # User Tero Marttila # Date 1212784665 -10800 # Node ID 43297144f19691125d6b20b34f16310bdab647f2 # Parent 082bfaf38cf0ddde8a9c2f34c4ee7c55c24a6bce * rename files, render_file -> file_main, render_node -> node_main, mandelbrot -> render_mandelbrot * make the error message stuff in common a /lot/ neater (a single function and a set of macros) * clean up rest of code to use those new macros committer: Tero Marttila diff -r 082bfaf38cf0 -r 43297144f196 Makefile --- a/Makefile Fri Jun 06 18:35:46 2008 +0300 +++ b/Makefile Fri Jun 06 23:37:45 2008 +0300 @@ -3,7 +3,7 @@ EXECS = render_file web_main render_node -all: render_file render_node web_main +all: render_file render_node render_web common.o: common.c common.h http.o: http.c http.h @@ -13,14 +13,15 @@ render_remote.o: render_remote.c render_remote.h render_png.o: render_png.c render_png.h render_local.o: render_local.c render_local.h +render_mandelbrot.o: render_mandelbrot.c render_mandelbrot.h -render_file.o: render_file.c -render_node.o: render_node.c +file_main.o: file_main.c +node_main.o: node_main.c web_main.o: web_main.c -render_file: render_file.o common.o render.o render_png.o render_local.o mandelbrot.o -render_node: render_node.o common.o render.o render_png.o render_local.o mandelbrot.o -web_main: web_main.o common.o http.o render.o remote_node.o remote_pool.o render_remote.o +render_file: file_main.o common.o render.o render_png.o render_local.o render_mandelbrot.o +render_node: node_main.o common.o render.o render_png.o render_local.o render_mandelbrot.o +render_web: web_main.o common.o http.o render.o remote_node.o remote_pool.o render_remote.o clean : rm *.o ${EXECS} diff -r 082bfaf38cf0 -r 43297144f196 common.c --- a/common.c Fri Jun 06 18:35:46 2008 +0300 +++ b/common.c Fri Jun 06 23:37:45 2008 +0300 @@ -7,75 +7,23 @@ #include "common.h" -void die (const char *msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -void error (const char *fmt, ...) { +void _generic_err (const char *func, int perr, int do_exit, const char *fmt, ...) { va_list va; - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - fprintf(stderr, "\n"); -} - -void perr (const char *fmt, ...) { - va_list va; - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - fprintf(stderr, ": %s\n", strerror(errno)); -} - -void perr_exit (const char *fmt, ...) { - va_list va; - + + if (func) + fprintf(stderr, "%s: ", func); + va_start(va, fmt); vfprintf(stderr, fmt, va); va_end(va); - - fprintf(stderr, ": %s\n", strerror(errno)); - exit(EXIT_FAILURE); -} - -void err_exit (const char *fmt, ...) { - va_list va; - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); + + if (perr) + fprintf(stderr, ": %s\n", strerror(errno)); fprintf(stderr, "\n"); - exit(EXIT_FAILURE); -} - -void err_func (const char *func, const char *fmt, ...) { - va_list va; - fprintf(stderr, "%s: ", func); - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - fprintf(stderr, "\n"); -} - -void perr_func (const char *func, const char *fmt, ...) { - va_list va; - - fprintf(stderr, "%s: ", func); - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - fprintf(stderr, ": %s\n", strerror(errno)); + if (do_exit) + exit(EXIT_FAILURE); } int parse_hostport (char *hostport, char **host, char **port) { diff -r 082bfaf38cf0 -r 43297144f196 common.h --- a/common.h Fri Jun 06 18:35:46 2008 +0300 +++ b/common.h Fri Jun 06 23:37:45 2008 +0300 @@ -3,32 +3,25 @@ * error handling */ -// perror + exit -void die (const char *msg); - -// fprintf + newline -void error (const char *fmt, ...); - -// fprintf + strerror + newline -void perr (const char *fmt, ...); +void _generic_err (const char *func, int perr, int do_exit, const char *fmt, ...); -// fprintf + strerror + newline + exit -void perr_exit (const char *fmt, ...); - -// fprintf + newline + exit -void err_exit (const char *fmt, ...); - -// fprintf (__func__ + msg, ...) -void err_func (const char *func, const char *fmt, ...); - -// fprintf (__func__ + msg + strerror, ...) -void perr_func (const char *func, const char *fmt, ...); +// various kinds of ways to handle an error, 2**3 of them, *g* +#define error(...) _generic_err(NULL, 0, 0, __VA_ARGS__) +#define err_exit(...) _generic_err(NULL, 0, 1, __VA_ARGS__) +#define perr(...) _generic_err(NULL, 1, 0, __VA_ARGS__) +#define perr_exit(...) _generic_err(NULL, 1, 1, __VA_ARGS__) +#define err_func(func, ...) _generic_err(func, 0, 0, __VA_ARGS__) +#define err_func_exit(func, ...) _generic_err(func, 0, 1, __VA_ARGS__) +#define perr_func(func, ...) _generic_err(func, 1, 0, __VA_ARGS__) +#define perr_func_exit(func, ...) _generic_err(func, 1, 1, __VA_ARGS__) // error(func + colon + msg, ...) + goto error -#define ERROR(msg) do { err_func(__func__, "%s", msg); goto error; } while (0) -#define ERROR_FMT(fmt, ...) do { err_func(__func__, fmt, __VA_ARGS__); goto error; } while (0) -#define PERROR(msg) do { perr_func(__func__, "%s", msg); goto error; } while (0) -#define PERROR_FMT(fmt, ...) do { perr_func(__func__, fmt, __VA_ARGS__); goto error; } while (0) +#define ERROR(...) do { err_func(__func__, __VA_ARGS__); goto error; } while (0) +#define PERROR(...) do { perr_func(__func__, __VA_ARGS__); goto error; } while (0) +#define FATAL(...) err_func_exit(__func__, __VA_ARGS__) +#define PFATAL(...) perr_func_exit(__func__, __VA_ARGS__) +#define WARNING(...) err_func(__func__, __VA_ARGS__) +#define PWARNING(...) perr_func(__func__, __VA_ARGS__) /* * Parse a host:port string. diff -r 082bfaf38cf0 -r 43297144f196 file_main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/file_main.c Fri Jun 06 23:37:45 2008 +0300 @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "render.h" +#include "render_local.h" + +static int verbose; + +int render_file_local (struct render *ctx, FILE *fh) { + double duration; + + if (render_io_stream(ctx, fh)) + ERROR("render_io_stream"); + + if (render_local(ctx, &duration)) + ERROR("render_local"); + + if (verbose) { + u_int32_t img_w, img_h; + + if (render_get_size(ctx, &img_w, &img_h)) + ERROR("render_get_size"); + + fprintf(stdout, "rendered %dx%d mandelbrot in %f seconds\n", img_w, img_h, duration); + } + + return 0; + +error: + return -1; +} + +int main (int argc, char **argv) { + int error = 1; + + struct render *ctx = NULL; + + // parse arguments + int opt; + FILE *output = NULL; + int img_w = 256, img_h = 256; + + while ((opt = getopt(argc, argv, "w:h:o:v")) != -1) { + switch(opt) { + case 'w' : + img_w = atoi(optarg); + break; + + case 'h' : + img_h = atoi(optarg); + break; + + case 'o' : + if (output) + err_exit("Only use -o once"); + + output = fopen(optarg, "w"); + + if (!output) + PFATAL("fopen: %s", optarg); + + break; + + case 'v' : + verbose = 1; + break; + + + default : + err_exit("Usage: %s [-w img_w] [-h img_h] [-o output_file] [-v]", argv[0]); + } + } + + if (!output) + output = stdout; + + // setup the struct render + if (!(ctx = render_alloc())) + ERROR("render_alloc"); + + if (render_set_mode(ctx, RENDER_PNG)) + ERROR("render_set_mode"); + + if (render_set_size(ctx, img_w, img_h)) + ERROR("render_set_size"); + + if (render_region_full(ctx)) + ERROR("render_region_full"); + + // do the render! + if (verbose) + fprintf(stderr, "Render [%dx%d] mandelbrot locally...\n", img_w, img_h); + + if (render_file_local(ctx, output)) + ERROR("render_local"); + + // success + error = 0; + +error: + if (output) + fclose(output); + + free(ctx); + + return error; +} + +#if 0 +void render_remote (int img_w, int img_h, FILE *output, FILE *remote) { + render_t ctx; + struct render_cmd cmd; + + render_init(&ctx, RENDER_PNG); + render_set_size(&ctx, img_w, img_h); + render_region_full(&ctx); + + if (render_cmd_build(&ctx, &cmd)) + err_exit("mandelbrot_render_remote failed"); + + int ret = fwrite((void *) &cmd, sizeof(cmd), 1, remote); + + if (ret != 1) + perr_exit("fwrite(remote)"); + + if (verbose) + printf("sent render command of %zu bytes\n", sizeof(cmd)); + + // shuffle data around + while (!feof(remote)) { + char buf[1024]; + + int bytes = fread(buf, 1, sizeof(buf), remote); + + if (bytes) + if (fwrite(buf, bytes, 1, output) != 1) + perr_exit("fwrite(output)"); + } + + if (verbose) + printf("got PNG data\n"); + + if (ferror(remote)) + perr_exit("fread(remote)"); +} + +FILE *open_remote (char *remote) { + char *addr_str, *port_str = NULL; + + addr_str = strsep(&remote, ":"); + + if (remote) + port_str = remote; + + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port_str ? atoi(port_str) : RENDER_PORT); + + if (inet_aton(addr_str, &addr.sin_addr) == 0) + err_exit("invalid address: %s", addr_str); + + int sock; + + if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) + perr_exit("socket"); + + if (verbose) + printf("connect(%s, %d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + if (connect(sock, (const struct sockaddr *) &addr, sizeof(addr)) == -1) + perr_exit("connect(%s, %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + FILE *fh = fdopen(sock, "w+"); + + if (!fh || ferror(fh)) + perr_exit("fdopen"); + + setbuffer(fh, NULL, 0); + + return fh; +} +#endif + + diff -r 082bfaf38cf0 -r 43297144f196 http.c --- a/http.c Fri Jun 06 18:35:46 2008 +0300 +++ b/http.c Fri Jun 06 23:37:45 2008 +0300 @@ -9,10 +9,8 @@ int http_qarg_parse (struct evhttp_request *request, struct http_qarg *qarg_spec) { // our return code - int error_flag = 0; + int error = -1; -#define ERROR(msg, ...) do { error("http_qarg_parse: " msg, __VA_ARGS__); error_flag = -1; goto error; } while (0) - // get the uri from the request const char *uri = evhttp_request_get_uri(request); @@ -41,7 +39,7 @@ int_val = strtol(qarg->value, &cptr, 10); if (*qarg->value == '\0' || *cptr != '\0' || int_val < 0) - ERROR("Invalid QARG_UINT: %s: %s -> %d", qarg->key, qarg->value, int_val); + ERROR("invalid QARG_UINT: %s: %s -> %d", qarg->key, qarg->value, int_val); *((unsigned long int *) qarg_info->hqa_addr) = (unsigned long int) int_val; @@ -51,17 +49,18 @@ ERROR("QARG_INVALID: %s: %s", qarg->key, qarg->value); default : - err_exit("http_qarg_parse: Invalid qarg_info->hqa_type: %d", qarg_info->hqa_type); + FATAL("invalid qarg_info->hqa_type: %d", qarg_info->hqa_type); } } } } - -#undef ERROR + + // success + error = 0; error: // clean up the qargs (badly named functions :< ) evhttp_clear_headers(&qargs); - return error_flag; + return error; } diff -r 082bfaf38cf0 -r 43297144f196 mandelbrot.c --- a/mandelbrot.c Fri Jun 06 18:35:46 2008 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#include -#include - -#include "render_internal.h" -#include "mandelbrot.h" -#include "common.h" - -#define DETAIL 255 - -#define absdelta(a, b) (a>b ? a-b : b-a) - -int render_mandelbrot (struct render *ctx) { - // render algorithm vars - u_int32_t img_x, img_y; - double x0, y0, x, y, _x, _y, w_scale, h_scale; - u_int8_t iter; - u_int8_t *row; - - // calcluate the scale factors - w_scale = ctx->img_w/absdelta(ctx->x1, ctx->x2); - h_scale = ctx->img_h/absdelta(ctx->y1, ctx->y2); - - // start rendering! - for (img_y=0; img_y < ctx->img_h; img_y++) { - // render the current row - for (img_x=0; img_x < ctx->img_w; img_x++) { - x = 0; - y = 0; - x0 = img_x/w_scale + ctx->x1; - y0 = img_y/h_scale + ctx->y1; - iter = DETAIL; - - while (x*x + y*y < (2*2) && iter > 0) { - _x = x*x - y*y + x0; - _y = 2*x*y + y0; - - x = _x; - y = _y; - - iter--; - } - - (*ctx->local_rowbuf_addr)[img_x] = iter; - } - - // row cb - if (ctx->local_row_fn(ctx->cb_arg, (*ctx->local_rowbuf_addr))) - ERROR("local_row_fn"); - } - - // return succesfully - return 0; - -error: - return -1; -} - -int render_mandelbrot_timed (struct render *ctx, double *duration) { - clock_t t1 = clock(); - int ret = render_mandelbrot(ctx); - clock_t t2 = clock(); - - *duration = ((double)(t2 - t1))/CLOCKS_PER_SEC; - - return ret; -} - diff -r 082bfaf38cf0 -r 43297144f196 mandelbrot.h --- a/mandelbrot.h Fri Jun 06 18:35:46 2008 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -#include "render.h" - -/* - * the mandelbrot-rendering algorithm - */ - -/* - * return codes for mandelbrot_render - */ -#define MANDELBROT_OK 0 -#define MANDELBROT_ERR 1 - -/* - * Render the image specified by the given render context - */ -int render_mandelbrot (struct render *ctx); -int render_mandelbrot_timed (struct render *ctx, double *duration); - diff -r 082bfaf38cf0 -r 43297144f196 node_main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/node_main.c Fri Jun 06 23:37:45 2008 +0300 @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "render.h" +#include "render_remote.h" // for RENDER_PORT_NAME +#include "render_local.h" + +void sigpipe_handler (int signal) { + /* ignore */ + fprintf(stderr, "SIGPIPE\n"); +} + +void sigpipe_ignore () { + struct sigaction sigpipe_action; + + memset(&sigpipe_action, 0, sizeof(sigpipe_action)); + sigpipe_action.sa_handler = SIG_IGN; + + if (sigaction(SIGPIPE, &sigpipe_action, NULL)) + perr_exit("sigaction"); +} + +int my_fread(FILE *fh, void *ptr, size_t size) { + int ret = fread(ptr, size, 1, fh); + + if (ret == 0) { + error("EOF"); + return 0; + + } else if (ret != 1) { + perror("fread"); + return 0; + } + + return 1; +} + +int read_byte (FILE *fh, u_int8_t *byte) { + return my_fread(fh, byte, sizeof(*byte)); +} + +int read_int (FILE *fh, u_int32_t *i) { + if (!my_fread(fh, i, sizeof(*i))) + return 0; + + *i = ntohl(*i); + + return 1; +} + +int read_double (FILE *fh, double *dbl) { + if (!my_fread(fh, dbl, sizeof(*dbl))) + return 0; + + return 1; +} + +void handle_client (int sock) { + double duration; + struct render *ctx; + FILE *fh; + u_int8_t mode; + u_int32_t img_w, img_h; + double x1, y1, x2, y2; + + + // open it as a FILE* + if (!(fh = fdopen(sock, "r+"))) + ERROR("fdopen"); + + // read the parameters + if ( + !read_byte(fh, &mode) + || !read_int(fh, &img_w) + || !read_int(fh, &img_h) + || !read_double(fh, &x1) + || !read_double(fh, &y1) + || !read_double(fh, &x2) + || !read_double(fh, &y2) + ) + ERROR("read_{byte,int,double}"); + + printf("RENDER: [%ux%u] (%f, %f) -> (%f, %f): ... ", img_w, img_h, x1, y1, x2, y2); + fflush(stdout); + + // set up the render_ctx + if (!(ctx = render_alloc())) + ERROR("render_alloc"); + + if (render_set_mode(ctx, mode)) + ERROR("render_set_mode"); + + if (render_set_size(ctx, img_w, img_h)) + ERROR("render_set_size"); + + if (render_region_raw(ctx, x1, y1, x2, y2)) + ERROR("render_region_raw"); + + if (render_io_stream(ctx, fh)) + ERROR("render_io_stream"); + + + // render! + if (render_local(ctx, &duration)) + ERROR("render_local"); + + printf("time=%fs\n", duration); + +error: + // close the FILE* and socket + fclose(fh); + + return; +} + + +int main (int argc, char** argv) { + int ssock, sock; + struct sockaddr_in addr; + socklen_t addr_len; + + // parse arguments + int opt; + const char *port_name = NULL; + unsigned short port; + + while ((opt = getopt(argc, argv, "l:")) != -1) { + switch (opt) { + case 'l': + if (port_name) + ERROR("only specify -l once"); + + port_name = optarg; + break; + + default: + err_exit("Usage: %s [-l port]", argv[0]); + } + } + + // post-process arguments + if (!port_name) + port_name = RENDER_PORT_NAME; + + if (!(port = atoi(port_name))) + ERROR("invalid port: %s", port_name); + + // create the socket + if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1) + PERROR("socket"); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(ssock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1) + PERROR("bind"); + + if (listen(ssock, 1) == -1) + PERROR("listen"); + + // ignore sigpipe + sigpipe_ignore(); + + // main accept loop + printf("RUN: %s:%hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + while (1) { + addr_len = sizeof(struct sockaddr_in); + + // accept a new client + if ((sock = accept(ssock, (struct sockaddr *) &addr, &addr_len)) == -1) + PERROR("accept"); + + printf("ACCEPT: %s:%hu\n", inet_ntoa(addr.sin_addr), addr.sin_port); + + // handle their resquest + handle_client(sock); + } + +error: + return 1; +} + diff -r 082bfaf38cf0 -r 43297144f196 render_file.c --- a/render_file.c Fri Jun 06 18:35:46 2008 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "render.h" -#include "render_local.h" - -static int verbose; - -int render_file_local (struct render *ctx, FILE *fh) { - double duration; - - if (render_io_stream(ctx, fh)) - ERROR("render_io_stream"); - - if (render_local(ctx, &duration)) - ERROR("render_local"); - - if (verbose) { - u_int32_t img_w, img_h; - - if (render_get_size(ctx, &img_w, &img_h)) - ERROR("render_get_size"); - - fprintf(stdout, "rendered %dx%d mandelbrot in %f seconds\n", img_w, img_h, duration); - } - - return 0; - -error: - return -1; -} - -int main (int argc, char **argv) { - int error = 1; - - struct render *ctx = NULL; - - // parse arguments - int opt; - FILE *output = NULL; - int img_w = 256, img_h = 256; - - while ((opt = getopt(argc, argv, "w:h:o:v")) != -1) { - switch(opt) { - case 'w' : - img_w = atoi(optarg); - break; - - case 'h' : - img_h = atoi(optarg); - break; - - case 'o' : - if (output) - err_exit("Only use -o once"); - - output = fopen(optarg, "w"); - - if (!output) - die(optarg); - - break; - - case 'v' : - verbose = 1; - break; - - - default : - err_exit("Usage: %s [-w img_w] [-h img_h] [-o output_file] [-v]", argv[0]); - } - } - - if (!output) - output = stdout; - - // setup the struct render - if (!(ctx = render_alloc())) - ERROR("render_alloc"); - - if (render_set_mode(ctx, RENDER_PNG)) - ERROR("render_set_mode"); - - if (render_set_size(ctx, img_w, img_h)) - ERROR("render_set_size"); - - if (render_region_full(ctx)) - ERROR("render_region_full"); - - // do the render! - if (verbose) - fprintf(stderr, "Render [%dx%d] mandelbrot locally...\n", img_w, img_h); - - if (render_file_local(ctx, output)) - ERROR("render_local"); - - // success - error = 0; - -error: - if (output) - fclose(output); - - free(ctx); - - return error; -} - -#if 0 -void render_remote (int img_w, int img_h, FILE *output, FILE *remote) { - render_t ctx; - struct render_cmd cmd; - - render_init(&ctx, RENDER_PNG); - render_set_size(&ctx, img_w, img_h); - render_region_full(&ctx); - - if (render_cmd_build(&ctx, &cmd)) - err_exit("mandelbrot_render_remote failed"); - - int ret = fwrite((void *) &cmd, sizeof(cmd), 1, remote); - - if (ret != 1) - perr_exit("fwrite(remote)"); - - if (verbose) - printf("sent render command of %zu bytes\n", sizeof(cmd)); - - // shuffle data around - while (!feof(remote)) { - char buf[1024]; - - int bytes = fread(buf, 1, sizeof(buf), remote); - - if (bytes) - if (fwrite(buf, bytes, 1, output) != 1) - perr_exit("fwrite(output)"); - } - - if (verbose) - printf("got PNG data\n"); - - if (ferror(remote)) - perr_exit("fread(remote)"); -} - -FILE *open_remote (char *remote) { - char *addr_str, *port_str = NULL; - - addr_str = strsep(&remote, ":"); - - if (remote) - port_str = remote; - - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons(port_str ? atoi(port_str) : RENDER_PORT); - - if (inet_aton(addr_str, &addr.sin_addr) == 0) - err_exit("invalid address: %s", addr_str); - - int sock; - - if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) - perr_exit("socket"); - - if (verbose) - printf("connect(%s, %d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - if (connect(sock, (const struct sockaddr *) &addr, sizeof(addr)) == -1) - perr_exit("connect(%s, %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - FILE *fh = fdopen(sock, "w+"); - - if (!fh || ferror(fh)) - perr_exit("fdopen"); - - setbuffer(fh, NULL, 0); - - return fh; -} -#endif - - diff -r 082bfaf38cf0 -r 43297144f196 render_local.c --- a/render_local.c Fri Jun 06 18:35:46 2008 +0300 +++ b/render_local.c Fri Jun 06 23:37:45 2008 +0300 @@ -1,19 +1,23 @@ #include +#include #include #include "common.h" #include "render_internal.h" #include "render_local.h" #include "render_png.h" -#include "mandelbrot.h" +#include "render_mandelbrot.h" int render_local (struct render *render, double *duration) { assert(render->mode == RENDER_PNG); unsigned char *rowbuf = NULL; struct render_png *png_ctx = NULL; + clock_t t1, t2; - *duration = -1; + + if (duration) + *duration = -1; // alloc the memory buffer if (!(rowbuf = malloc(render->img_w))) @@ -28,9 +32,17 @@ ERROR("render_local_mem"); // then we can actually render - if (duration ? render_mandelbrot_timed(render, duration) : render_mandelbrot(render)) + t1 = clock(); + + if (render_mandelbrot(render)) ERROR("render_mandelbrot"); + t2 = clock(); + + // calculate the time taken + if (duration) + *duration = ((double)(t2 - t1))/CLOCKS_PER_SEC; + // success return 0; diff -r 082bfaf38cf0 -r 43297144f196 render_mandelbrot.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/render_mandelbrot.c Fri Jun 06 23:37:45 2008 +0300 @@ -0,0 +1,54 @@ + +#include "common.h" +#include "render_internal.h" +#include "render_mandelbrot.h" + +#define DETAIL 255 + +#define absdelta(a, b) (a>b ? a-b : b-a) + +int render_mandelbrot (struct render *ctx) { + // render algorithm vars + u_int32_t img_x, img_y; + double x0, y0, x, y, _x, _y, w_scale, h_scale; + u_int8_t iter; + + // calcluate the scale factors + w_scale = ctx->img_w/absdelta(ctx->x1, ctx->x2); + h_scale = ctx->img_h/absdelta(ctx->y1, ctx->y2); + + // start rendering! + for (img_y=0; img_y < ctx->img_h; img_y++) { + // render the current row + for (img_x=0; img_x < ctx->img_w; img_x++) { + x = 0; + y = 0; + x0 = img_x/w_scale + ctx->x1; + y0 = img_y/h_scale + ctx->y1; + iter = DETAIL; + + while (x*x + y*y < (2*2) && iter > 0) { + _x = x*x - y*y + x0; + _y = 2*x*y + y0; + + x = _x; + y = _y; + + iter--; + } + + (*ctx->local_rowbuf_addr)[img_x] = iter; + } + + // row cb + if (ctx->local_row_fn(ctx->cb_arg, (*ctx->local_rowbuf_addr))) + ERROR("local_row_fn"); + } + + // return succesfully + return 0; + +error: + return -1; +} + diff -r 082bfaf38cf0 -r 43297144f196 render_mandelbrot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/render_mandelbrot.h Fri Jun 06 23:37:45 2008 +0300 @@ -0,0 +1,17 @@ +#include "render.h" + +/* + * the mandelbrot-rendering algorithm + */ + +/* + * return codes for mandelbrot_render + */ +#define MANDELBROT_OK 0 +#define MANDELBROT_ERR 1 + +/* + * Render the image specified by the given render context + */ +int render_mandelbrot (struct render *ctx); + diff -r 082bfaf38cf0 -r 43297144f196 render_node.c --- a/render_node.c Fri Jun 06 18:35:46 2008 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "render.h" -#include "render_remote.h" -#include "render_local.h" -#include "mandelbrot.h" - -void sigpipe_handler (int signal) { - /* ignore */ - fprintf(stderr, "SIGPIPE\n"); -} - -void sigpipe_ignore () { - struct sigaction sigpipe_action; - - memset(&sigpipe_action, 0, sizeof(sigpipe_action)); - sigpipe_action.sa_handler = SIG_IGN; - - if (sigaction(SIGPIPE, &sigpipe_action, NULL)) - perr_exit("sigaction"); -} - -int my_fread(FILE *fh, void *ptr, size_t size) { - int ret = fread(ptr, size, 1, fh); - - if (ret == 0) { - error("EOF"); - return 0; - - } else if (ret != 1) { - perror("fread"); - return 0; - } - - return 1; -} - -int read_byte (FILE *fh, u_int8_t *byte) { - return my_fread(fh, byte, sizeof(*byte)); -} - -int read_int (FILE *fh, u_int32_t *i) { - if (!my_fread(fh, i, sizeof(*i))) - return 0; - - *i = ntohl(*i); - - return 1; -} - -int read_double (FILE *fh, double *dbl) { - if (!my_fread(fh, dbl, sizeof(*dbl))) - return 0; - - return 1; -} - -void handle_client (int sock) { - double duration; - struct render *ctx; - FILE *fh; - u_int8_t mode; - u_int32_t img_w, img_h; - double x1, y1, x2, y2; - - - // open it as a FILE* - if (!(fh = fdopen(sock, "r+"))) - ERROR("fdopen"); - - // read the parameters - if ( - !read_byte(fh, &mode) - || !read_int(fh, &img_w) - || !read_int(fh, &img_h) - || !read_double(fh, &x1) - || !read_double(fh, &y1) - || !read_double(fh, &x2) - || !read_double(fh, &y2) - ) - ERROR("read_{byte,int,double}"); - - printf("RENDER: [%ux%u] (%f, %f) -> (%f, %f): ... ", img_w, img_h, x1, y1, x2, y2); - fflush(stdout); - - // set up the render_ctx - if (!(ctx = render_alloc())) - ERROR("render_alloc"); - - if (render_set_mode(ctx, mode)) - ERROR("render_set_mode"); - - if (render_set_size(ctx, img_w, img_h)) - ERROR("render_set_size"); - - if (render_region_raw(ctx, x1, y1, x2, y2)) - ERROR("render_region_raw"); - - if (render_io_stream(ctx, fh)) - ERROR("render_io_stream"); - - - // render! - if (render_local(ctx, &duration)) - ERROR("render_local"); - - printf("time=%fs\n", duration); - -error: - // close the FILE* and socket - fclose(fh); - - return; -} - - -int main (int argc, char** argv) { - int ssock, sock; - struct sockaddr_in addr; - socklen_t addr_len; - - // parse arguments - int opt; - const char *port_name = NULL; - unsigned short port; - - while ((opt = getopt(argc, argv, "l:")) != -1) { - switch (opt) { - case 'l': - if (port_name) - ERROR("only specify -l once"); - - port_name = optarg; - break; - - default: - err_exit("Usage: %s [-l port]", argv[0]); - } - } - - // post-process arguments - if (!port_name) - port_name = RENDER_PORT_NAME; - - if (!(port = atoi(port_name))) - ERROR_FMT("invalid port: %s", port_name); - - // create the socket - if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1) - PERROR("socket"); - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - if (bind(ssock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1) - PERROR("bind"); - - if (listen(ssock, 1) == -1) - PERROR("listen"); - - // ignore sigpipe - sigpipe_ignore(); - - // main accept loop - printf("RUN: %s:%hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - while (1) { - addr_len = sizeof(struct sockaddr_in); - - // accept a new client - if ((sock = accept(ssock, (struct sockaddr *) &addr, &addr_len)) == -1) - PERROR("accept"); - - printf("ACCEPT: %s:%hu\n", inet_ntoa(addr.sin_addr), addr.sin_port); - - // handle their resquest - handle_client(sock); - } - -error: - return 1; -} - diff -r 082bfaf38cf0 -r 43297144f196 web_main.c --- a/web_main.c Fri Jun 06 18:35:46 2008 +0300 +++ b/web_main.c Fri Jun 06 23:37:45 2008 +0300 @@ -1,18 +1,25 @@ +#include +#include +#include #include +#include +#include +#include +#include #include -#include #include #include #include +#include #include +#include "common.h" +#include "http.h" #include "render.h" #include "render_remote.h" #include "remote_node.h" #include "remote_pool.h" -#include "http.h" -#include "common.h" #define MIN_CHUNK_SIZE 4096 #define OVERFLOW_BUFFER 4096 @@ -156,11 +163,6 @@ } void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) { - // error message - const char *errmsg = NULL; - -#define ERROR(msg) do { errmsg = msg; goto error; } while (0) - // render request context struct render_request *req_ctx = calloc(1, sizeof(struct render_request)); @@ -172,14 +174,18 @@ req_ctx->bytes_sent = 0; // render context - render_t rend_ctx; - if (render_init(&rend_ctx, RENDER_PNG)) - ERROR("render_init"); + struct render *render; + + if (!(render = render_alloc())) + ERROR("render_alloc"); - if (render_set_size(&rend_ctx, img_w, img_h)) + if (render_set_mode(render, RENDER_PNG)) + ERROR("render_set_mode"); + + if (render_set_size(render, img_w, img_h)) ERROR("render_set_size"); - if (render_region_full(&rend_ctx)) + if (render_region_full(render)) ERROR("render_region_full"); // pick a render_node @@ -189,7 +195,7 @@ ERROR("remote_pool_get"); // initiate the remote render operation - if ((req_ctx->remote_ctx = render_remote(&rend_ctx, node_info, + if ((req_ctx->remote_ctx = render_remote(render, node_info, &_render_sent, &_render_data, &_render_done, @@ -198,8 +204,6 @@ )) == NULL) ERROR("render_remote"); -#undef ERROR /* can't be used after request has been sent */ - // set close cb evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx); @@ -208,7 +212,6 @@ return; error: - error("ERR: %s", errmsg); evhttp_send_error(request, 500, "Internal Server Error"); free(req_ctx); @@ -226,20 +229,19 @@ evhttp_request_get_peer(request, &peer_address, &peer_port); - // request arguments - unsigned long int img_w = 256, img_h = 256; - + u_int32_t img_w = 256, img_h = 256; + + // parse request arguments struct http_qarg qarg_spec[] = { { "w", QARG_UINT, &img_w }, { "h", QARG_UINT, &img_h }, { NULL, QARG_END, NULL } }; - // parse them http_qarg_parse(request, qarg_spec); // request log - printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%lu, img_h=%lu\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h); + printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h); // do it _http_render_execute(request, img_w, img_h); @@ -281,7 +283,7 @@ ev_base = event_init(); if (!ev_base) - die("event_init"); + FATAL("event_init"); // set up our render node pool remote_pool_init(&remote_pool); @@ -323,9 +325,9 @@ int pool_size = remote_pool_size(&remote_pool); - if (!pool_size) { - err_exit("No remote render nodes given"); - } + if (!pool_size) + FATAL("No remote render nodes given"); + printf("Registered %d render nodes in our pool\n", pool_size); @@ -340,11 +342,11 @@ struct evhttp *http_server = evhttp_new(ev_base); if (!http_server) - die("evhttp_new"); + FATAL("evhttp_new"); // bind to the correct interface/port if (evhttp_bind_socket(http_server, "0.0.0.0", 8117)) - die("evhttp_bind_socket"); + FATAL("evhttp_bind_socket"); // add our http request handler evhttp_set_cb(http_server, "/render", &http_render, NULL); @@ -354,7 +356,7 @@ // run the libevent mainloop if (event_base_dispatch(ev_base)) - die("event_dispatch"); + WARNING("event_dispatch"); printf("SHUTDOWN\n");