added a rawio interface to render_remote, this broke render_multi.c but it needs a rewrite now anyways
committer: Tero Marttila <terom@fixme.fi>
--- a/Makefile Sat Jun 07 05:18:06 2008 +0300
+++ b/Makefile Sun Jun 08 21:03:23 2008 +0300
@@ -14,7 +14,7 @@
render_png.o: render_png.c render_png.h
render_raw.o: render_raw.c render_raw.h
render_local.o: render_local.c render_local.h
-render_multi.o: render_multi.c render_multi.h
+render_multi.o: render_multi.c render_multi.h render_remote.h
render_mandelbrot.o: render_mandelbrot.c render_mandelbrot.h
file_main.o: file_main.c
--- a/common.h Sat Jun 07 05:18:06 2008 +0300
+++ b/common.h Sun Jun 08 21:03:23 2008 +0300
@@ -3,7 +3,8 @@
* error handling
*/
-void _generic_err (const char *func, int perr, int do_exit, const char *fmt, ...);
+void _generic_err (const char *func, int perr, int do_exit, const char *fmt, ...)
+ __attribute__ ((format (printf, 4, 5)));
// various kinds of ways to handle an error, 2**3 of them, *g*
#define error(...) _generic_err(NULL, 0, 0, __VA_ARGS__)
--- a/render_multi.c Sat Jun 07 05:18:06 2008 +0300
+++ b/render_multi.c Sun Jun 08 21:03:23 2008 +0300
@@ -15,7 +15,7 @@
int index;
// the remote_render_ctx
- struct remote_render_ctx *remote_render;
+ struct render_remote *remote_render;
// a pointer to ourself
struct render_multi *self;
@@ -283,8 +283,7 @@
// XXX: this will result in recursion
for (i = 0; i < ctx->self->remote_render_count; i++) {
if (ctx->self->remote_renders[i].remote_render) {
- if (render_remote_shake(ctx->self->remote_renders[i].remote_render))
- ERROR("render_remote_shake");
+ render_remote_flush(ctx->self->remote_renders[i].remote_render);
} else {
// already disconnected, use in_buf instead
assert(ctx->self->remote_renders[i].in_buf);
@@ -338,14 +337,14 @@
ctx->render_done = 1;
// shake out the rest of the data as needed, as render_multi won't keep it anymore
- render_remote_shake(ctx->remote_render);
+ render_remote_flush(ctx->remote_render);
// invalidate this ctx's remote render
ctx->remote_render = NULL;
// is the data incomplete?
if (!(ctx->col == ctx->slice_width || ctx->col == 0))
- ERROR("incomplete data for slice %d: %d/%d bytes", ctx->index, ctx->col, ctx->slice_width);
+ ERROR("incomplete data for slice %d: %zu/%zu bytes", ctx->index, ctx->col, ctx->slice_width);
// are all of them done?
int i;
--- a/render_png.c Sat Jun 07 05:18:06 2008 +0300
+++ b/render_png.c Sun Jun 08 21:03:23 2008 +0300
@@ -104,7 +104,7 @@
return 0;
error:
- _render_png_free(ctx);
+ // don't free it here, our user needs to do that
return -1;
}
@@ -139,6 +139,7 @@
return 0;
error:
+ free(ctx);
return -1;
}
--- a/render_remote.c Sat Jun 07 05:18:06 2008 +0300
+++ b/render_remote.c Sun Jun 08 21:03:23 2008 +0300
@@ -6,15 +6,20 @@
#include <assert.h>
#include <event2/event.h>
+#include <event2/event_struct.h>
#include <event2/bufferevent.h>
#include "render_internal.h" // for render_cmd_build
#include "render_remote.h"
#include "common.h"
-struct remote_render_ctx {
- struct event *ev_conn;
- struct bufferevent *data_bev;
+struct render_remote {
+ // the socket fd
+ int sock;
+
+ // the event/bufferevent
+ struct event ev_connect, ev_data;
+ struct bufferevent *bev_data;
#pragma pack(push)
#pragma pack(1)
@@ -33,7 +38,13 @@
#pragma pack(pop)
- // has cb_done/cb_fail already been called?
+ // have we sent the command yet?
+ int cmd_sent;
+
+ // have we received the EOF?
+ int have_eof;
+
+ // has cb_done/cb_fail/cancel already been called?
int alive;
void (*cb_sent)(void *arg);
@@ -44,83 +55,119 @@
void *cb_arg;
};
-static void _remote_render_free (struct remote_render_ctx *ctx) {
- // free the data_bev
- if (ctx->data_bev) {
- bufferevent_free(ctx->data_bev);
- ctx->data_bev = NULL;
- }
+// internal prototypes
+static void _render_remote_free (struct render_remote *ctx);
+static void _render_remote_do_data (struct render_remote *ctx);
+static void _render_remote_do_done (struct render_remote *ctx);
+static void _render_remote_do_fail (struct render_remote *ctx);
+
+static void _render_remote_free (struct render_remote *ctx) {
+ // free the bev_data
+ if (ctx->bev_data)
+ bufferevent_free(ctx->bev_data);
- // close the socket (ctx->ev_conn remains valid even after we're done with it...)
- close(event_get_fd(ctx->ev_conn));
-
- // and the event
- event_free(ctx->ev_conn);
+ // and the events
+ if (event_pending(&ctx->ev_connect, EV_WRITE, NULL))
+ event_del(&ctx->ev_connect);
+
+ if (event_pending(&ctx->ev_data, EV_READ, NULL))
+ event_del(&ctx->ev_data);
+
+ // close the socket (ctx->ev_connect remains valid even after we're done with it...)
+ if (ctx->sock)
+ close(ctx->sock);
// free the context structure
free(ctx);
}
-static void _remote_render_done (struct remote_render_ctx *ctx) {
+static void _render_remote_do_data (struct render_remote *ctx) {
+ // if there's data in the buffer, call cb_data
+ if (evbuffer_get_length(bufferevent_get_input(ctx->bev_data))) {
+ ctx->cb_data(EVBUFFER_INPUT(ctx->bev_data), ctx->cb_arg);
+ }
+
+ // if we got EOF on the connection and there's no data left in the buffer, call cb_done
+ if (ctx->have_eof && evbuffer_get_length(bufferevent_get_input(ctx->bev_data)) == 0) {
+ _render_remote_do_done(ctx);
+ }
+}
+
+static void _render_remote_do_done (struct render_remote *ctx) {
assert(ctx->alive);
ctx->alive = 0;
ctx->cb_done(ctx->cb_arg);
-
- _remote_render_free(ctx);
}
-static void _remote_render_fail (struct remote_render_ctx *ctx) {
+static void _render_remote_do_fail (struct render_remote *ctx) {
assert(ctx->alive);
ctx->alive = 0;
ctx->cb_fail(ctx->cb_arg);
-
- _remote_render_free(ctx);
}
static void _remote_write (struct bufferevent *bev, void *arg) {
- struct remote_render_ctx *ctx = arg;
-
- // the write buffer was drained, so the render command was sent
- ctx->cb_sent(ctx->cb_arg);
+ struct render_remote *ctx = arg;
- // we don't care about EV_WRITE anymore
- if (bufferevent_disable(ctx->data_bev, EV_WRITE))
- ERROR("bufferevent_disable");
+ if (!ctx->cmd_sent) {
+ // write the render command
+ if (bufferevent_write(ctx->bev_data, &ctx->render_cmd, sizeof(ctx->render_cmd)))
+ ERROR("bufferevent_write");
- // start receiving data
- if (bufferevent_enable(ctx->data_bev, EV_READ))
- ERROR("bufferevent_enable");
-
+ // wait for it to be written out (we get called a second time)
+ ctx->cmd_sent = 1;
+
+ } else {
+ // the write buffer was drained, so the render command was write():n
+ assert(ctx->cb_sent);
+ ctx->cb_sent(ctx->cb_arg);
+ ctx->cb_sent = NULL;
+
+ // we don't care about EV_WRITE anymore
+ if (bufferevent_disable(ctx->bev_data, EV_WRITE))
+ ERROR("bufferevent_disable");
+
+ // are we buffered or raw?
+ if (ctx->cb_data) {
+ // start receiving data into our buffer
+ if (bufferevent_enable(ctx->bev_data, EV_READ))
+ ERROR("bufferevent_enable");
+
+ } else {
+ assert(event_initialized(&ctx->ev_data));
+
+ // enable the raw read event
+ if (event_add(&ctx->ev_data, NULL))
+ ERROR("event_add");
+ }
+ }
+
return;
+
error:
- _remote_render_fail(ctx);
+ _render_remote_do_fail(ctx);
}
static void _remote_read (struct bufferevent *bev, void *arg) {
- struct remote_render_ctx *ctx = arg;
-
- // pass the bufferevent's input buffer to our callback - libevent doesn't provide any function to access this, but hopefully this works correctly
- ctx->cb_data(EVBUFFER_INPUT(bev), ctx->cb_arg);
+ struct render_remote *ctx = arg;
+
+ _render_remote_do_data(ctx);
}
static void _remote_error (struct bufferevent *bev, short what, void *arg) {
- struct remote_render_ctx *ctx = arg;
+ struct render_remote *ctx = arg;
// OH NOES; WHAT DO WE DO!?
if (what & EVBUFFER_EOF) {
// great!
+ ctx->have_eof = 1;
- // send any remaining-chunk data
- if (EVBUFFER_LENGTH(EVBUFFER_INPUT(bev)) > 0)
- ctx->cb_data(EVBUFFER_INPUT(bev), ctx->cb_arg);
-
- // signal completion
- _remote_render_done(ctx);
+ // flush any remaining data/call cb_send as needed
+ _render_remote_do_data(ctx);
return;
@@ -137,32 +184,22 @@
}
// cb_fail + free
- _remote_render_fail(ctx);
+ _render_remote_do_fail(ctx);
}
-static void _remote_connected (int fd, short event, void *arg) {
- struct remote_render_ctx *ctx = arg;
-
- // set up the read/write bufferevent
- if ((ctx->data_bev = bufferevent_new(fd, &_remote_read, &_remote_write, &_remote_error, ctx)) == NULL)
- ERROR("bufferevent_new");
-
- // write the render command
- if (bufferevent_write(ctx->data_bev, &ctx->render_cmd, sizeof(ctx->render_cmd)))
- ERROR("bufferevent_write");
+/*
+ * Do the initial IO-agnostic work to initialize the rendering process
+ */
+static struct render_remote *_render_remote_init (struct render *render, struct remote_node *remote_node) {
+ struct render_remote *ctx;
- // wait for it to be written out
- if (bufferevent_enable(ctx->data_bev, EV_WRITE))
- ERROR("bufferevent_enable");
-
- return;
+ printf("remote_node render load: %d/%d\n", remote_node->current_load, remote_node->parallel_renders);
-error:
- _remote_render_fail(ctx);
-}
-
-static void render_cmd_build (struct render *render, struct remote_render_ctx *ctx) {
- // just copy over the render params to the render_cmd
+ // alloc the remote render ctx
+ if (!(ctx = calloc(1, sizeof(struct render_remote))))
+ ERROR("calloc");
+
+ // copy the relevant stuff from the render_ctx
ctx->render_cmd.mode = render->mode;
ctx->render_cmd.img_w = htonl(render->img_w);
ctx->render_cmd.img_h = htonl(render->img_h);
@@ -170,9 +207,77 @@
ctx->render_cmd.y1 = render->y1;
ctx->render_cmd.x2 = render->x2;
ctx->render_cmd.y2 = render->y2;
+
+ // create the socket
+ if ((ctx->sock = socket(remote_node->addr.ss_family, SOCK_STREAM, 0)) < 0)
+ PERROR("socket");
+
+ // mark it as nonblocking
+ if (fcntl(ctx->sock, F_SETFL, O_NONBLOCK) == -1)
+ PERROR("fcntl");
+
+ // initiate the connect
+ int err = connect(ctx->sock, (struct sockaddr *) &remote_node->addr, sizeof(remote_node->addr));
+
+ if (err != -1 || errno != EINPROGRESS)
+ PERROR("connect");
+
+ // return the raw ctx
+ return ctx;
+
+error:
+ _render_remote_free(ctx);
+ return NULL;
}
-struct remote_render_ctx *render_remote (
+/*
+ * Raw unbuffered I/O mode
+ */
+struct render_remote *render_remote_rawio (
+ struct render *render,
+ struct remote_node *remote_node,
+ void (*cb_sent)(void *arg),
+ void (*cb_fail)(void *arg),
+ void (*cb_io_data)(evutil_socket_t, short, void*),
+ void *cb_arg
+) {
+ struct render_remote *ctx;
+
+ // short-circuit error handling
+ if (!(ctx = _render_remote_init(render, remote_node)))
+ return NULL;
+
+ // store the provided callback functions
+ ctx->cb_sent = cb_sent;
+ ctx->cb_fail = cb_fail;
+ ctx->cb_arg = cb_arg;
+
+ // set up the write bufferevent
+ if ((ctx->bev_data = bufferevent_new(ctx->sock, NULL, &_remote_write, &_remote_error, ctx)) == NULL)
+ ERROR("bufferevent_new");
+
+ // wait for it to connect
+ if (bufferevent_enable(ctx->bev_data, EV_WRITE))
+ ERROR("bufferevent_enable");
+
+ // set up the custom EV_READ callback
+ event_set(&ctx->ev_data, ctx->sock, EV_READ, cb_io_data, cb_arg);
+
+ // we are now alive
+ ctx->alive = 1;
+
+ // success
+ return ctx;
+
+error:
+ _render_remote_free(ctx);
+ return NULL;
+}
+
+/*
+ * Old buffered mode
+ */
+struct render_remote *render_remote (
struct render *render,
struct remote_node *remote_node,
void (*cb_sent)(void *arg),
@@ -181,14 +286,11 @@
void (*cb_fail)(void *arg),
void *cb_arg
) {
- struct remote_render_ctx *ctx;
- int sock;
-
- printf("remote_node render load: %d/%d\n", remote_node->current_load, remote_node->parallel_renders);
-
- // alloc the remote render ctx
- if (!(ctx = calloc(1, sizeof(struct remote_render_ctx))))
- ERROR("calloc");
+ struct render_remote *ctx;
+
+ // short-circuit error handling
+ if (!(ctx = _render_remote_init(render, remote_node)))
+ return NULL;
// store the provided callback functions
ctx->cb_sent = cb_sent;
@@ -196,31 +298,15 @@
ctx->cb_done = cb_done;
ctx->cb_fail = cb_fail;
ctx->cb_arg = cb_arg;
-
- // copy the relevant stuff from the render_ctx
- render_cmd_build(render, ctx);
-
- // create the socket
- if ((sock = socket(remote_node->addr.ss_family, SOCK_STREAM, 0)) < 0)
- PERROR("socket");
- // mark it as nonblocking
- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
- PERROR("fcntl");
-
- // initiate the connect
- int err = connect(sock, (struct sockaddr *) &remote_node->addr, sizeof(remote_node->addr));
+ // set up the read/write bufferevent
+ if ((ctx->bev_data = bufferevent_new(ctx->sock, &_remote_read, &_remote_write, &_remote_error, ctx)) == NULL)
+ ERROR("bufferevent_new");
- if (err != -1 || errno != EINPROGRESS)
- PERROR("connect");
+ // wait for it to connect
+ if (bufferevent_enable(ctx->bev_data, EV_WRITE))
+ ERROR("bufferevent_enable");
- // do the libevent dance
- if (!(ctx->ev_conn = event_new(NULL, sock, EV_WRITE, &_remote_connected, ctx)))
- ERROR("event_new");
-
- if (event_add(ctx->ev_conn, NULL))
- ERROR("event_add");
-
// we are now alive
ctx->alive = 1;
@@ -228,41 +314,47 @@
return ctx;
error:
- free(ctx);
-
- if (sock > 0)
- close(sock);
-
+ _render_remote_free(ctx);
return NULL;
}
-int render_remote_set_recv (struct remote_render_ctx *ctx, size_t recv_threshold, size_t unread_buffer) {
- if (ctx->data_bev == NULL)
- return -1;
+void render_remote_set_recv (struct render_remote *ctx, size_t recv_threshold, size_t unread_buffer) {
+ assert(ctx->bev_data);
- bufferevent_setwatermark(ctx->data_bev, EV_READ, recv_threshold, recv_threshold + unread_buffer);
-
- return 0;
+ bufferevent_setwatermark(ctx->bev_data, EV_READ, recv_threshold, recv_threshold + unread_buffer);
}
-int render_remote_shake (struct remote_render_ctx *ctx) {
- if (ctx->data_bev == NULL)
- return -1;
+void render_remote_flush (struct render_remote *ctx) {
+ assert(ctx->bev_data);
- ctx->cb_data(EVBUFFER_INPUT(ctx->data_bev), ctx->cb_arg);
-
- return 0;
+ // call cb_data/cb_done as appropriate
+ _render_remote_do_data(ctx);
}
-void render_remote_cancel (struct remote_render_ctx *ctx) {
+int render_remote_reschedule (struct render_remote *ctx) {
+ assert(event_initialized(&ctx->ev_data));
+
+ // just reschedule it
+ if (event_add(&ctx->ev_data, NULL))
+ ERROR("event_add");
+
+ // ok
+ return 0;
+
+error:
+ return -1;
+}
+
+void render_remote_cancel (struct render_remote *ctx) {
// we must be alive for this..
assert(ctx->alive);
- // if it's still just connecting, cancel that
- if (event_pending(ctx->ev_conn, EV_WRITE, NULL))
- event_del(ctx->ev_conn);
-
- // this takes care of the rest
- _remote_render_free (ctx);
+ _render_remote_free(ctx);
}
+void render_remote_free (struct render_remote *ctx) {
+ // XXX: add some sanity checks
+
+ _render_remote_free(ctx);
+}
+
--- a/render_remote.h Sat Jun 07 05:18:06 2008 +0300
+++ b/render_remote.h Sun Jun 08 21:03:23 2008 +0300
@@ -8,27 +8,45 @@
#include "remote_node.h"
/*
- * Execute a render_t operation on a remote render_node
+ * Execute a render operation on a remote render_node
*/
#define RENDER_PORT_NAME "6159"
-struct remote_render_ctx;
+struct render_remote;
/*
- * Execute the given render operation on the render_node at the given remote address.
- *
- * The various callback functions must all be provided.
+ * Execute the given render operation on the render_node at the given remote
+ * address, and buffer the data stream.
*
- * cb_sent will be invoked after the request has succesfully been written, and before cb_data is called.
- * cb_data is called whenever new data has been received. See also, render_remote_set_chunk_size
- * cb_done is called after our last call to cb_data (note: see render_remote_shake)
- * cb_fail is called when an error is encountered. This can (and will) happen at any time!
+ * The various callback functions must all be provided!
*
- * Returns NULL on error, or a handle that can be used for cancel/etc on success
+ * cb_sent
+ * Will be invoked once we have a pretty good guess that the render will
+ * complete succesfully.
+ *
+ * cb_data
+ * Will be invoked after cb_sent has been called whenever any new data has
+ * been received into our buffer, once we've buffered all the data, or after
+ * render_remote_flush.
+ *
+ * cb_done
+ * The request was terminated succesfully and all data has been read out of
+ * our buffer by cb_data
+ *
+ * cb_fail
+ * The request was terminated abnormally. This may happen at any time, except
+ * after cb_done has been called.
+ *
+ * The returned struct render_remote can be used as a handle for the control
+ * functions, and it is the caller's responsibility to free it using
+ * render_remote_free after cb_done/cb_fail has been called, or alternatively,
+ * cancel it using render_remote_cancel.
+ *
+ * Returns NULL on error, or a handle on success
*/
-struct remote_render_ctx *render_remote (
+struct render_remote *render_remote (
struct render *render, // what to render
struct remote_node *remote_node, // what render node to use
void (*cb_sent)(void *arg),
@@ -39,10 +57,29 @@
);
/*
- * Cancel the given request. No more callbacks will be called, buffered data is
- * discarded and the remote render process will cancel ASAP.
+ * Execute the given render operation on the render_node at the given remote
+ * address, and let the user handle the read I/O events.
+ *
+ * The various callback functions must all be provided!
+ *
+ * cb_sent
+ * Will be called once the request has been sent.
+ *
+ * cb_fail
+ * Will be called if sending the request fails.
+ *
+ * cb_io_data
+ * Will be called once when there is data on the socket to receive. Must be
+ * re-enabled using render_remote_again each time.
*/
-void render_remote_cancel (struct remote_render_ctx *ctx);
+struct render_remote *render_remote_rawio (
+ struct render *render,
+ struct remote_node *remote_node,
+ void (*cb_sent)(void *arg),
+ void (*cb_fail)(void *arg),
+ void (*cb_io_data)(evutil_socket_t, short, void*),
+ void *cb_arg
+);
/*
* Controls the behaviour of when cb_data is called, and how remote data is read in.
@@ -59,20 +96,40 @@
* called any more.
*
* This means that there is a potential for deadlock if the buffer is full. You
- * MUST call render_remote_shake once you are ready to start consuming the
+ * MUST call render_remote_again once you are ready to start consuming the
* buffer again.
*
- * Only call this once cb_sent has fired
+ * Only valid for normal buffered renders.
*/
-int render_remote_set_recv (struct remote_render_ctx *ctx, size_t recv_threshold, size_t unread_buffer);
+void render_remote_set_recv (struct render_remote *ctx, size_t recv_threshold, size_t unread_buffer);
/*
- * Call cb_data with the current set of buffered input data immediately,
- * regardless of whether or not the buffer contains any data, or any new
- * data has been received.
+ * For buffered I/O, call cb_data with the current set of buffered input data
+ * immediately, regardless of whether or not the buffer contains any data, or
+ * any new data has been received. Only call this once cb_sent has been invoked.
+ */
+void render_remote_flush (struct render_remote *ctx);
+
+/*
+ * For non-buffered I/O, reschedule the cb_io_data event to be called when more
+ * data is received.
+ */
+int render_remote_reschedule (struct render_remote *ctx);
+
+/*
+ * Cancel the given request. No more callbacks will be called, the ctx is freed
+ * and the remote render process will cancel ASAP.
*
- * Only call this after cb_sent and before cb_done/cb_fail.
+ * For buffered I/O, the any buffered data is discarded.
+ *
+ * Note that you do not need to call render_remote_free after this.
*/
-int render_remote_shake (struct remote_render_ctx *ctx);
+void render_remote_cancel (struct render_remote *ctx);
+
+/*
+ * Free the render_remote ctx and its assoicated resources. Only valid after a
+ * cb_done/cb_fail, otherwise use render_remote_cancel.
+ */
+void render_remote_free (struct render_remote *ctx);
#endif /* RENDER_REMOTE_H */
--- a/web_main.c Sat Jun 07 05:18:06 2008 +0300
+++ b/web_main.c Sun Jun 08 21:03:23 2008 +0300
@@ -8,6 +8,7 @@
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
+#include <assert.h>
#include <event2/event.h>
#include <event2/event_compat.h>
@@ -43,7 +44,7 @@
int headers_sent;
- struct render_multi *render_info;
+ struct render_remote *render_info;
size_t bytes_sent;
@@ -54,16 +55,15 @@
static void _render_http_written (struct evhttp_request *request, void *arg);
static void _render_cleanup (struct render_request *ctx) {
- // clean up
+ if (ctx->render_info)
+ render_remote_free(ctx->render_info);
+
free(ctx);
}
static void _render_sent (void *arg) {
struct render_request *ctx = arg;
- // set chunk size
- render_multi_set_recv(ctx->render_info, MIN_CHUNK_SIZE, OVERFLOW_BUFFER);
-
// send headers
evhttp_add_header(evhttp_request_get_output_headers(ctx->http_request), "Content-Type", "image/png");
evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
@@ -81,12 +81,7 @@
size_t buf_size = EVBUFFER_LENGTH(buf);
- // ignore empty buffers, a result of render_remote_shake()
- if (buf_size == 0) {
- printf("render [%p]: remote buffer is empty\n", ctx);
-
- return;
- }
+ assert(buf_size > 0); // shouldn't happen anymore with the new render_remote
// check if we are paused
if (ctx->paused) {
@@ -111,14 +106,6 @@
static void _render_done (void *arg) {
struct render_request *ctx = arg;
- // if we are paused, just shove the data into the http buffers, they might become larger than they should be, but it's easier to just move the data there and let render_remote complete
- if (ctx->paused) {
- printf("render [%p]: done: flushing the rest of our data\n", ctx);
- ctx->paused = 0;
-
- render_multi_shake(ctx->render_info);
- }
-
// send end
evhttp_send_reply_end(ctx->http_request);
@@ -134,6 +121,7 @@
if (ctx->headers_sent) {
// just terminate the PNG stream where it is
evhttp_send_reply_end(ctx->http_request);
+
} else {
evhttp_send_error(ctx->http_request, 500, "Internal Server Error");
}
@@ -149,7 +137,8 @@
printf("render [%p]: lost http connection\n", ctx);
// cancel
- render_multi_cancel(ctx->render_info);
+ render_remote_cancel(ctx->render_info);
+ ctx->render_info = NULL;
_render_cleanup(ctx);
}
@@ -162,20 +151,20 @@
// unpause ourself
ctx->paused = 0;
- // shake out the buffers
- render_multi_shake(ctx->render_info);
+ // any data waiting in the buffer?
+ render_remote_flush(ctx->render_info);
}
static void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
// render request context
- struct render_request *req_ctx = calloc(1, sizeof(struct render_request));
+ struct render_request *ctx = calloc(1, sizeof(struct render_request));
- if (!req_ctx)
+ if (!ctx)
ERROR("calloc");
- req_ctx->http_request = request;
- req_ctx->headers_sent = 0;
- req_ctx->bytes_sent = 0;
+ ctx->http_request = request;
+ ctx->headers_sent = 0;
+ ctx->bytes_sent = 0;
// render context
struct render render;
@@ -189,36 +178,36 @@
if (render_region_full(&render))
ERROR("render_region_full");
-/*
// pick a render_node
struct remote_node *node_info;
if ((node_info = remote_pool_get(&remote_pool)) == NULL)
ERROR("remote_pool_get");
-*/
// initiate the remote render operation
- if ((req_ctx->render_info = render_multi(&render, &remote_pool,
+ if ((ctx->render_info = render_remote(&render, node_info,
&_render_sent,
&_render_data,
&_render_done,
&_render_fail,
- req_ctx
+ ctx
)) == NULL)
ERROR("render_multi");
+
+ // set chunk size
+ render_remote_set_recv(ctx->render_info, MIN_CHUNK_SIZE, OVERFLOW_BUFFER);
// set close cb
- evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx);
+ evhttp_set_reply_abortcb(request, &_render_http_lost, ctx);
- printf("render [%p]: started\n", req_ctx);
+ printf("render [%p]: started\n", ctx);
return;
error:
evhttp_send_error(request, 500, "Internal Server Error");
- free(req_ctx);
-
+ _render_cleanup(ctx);
}
/*