4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "arraylist.h"
28 #include "brender.inc"
30 #include "condition.inc"
33 #include "mwindow.inc"
34 #include "packagedispatcher.inc"
35 #include "pluginserver.inc"
36 #include "preferences.inc"
38 #include "renderfarm.inc"
39 #include "renderfarmclient.inc"
40 //#include "renderfarmfsserver.inc"
47 // The renderfarm starts a RenderFarmServerThread for each client
48 // listed in the preferences.
49 // The RenderFarmServerThread starts a RenderFarmWatchdog thread.
50 // write_socket and read_socket start the watchdog thread. If they don't
51 // return in a certain time, the watchdog thread assumes the client has crashed
52 // and kills RenderFarmServerThread.
53 // RenderFarmServerThread handles requests from the client once the
54 // connection is open. All the RenderFarmServerThread's are joined by the
55 // RenderFarmServer when the jobs are finished.
57 // On the client side, the process started by the user is a RenderFarmClient.
58 // It waits for connections from the server and starts a RenderFarmClientThread
59 // for each connection. RenderFarmClientThread is a thread but it in turn
60 // starts a fork for the actual rendering. A fork instead of a thread is
61 // used to avoid reentrancy problems with the
62 // codecs, but we still need a thread to join the process.
64 // The fork requests jobs from the server until the job table is empty
65 // or the server reports an error. This fork must poll the server
66 // after every frame for the error status. Also the fork creates a
67 // RenderFarmWatchdog thread to kill itself if a write_socket or read_socket
70 // RenderFarmClientThread detaches when finished.
71 // It doesn't account for the server command loop, which waits for read_socket
72 // indefinitely. This needs to be pinged periodically to keep the read_socket
75 // Once, it tried to use a virtual file system to allow rendering clients without
76 // mounting the filesystem of the server. This proved impractical because of
77 // the many odd schemes used by file libraries. Abstracting "open" didn't
78 // work. Read ahead and caching were required to get decent performance.
80 // Whether it cleans up when timed out is unknown.
83 // 1 byte -> request code
84 // 4 bytes -> size of packet exclusive
85 // size of packet -> data
89 // General reply format
90 // 4 bytes -> size of packet exclusive
91 // size of packet -> data
93 #define STORE_INT32(value) \
94 datagram[i++] = (((uint32_t)(value)) >> 24) & 0xff; \
95 datagram[i++] = (((uint32_t)(value)) >> 16) & 0xff; \
96 datagram[i++] = (((uint32_t)(value)) >> 8) & 0xff; \
97 datagram[i++] = ((uint32_t)(value)) & 0xff;
99 #define STORE_INT64(value) \
100 datagram[i++] = (((uint64_t)(value)) >> 56) & 0xff; \
101 datagram[i++] = (((uint64_t)(value)) >> 48) & 0xff; \
102 datagram[i++] = (((uint64_t)(value)) >> 40) & 0xff; \
103 datagram[i++] = (((uint64_t)(value)) >> 32) & 0xff; \
104 datagram[i++] = (((uint64_t)(value)) >> 24) & 0xff; \
105 datagram[i++] = (((uint64_t)(value)) >> 16) & 0xff; \
106 datagram[i++] = (((uint64_t)(value)) >> 8) & 0xff; \
107 datagram[i++] = ((uint64_t)(value)) & 0xff;
109 #define READ_INT32(data) \
110 ((((uint32_t)(data)[0]) << 24) | \
111 (((uint32_t)(data)[1]) << 16) | \
112 (((uint32_t)(data)[2]) << 8) | \
113 ((uint32_t)(data)[3]))
115 #define READ_INT64(data) \
116 ((((uint64_t)(data)[0]) << 56) | \
117 (((uint64_t)(data)[1]) << 48) | \
118 (((uint64_t)(data)[2]) << 40) | \
119 (((uint64_t)(data)[3]) << 32) | \
120 (((uint64_t)(data)[4]) << 24) | \
121 (((uint64_t)(data)[5]) << 16) | \
122 (((uint64_t)(data)[6]) << 8) | \
123 ((uint64_t)(data)[7]))
126 // Request codes to be used in both client and server.
130 RENDERFARM_PREFERENCES, // 0 Get preferences on startup
131 RENDERFARM_ASSET, // Get output format on startup
132 RENDERFARM_EDL, // Get EDL on startup
133 RENDERFARM_PACKAGE, // Get one package after another to render
134 RENDERFARM_PROGRESS, // Update completion total
135 RENDERFARM_SET_RESULT, // Update error status
136 RENDERFARM_GET_RESULT, // Retrieve error status
137 RENDERFARM_DONE, // Quit
138 RENDERFARM_SET_VMAP, // 8 Update video map in background rendering
139 RENDERFARM_COMMAND, // Get the client to run
140 RENDERFARM_TUNER, // Run a tuner server
141 RENDERFARM_PACKAGES, // Run packages
142 RENDERFARM_KEEPALIVE, // Keep alive
162 class RenderFarmServer
168 PackageDispatcher *packages,
169 Preferences *preferences,
172 int64_t *total_return,
173 Mutex *total_return_lock,
174 Asset *default_asset,
177 virtual ~RenderFarmServer();
180 // Open connections to clients.
182 // The render farm must wait for all the clients to finish.
184 // number of running clients
185 int active_clients();
187 // Likewise the render farm must check the internal render loop before
188 // dispatching the next job and whenever a client queries for errors.
191 ArrayList<RenderFarmServerThread*> clients;
194 PackageDispatcher *packages;
195 Preferences *preferences;
196 // Use master node's framerate
198 // These values are shared between the local renderer and the
199 // renderfarm server threads.
201 // Any nonzero value is an error and stops rendering.
203 // The total number of frames completed
204 int64_t *total_return;
205 Mutex *total_return_lock;
206 Asset *default_asset;
213 class RenderFarmServerThread : public Thread
216 RenderFarmServerThread(RenderFarmServer *server,
218 ~RenderFarmServerThread();
221 // Used by both client and server
222 int write_int64(int64_t value);
223 int64_t read_int64(int *error);
224 // Inserts header and writes string to socket
225 void write_string(char *string);
226 static int open_client(const char *hostname, int port);
230 // Used by server only
231 int read_socket(char *data, int len);
232 int write_socket(char *data, int len);
234 void send_preferences();
237 void send_package(unsigned char *buffer);
238 void set_progress(unsigned char *buffer);
239 int set_video_map(unsigned char *buffer);
240 void set_result(unsigned char *buffer);
242 void reallocate_buffer(int size);
247 RenderFarmServer *server;
248 RenderFarmWatchdog *watchdog;
251 // Rate of last job or 0
252 double frames_per_second;
253 // Pointer to default asset
254 Asset *default_asset;
255 // These objects can be left dangling of the watchdog kills the thread.
256 // They are deleted in the destructor.
257 unsigned char *buffer;
258 int64_t buffer_allocated;
262 class RenderFarmWatchdog : public Thread
265 RenderFarmWatchdog(int timeout_secs,
266 RenderFarmServerThread *server, RenderFarmClientThread *client);
267 ~RenderFarmWatchdog();
269 // Called at the beginning of a socket read
270 void begin_request();
271 // Called when a socket read succeeds
275 RenderFarmServerThread *server;
276 RenderFarmClientThread *client;
277 Condition *next_request;
278 Condition *request_complete;