9 #include "condition.inc"
12 #include "mwindow.inc"
13 #include "packagedispatcher.inc"
14 #include "pluginserver.inc"
15 #include "preferences.inc"
17 #include "renderfarm.inc"
18 #include "renderfarmclient.inc"
19 //#include "renderfarmfsserver.inc"
26 // The renderfarm starts a RenderFarmServerThread for each client
27 // listed in the preferences.
28 // The RenderFarmServerThread starts a RenderFarmWatchdog thread.
29 // write_socket and read_socket start the watchdog thread. If they don't
30 // return in a certain time, the watchdog thread assumes the client has crashed
31 // and kills RenderFarmServerThread.
32 // RenderFarmServerThread handles requests from the client once the
33 // connection is open. All the RenderFarmServerThread's are joined by the
34 // RenderFarmServer when the jobs are finished.
36 // On the client side, the process started by the user is a RenderFarmClient.
37 // It waits for connections from the server and starts a RenderFarmClientThread
38 // for each connection. RenderFarmClientThread is a thread but it in turn
39 // starts a fork for the actual rendering. A fork instead of a thread is
40 // used to avoid reentrancy problems with the
41 // codecs, but we still need a thread to join the process.
43 // The fork requests jobs from the server until the job table is empty
44 // or the server reports an error. This fork must poll the server
45 // after every frame for the error status. Also the fork creates a
46 // RenderFarmWatchdog thread to kill itself if a write_socket or read_socket
49 // RenderFarmClientThread detaches when finished.
50 // It doesn't account for the server command loop, which waits for read_socket
51 // indefinitely. This needs to be pinged periodically to keep the read_socket
54 // Once, it tried to use a virtual file system to allow rendering clients without
55 // mounting the filesystem of the server. This proved impractical because of
56 // the many odd schemes used by file libraries. Abstracting "open" didn't
57 // work. Read ahead and caching were required to get decent performance.
59 // Whether it cleans up when timed out is unknown.
62 // 1 byte -> request code
63 // 4 bytes -> size of packet exclusive
64 // size of packet -> data
68 // General reply format
69 // 4 bytes -> size of packet exclusive
70 // size of packet -> data
72 #define STORE_INT32(value) \
73 datagram[i++] = (((uint32_t)(value)) >> 24) & 0xff; \
74 datagram[i++] = (((uint32_t)(value)) >> 16) & 0xff; \
75 datagram[i++] = (((uint32_t)(value)) >> 8) & 0xff; \
76 datagram[i++] = ((uint32_t)(value)) & 0xff;
78 #define STORE_INT64(value) \
79 datagram[i++] = (((uint64_t)(value)) >> 56) & 0xff; \
80 datagram[i++] = (((uint64_t)(value)) >> 48) & 0xff; \
81 datagram[i++] = (((uint64_t)(value)) >> 40) & 0xff; \
82 datagram[i++] = (((uint64_t)(value)) >> 32) & 0xff; \
83 datagram[i++] = (((uint64_t)(value)) >> 24) & 0xff; \
84 datagram[i++] = (((uint64_t)(value)) >> 16) & 0xff; \
85 datagram[i++] = (((uint64_t)(value)) >> 8) & 0xff; \
86 datagram[i++] = ((uint64_t)(value)) & 0xff;
88 #define READ_INT32(data) \
89 ((((uint32_t)(data)[0]) << 24) | \
90 (((uint32_t)(data)[1]) << 16) | \
91 (((uint32_t)(data)[2]) << 8) | \
92 ((uint32_t)(data)[3]))
94 #define READ_INT64(data) \
95 ((((uint64_t)(data)[0]) << 56) | \
96 (((uint64_t)(data)[1]) << 48) | \
97 (((uint64_t)(data)[2]) << 40) | \
98 (((uint64_t)(data)[3]) << 32) | \
99 (((uint64_t)(data)[4]) << 24) | \
100 (((uint64_t)(data)[5]) << 16) | \
101 (((uint64_t)(data)[6]) << 8) | \
102 ((uint64_t)(data)[7]))
105 // Request codes to be used in both client and server.
109 RENDERFARM_PREFERENCES
, // 0 Get preferences on startup
110 RENDERFARM_ASSET
, // Get output format on startup
111 RENDERFARM_EDL
, // Get EDL on startup
112 RENDERFARM_PACKAGE
, // Get one package after another to render
113 RENDERFARM_PROGRESS
, // Update completion total
114 RENDERFARM_SET_RESULT
, // Update error status
115 RENDERFARM_GET_RESULT
, // Retrieve error status
116 RENDERFARM_DONE
, // Quit
117 RENDERFARM_SET_VMAP
, // 8 Update video map in background rendering
118 RENDERFARM_COMMAND
, // Get the client to run
119 RENDERFARM_TUNER
, // Run a tuner server
120 RENDERFARM_PACKAGES
, // Run packages
121 RENDERFARM_KEEPALIVE
, // Keep alive
141 class RenderFarmServer
144 // MWindow is required to get the plugindb to save the EDL.
145 RenderFarmServer(ArrayList
<PluginServer
*> *plugindb
,
146 PackageDispatcher
*packages
,
147 Preferences
*preferences
,
150 int64_t *total_return
,
151 Mutex
*total_return_lock
,
152 Asset
*default_asset
,
155 virtual ~RenderFarmServer();
158 // Open connections to clients.
160 // The render farm must wait for all the clients to finish.
163 // Likewise the render farm must check the internal render loop before
164 // dispatching the next job and whenever a client queries for errors.
167 ArrayList
<RenderFarmServerThread
*> clients
;
168 ArrayList
<PluginServer
*> *plugindb
;
170 PackageDispatcher
*packages
;
171 Preferences
*preferences
;
172 // Use master node's framerate
174 // These values are shared between the local renderer and the
175 // renderfarm server threads.
177 // Any nonzero value is an error and stops rendering.
179 // The total number of frames completed
180 int64_t *total_return
;
181 Mutex
*total_return_lock
;
182 Asset
*default_asset
;
189 class RenderFarmServerThread
: public Thread
192 RenderFarmServerThread(ArrayList
<PluginServer
*> *plugindb
,
193 RenderFarmServer
*server
,
195 ~RenderFarmServerThread();
198 // Used by both client and server
199 int write_int64(int64_t value
);
200 int64_t read_int64(int *error
);
201 // Inserts header and writes string to socket
202 int write_string(char *string
);
203 static int open_client(char *hostname
, int port
);
207 // Used by server only
208 int read_socket(char *data
, int len
);
209 int write_socket(char *data
, int len
);
211 void send_preferences();
214 void send_package(unsigned char *buffer
);
215 void set_progress(unsigned char *buffer
);
216 int set_video_map(unsigned char *buffer
);
217 void set_result(unsigned char *buffer
);
219 void reallocate_buffer(int size
);
225 ArrayList
<PluginServer
*> *plugindb
;
226 RenderFarmServer
*server
;
227 RenderFarmWatchdog
*watchdog
;
230 // Rate of last job or 0
231 double frames_per_second
;
232 // Pointer to default asset
233 Asset
*default_asset
;
234 // These objects can be left dangling of the watchdog kills the thread.
235 // They are deleted in the destructor.
236 unsigned char *buffer
;
237 int64_t buffer_allocated
;
241 class RenderFarmWatchdog
: public Thread
244 // use_pid - causes it to kill the pid instead of cancel the thread
246 RenderFarmWatchdog(RenderFarmServerThread
*server
,
247 RenderFarmClientThread
*client
);
248 ~RenderFarmWatchdog();
250 // Called at the beginning of a socket read
251 void begin_request();
252 // Called when a socket read succeeds
256 RenderFarmServerThread
*server
;
257 RenderFarmClientThread
*client
;
258 Condition
*next_request
;
259 Condition
*request_complete
;