Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / cinelerra / renderfarm.h
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifndef RENDERFARM_H
23 #define RENDERFARM_H
24
25
26 #include "arraylist.h"
27 #include "asset.inc"
28 #include "brender.inc"
29 #include "bchash.inc"
30 #include "condition.inc"
31 #include "edl.inc"
32 #include "mutex.inc"
33 #include "mwindow.inc"
34 #include "packagedispatcher.inc"
35 #include "pluginserver.inc"
36 #include "preferences.inc"
37 #include "render.inc"
38 #include "renderfarm.inc"
39 #include "renderfarmclient.inc"
40 //#include "renderfarmfsserver.inc"
41 #include "thread.h"
42
43 #include <stdint.h>
44
45
46 // Renderfarm theory:
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.
56 //
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.
63 //
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
68 // doesn't return.
69 //
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
73 // alive.
74 //
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.
79 //
80 // Whether it cleans up when timed out is unknown.
81
82 // Request format
83 // 1 byte -> request code
84 // 4 bytes -> size of packet exclusive
85 // size of packet -> data
86
87
88
89 // General reply format
90 // 4 bytes -> size of packet exclusive
91 // size of packet -> data
92
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;
98
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;
108
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]))
114
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]))
124
125
126 // Request codes to be used in both client and server.
127 enum
128 {
129         RENDERFARM_NONE,
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
143
144 // VFS commands
145         RENDERFARM_FOPEN,
146         RENDERFARM_FCLOSE,
147         RENDERFARM_REMOVE,
148         RENDERFARM_RENAME,
149         RENDERFARM_FGETC,
150         RENDERFARM_FPUTC,
151         RENDERFARM_FREAD,
152         RENDERFARM_FWRITE,
153         RENDERFARM_FSEEK,
154         RENDERFARM_FTELL,
155         RENDERFARM_STAT,
156         RENDERFARM_STAT64,
157         RENDERFARM_FGETS,
158         RENDERFARM_FILENO
159 };
160
161
162 class RenderFarmServer
163 {
164 public:
165         RenderFarmServer(
166 // Can be 0
167                 MWindow *mwindow,
168                 PackageDispatcher *packages,
169                 Preferences *preferences,
170                 int use_local_rate,
171                 int *result_return,
172                 int64_t *total_return,
173                 Mutex *total_return_lock,
174                 Asset *default_asset,
175                 EDL *edl,
176                 BRender *brender);
177         virtual ~RenderFarmServer();
178
179
180 // Open connections to clients.
181         int start_clients();
182 // The render farm must wait for all the clients to finish.
183         int wait_clients();
184 // number of running clients
185         int active_clients();
186
187 // Likewise the render farm must check the internal render loop before
188 // dispatching the next job and whenever a client queries for errors.
189
190
191         ArrayList<RenderFarmServerThread*> clients;
192 // Can be 0
193         MWindow *mwindow;
194         PackageDispatcher *packages;
195         Preferences *preferences;
196 // Use master node's framerate
197         int use_local_rate;
198 // These values are shared between the local renderer and the
199 // renderfarm server threads.
200 // The error code.
201 // Any nonzero value is an error and stops rendering.
202         int *result_return;
203 // The total number of frames completed
204         int64_t *total_return;
205         Mutex *total_return_lock;
206         Asset *default_asset;
207         EDL *edl;
208         Mutex *client_lock;
209         BRender *brender;
210 };
211
212
213 class RenderFarmServerThread : public Thread
214 {
215 public:
216         RenderFarmServerThread(RenderFarmServer *server,
217                 int number);
218         ~RenderFarmServerThread();
219
220
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);
227
228
229
230 // Used by server only
231         int read_socket(char *data, int len);
232         int write_socket(char *data, int len);
233         int start_loop();
234         void send_preferences();
235         void send_asset();
236         void send_edl();
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);
241         void get_result();
242         void reallocate_buffer(int size);
243
244
245         void run();
246
247         RenderFarmServer *server;
248         RenderFarmWatchdog *watchdog;
249         int socket_fd;
250         int number;
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;
259         char *datagram;
260 };
261
262 class RenderFarmWatchdog : public Thread
263 {
264 public:
265         RenderFarmWatchdog(int timeout_secs,
266                 RenderFarmServerThread *server, RenderFarmClientThread *client);
267         ~RenderFarmWatchdog();
268
269 // Called at the beginning of a socket read
270         void begin_request();
271 // Called when a socket read succeeds
272         void end_request();
273         void run();
274
275         RenderFarmServerThread *server;
276         RenderFarmClientThread *client;
277         Condition *next_request;
278         Condition *request_complete;
279         int done;
280         int pid;
281         int timeout_usecs;
282 };
283
284
285
286
287
288 #endif