* 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 <terom@fixme.fi>
--- 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}
--- 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) {
--- 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.
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#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
+
+
--- 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;
}
--- 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 <stdlib.h>
-#include <time.h>
-
-#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;
-}
-
--- 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);
-
--- /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 <stdio.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#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;
+}
+
--- 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#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
-
-
--- 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 <stdlib.h>
+#include <time.h>
#include <assert.h>
#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;
--- /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;
+}
+
--- /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);
+
--- 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 <stdio.h>
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-
-#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;
-}
-
--- 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 <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
#include <signal.h>
-#include <string.h>
#include <unistd.h>
#include <event2/event.h>
#include <event2/event_compat.h>
+#include <event2/http.h>
#include <event2/event_struct.h>
+#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");