--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote_node.c Fri Jun 06 03:24:55 2008 +0300
@@ -0,0 +1,51 @@
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <assert.h>
+
+#include "common.h"
+#include "render_remote.h"
+#include "remote_node.h"
+
+int remote_node_init (struct remote_node *node_info, const char *hostname, const char *portname) {
+ // zero out the struct
+ memset(node_info, 0, sizeof(*node_info));
+
+ // XXX: currently, this is hardcoded to one, but should be automagically discovered
+ node_info->parallel_renders = 1;
+
+ // lookup the host:port
+ portname = portname ? portname : RENDER_PORT_NAME;
+
+ // XXX: stat it and look for a PF_UNIX socket!
+
+ // PF_INET
+
+ struct addrinfo hints, *results, *result;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG; // attempt to get a working address as the first result
+
+ int err = getaddrinfo(hostname, portname, &hints, &results);
+
+ if (err != 0) {
+ error("getaddrinfo: [%s].%s: %s", hostname, portname, gai_strerror(err));
+
+ return -1;
+ }
+
+ assert(results != NULL); // we expect at least one result
+
+ // XXX: only use the first result, discard the rest.
+ result = results;
+ memcpy(&node_info->addr, result->ai_addr, result->ai_addrlen);
+
+ freeaddrinfo(results);
+
+ // success!
+ node_info->valid = 1;
+ return 0;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote_node.h Fri Jun 06 03:24:55 2008 +0300
@@ -0,0 +1,42 @@
+#ifndef REMOTE_NODE_H
+#define REMOTE_NODE_H
+
+#include <sys/socket.h>
+
+/*
+ * Information about a single remote render node.
+ */
+
+struct remote_node {
+ int valid;
+
+ /*
+ * Static information
+ */
+
+ // the remote address, note how this can both AF_INET and AF_LOCAL
+ struct sockaddr_storage addr;
+
+ // how many render requests this node can process concurrently
+ int parallel_renders;
+
+ /*
+ * Dynamic information
+ */
+
+ // how many render requests this node is currently processing
+ int current_load;
+};
+
+/*
+ * Initialize the given remote_node struct to work with the render node at the given host/port.
+ *
+ * Portname may also be NULL, in which case the default port is used.
+ *
+ * Note that this is a blocking function, and should only be called at startup.
+ *
+ * returns nonzero on error, zero on success.
+ */
+int remote_node_init (struct remote_node *node_info, const char *hostname, const char *portname);
+
+#endif /* REMOTE_NODE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote_pool.c Fri Jun 06 03:24:55 2008 +0300
@@ -0,0 +1,119 @@
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "remote_pool.h"
+#include "common.h"
+
+void remote_pool_init (struct remote_pool *pool_info) {
+ memset(pool_info, 0, sizeof(*pool_info));
+}
+
+int remote_pool_add (struct remote_pool *pool_info, const char *hostname, const char *portname) {
+ int i;
+ struct remote_node *node_info = NULL;
+
+ // find a free remote_node entry and store its pointer in node_info
+ for (i = 0; i < REMOTE_POOL_MAX; i++) {
+ if (!pool_info->nodes[i].valid) {
+ node_info = &pool_info->nodes[i];
+ break;
+ }
+ }
+
+ if (!node_info) {
+ error("remote_pool_add: pool full, consider increasing REMOTE_POOL_MAX");
+ return -1;
+ }
+
+ return remote_node_init(node_info, hostname, portname);
+}
+
+int remote_pool_load (struct remote_pool *pool_info, const char *filename) {
+ // open the file
+ FILE *fh = fopen(filename, "r");
+
+ if (!fh) {
+ perr("remote_pool_load: fopen(%s)", filename);
+ return -1;
+ }
+
+ // read it in line-by-line
+ char line_buf[POOL_FILE_LINE_LENGTH], *hostname, *portname, *c;
+
+ // non-ferror error indicator
+ int error_flag = 0;
+
+ while (1) {
+ // read in a line
+ if (!fgets(line_buf, POOL_FILE_LINE_LENGTH, fh)) {
+ perr("remote_pool_load: fgets");
+ break;
+ }
+
+ // strip comments
+ c = strchr(line_buf, '#');
+
+ if (c)
+ *c = '\0';
+
+ // skip empty lines
+ for (c = line_buf; *c != '\0'; c++)
+ if (!isspace(*c))
+ break;
+
+ if (*c == '\0')
+ continue;
+
+ // parse
+ if (!parse_hostport(line_buf, &hostname, &portname)) {
+ error_flag = 1;
+ break;
+ }
+
+ // add it to the pool
+ if (remote_pool_add(pool_info, hostname, portname)) {
+ error_flag = 1;
+ break;
+ }
+ }
+
+ // pick up ferrors if otherwise fine
+ error_flag = error_flag || ferror(fh);
+
+ // close the fd
+ fclose(fh);
+
+ // error return?
+ if (error_flag)
+ return -1;
+
+ return 0;
+}
+
+struct remote_node *remote_pool_get (struct remote_pool *pool_info) {
+ int i;
+ struct remote_node *node_info = NULL;
+
+ // find a the appropriate remote_node entry and store its pointer in node_info
+ for (i = 0; i < REMOTE_POOL_MAX; i++) {
+ if (pool_info->nodes[i].valid && (node_info == NULL || pool_info->nodes[i].current_load < node_info->current_load)) {
+ node_info = &pool_info->nodes[i];
+ }
+ }
+
+ // either NULL or the right remote_info
+ return node_info;
+}
+
+int remote_pool_size (struct remote_pool *pool_info) {
+ int i, size = 0;
+
+ for (i = 0; i < REMOTE_POOL_MAX; i++) {
+ if (pool_info->nodes[i].valid) {
+ size++;
+ }
+ }
+
+ return size;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote_pool.h Fri Jun 06 03:24:55 2008 +0300
@@ -0,0 +1,51 @@
+#ifndef REMOTE_POOL_H
+#define REMOTE_POOL_H
+
+#include "remote_node.h"
+
+// maximum number of nodes in a remote pool
+#define REMOTE_POOL_MAX 8
+
+// how many bytes long each line in a pool file may be
+#define POOL_FILE_LINE_LENGTH 512
+
+struct remote_pool {
+ // the remote_nodes are part of this struct
+ struct remote_node nodes[REMOTE_POOL_MAX];
+};
+
+/*
+ * Initialize the given remote_pool
+ */
+void remote_pool_init (struct remote_pool *pool_info);
+
+/*
+ * Add a remote_node to the pool, see remote_node_init
+ */
+int remote_pool_add (struct remote_pool *pool_info, const char *hostname, const char *portname);
+
+/*
+ * Adds remote_nodes to the pool based on the contents of the given file
+ *
+ * The format for the file is a set of "<hostname>:<portname>" lines, see
+ * parse_hostport in common.h. Blank lines are skipped, and any comments
+ * prefixed with a '#' char is ignored. Whitespace inside lines is also
+ * ignored.
+ *
+ * Returns however many nodes were added (possibly zero), or -1 on error
+ */
+int remote_pool_load (struct remote_pool *pool_info, const char *filename);
+
+/*
+ * Choose a remote_node from the pool
+ *
+ * Attempts to pick the one that's least busy
+ */
+struct remote_node *remote_pool_get (struct remote_pool *pool_info);
+
+/*
+ * Get the number of remote render nodes in this pool
+ */
+int remote_pool_size (struct remote_pool *pool_info);
+
+#endif /* REMOTE_POOL_H */