r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / renderfarmclient.C
blob043fca2c88f9874d9908b5718c21a248f80e8da5
1 #include "asset.h"
2 #include "assets.h"
3 #include "clip.h"
4 #include "defaults.h"
5 #include "edl.h"
6 #include "filesystem.h"
7 #include "filexml.h"
8 #include "mwindow.h"
9 #include "pluginserver.h"
10 #include "preferences.h"
11 #include "renderfarm.h"
12 #include "renderfarmclient.h"
13 #include "renderfarmfsclient.h"
14 #include "sighandler.h"
16 #include <arpa/inet.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <netdb.h>
20 #include <netinet/in.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <sys/un.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
30 #include <libintl.h>
31 #define _(String) gettext(String)
32 #define gettext_noop(String) String
33 #define N_(String) gettext_noop (String)
36 // The render client waits for connections from the server.
37 // Then it starts a thread for each connection.
38 RenderFarmClient::RenderFarmClient(int port, char *deamon_path, int nice_value)
40         this->port = port;
41         this->deamon_path = deamon_path;
42         SigHandler *signals = new SigHandler;
43         signals->initialize();
45         this_pid = getpid();
46         nice(nice_value);
48         thread = new RenderFarmClientThread(this);
50         MWindow::init_defaults(boot_defaults);
51         boot_preferences = new Preferences;
52         boot_preferences->load_defaults(boot_defaults);
53         MWindow::init_plugins(boot_preferences, plugindb, 0);
59 RenderFarmClient::~RenderFarmClient()
61         delete thread;
62         delete boot_defaults;
63         delete boot_preferences;
64         plugindb->remove_all_objects();
65         delete plugindb;
69 void RenderFarmClient::main_loop()
71         int socket_fd;
75 // Open listening port
77         if(!deamon_path)
78         {
79                 struct sockaddr_in addr;
81                 addr.sin_family = AF_INET;
82                 addr.sin_port = htons((unsigned short)port);
83                 addr.sin_addr.s_addr = htonl(INADDR_ANY);
85                 if((socket_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
86                 {
87                         perror(_("RenderFarmClient::main_loop: socket"));
88                         return;
89                 }
91                 if(bind(socket_fd, 
92                         (struct sockaddr*)&addr, 
93                         sizeof(addr)) < 0)
94                 {
95                         fprintf(stderr, 
96                                 _("RenderFarmClient::main_loop: bind port %d: %s"),
97                                 port,
98                                 strerror(errno));
99                         return;
100                 }
101         }
102         else
103         {
104                 struct sockaddr_un addr;
105                 addr.sun_family = AF_FILE;
106                 strcpy(addr.sun_path, deamon_path);
107                 int size = (offsetof(struct sockaddr_un, sun_path) + 
108                         strlen(deamon_path) + 1);
110                 if((socket_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
111                 {
112                         perror(_("RenderFarmClient::main_loop: socket"));
113                         return;
114                 }
116                 if(bind(socket_fd, 
117                         (struct sockaddr*)&addr, 
118                         size) < 0)
119                 {
120                         fprintf(stderr, 
121                                 _("RenderFarmClient::main_loop: bind path %s: %s\n"),
122                                 deamon_path,
123                                 strerror(errno));
124                         return;
125                 }
126         }
128 // Wait for connections
129         printf("RenderFarmClient::main_loop: client started\n");
130         while(1)
131         {
132                 if(listen(socket_fd, 256) < 0)
133         {
134                 perror(_("RenderFarmClient::main_loop: listen"));
135                 return;
136         }
138                 int new_socket_fd;
142                 if(!deamon_path)
143                 {
144                         struct sockaddr_in clientname;
145                         socklen_t size = sizeof(clientname);
146                 if((new_socket_fd = accept(socket_fd,
147                                 (struct sockaddr*)&clientname, 
148                                                 &size)) < 0)
149                 {
150                         perror(_("RenderFarmClient::main_loop: accept"));
151                         return;
152                 }
153                         else
154                         {
155 printf("RenderFarmClient::main_loop: Session started from %s\n", inet_ntoa(clientname.sin_addr));
156                                 thread->main_loop(new_socket_fd);
157                         }
158                 }
159                 else
160                 {
161                         struct sockaddr_un clientname;
162                         socklen_t size = sizeof(clientname);
163                 if((new_socket_fd = accept(socket_fd,
164                                 (struct sockaddr*)&clientname, 
165                                                 &size)) < 0)
166                 {
167                         perror(_("RenderFarmClient::main_loop: accept"));
168                         return;
169                 }
170                         else
171                         {
172 printf("RenderFarmClient::main_loop: Session started from %s\n", clientname.sun_path);
173                                 thread->main_loop(new_socket_fd);
174                         }
175                 }
176         }
179 void RenderFarmClient::kill_client()
181 printf("RenderFarmClient::kill_client 1\n");
182         if(deamon_path)
183         {
184 printf("RenderFarmClient::kill_client 2\n");
185                 remove(deamon_path);
186                 kill(this_pid, SIGKILL);
187         }
200 // The thread requests jobs from the server until the job table is empty
201 // or the server reports an error.  This thread must poll the server
202 // after every frame for the error status.
203 // Detaches when finished.
204 RenderFarmClientThread::RenderFarmClientThread(RenderFarmClient *client)
205  : Thread()
207         this->client = client;
208         frames_per_second = 0;
209         Thread::set_synchronous(0);
210         fs_client = 0;
211         mutex_lock = new Mutex;
214 RenderFarmClientThread::~RenderFarmClientThread()
216         if(fs_client) delete fs_client;
217         delete mutex_lock;
221 int RenderFarmClientThread::send_request_header(int request, 
222         int len)
224         unsigned char datagram[5];
225         datagram[0] = request;
227         int i = 1;
228         STORE_INT32(len);
229 //printf("RenderFarmClientThread::send_request_header %02x%02x%02x%02x%02x\n",
230 //      datagram[0], datagram[1], datagram[2], datagram[3], datagram[4]);
232         return (write_socket((char*)datagram, 
233                 5, 
234                 RENDERFARM_TIMEOUT) != 5);
237 int RenderFarmClientThread::write_socket(char *data, int len, int timeout)
239         return RenderFarmServerThread::write_socket(socket_fd, 
240                 data, 
241                 len, 
242                 timeout);
245 int RenderFarmClientThread::read_socket(char *data, int len, int timeout)
247         return RenderFarmServerThread::read_socket(socket_fd, 
248                 data, 
249                 len, 
250                 timeout);
253 void RenderFarmClientThread::lock()
255 //printf("RenderFarmClientThread::lock 1 %p %p\n", this, mutex_lock);
256         mutex_lock->lock();
259 void RenderFarmClientThread::unlock()
261 //printf("RenderFarmClientThread::unlock 1\n");
262         mutex_lock->unlock();
265 void RenderFarmClientThread::read_string(int socket_fd, char* &string)
267         unsigned char header[4];
268         if(read_socket((char*)header, 4, RENDERFARM_TIMEOUT) != 4)
269         {
270                 string = 0;
271                 return;
272         }
274         int64_t len = (((u_int32_t)header[0]) << 24) | 
275                                 (((u_int32_t)header[1]) << 16) | 
276                                 (((u_int32_t)header[2]) << 8) | 
277                                 ((u_int32_t)header[3]);
278 //printf("RenderFarmClientThread::read_string %d %02x%02x%02x%02x\n",
279 //      len, header[0], header[1], header[2], header[3]);
281         if(len)
282         {
283                 string = new char[len];
284                 if(read_socket(string, len, RENDERFARM_TIMEOUT) != len)
285                 {
286                         delete [] string;
287                         string = 0;
288                 }
289         }
290         else
291                 string = 0;
293 //printf("RenderFarmClientThread::read_string \n%s\n", string);
297 void RenderFarmClientThread::read_preferences(int socket_fd, 
298         Preferences *preferences)
300 //printf("RenderFarmClientThread::read_preferences 1\n");
301         send_request_header(RENDERFARM_PREFERENCES, 
302                 0);
304 //printf("RenderFarmClientThread::read_preferences 2\n");
305         char *string;
306         read_string(socket_fd, string);
307 //printf("RenderFarmClientThread::read_preferences 3\n%s\n", string);
309         Defaults defaults;
310         defaults.load_string((char*)string);
311         preferences->load_defaults(&defaults);
312 //printf("RenderFarmClientThread::read_preferences 4\n");
314         delete [] string;
319 void RenderFarmClientThread::read_asset(int socket_fd, Asset *asset)
321         send_request_header(RENDERFARM_ASSET, 
322                 0);
324         char *string;
325         read_string(socket_fd, string);
326 //printf("RenderFarmClientThread::read_asset\n%s\n", string);
328         FileXML file;
329         file.read_from_string((char*)string);
330         asset->read(client->plugindb, &file);
332         delete [] string;
335 void RenderFarmClientThread::read_edl(int socket_fd, 
336         EDL *edl, 
337         Preferences *preferences)
339         send_request_header(RENDERFARM_EDL, 
340                 0);
342         char *string;
343         read_string(socket_fd, string);
345 //printf("RenderFarmClientThread::read_edl 1\n");
347         FileXML file;
348         file.read_from_string((char*)string);
349         delete [] string;
358         edl->load_xml(client->plugindb,
359                 &file, 
360                 LOAD_ALL);
364 // Tag input paths for VFS here.
365 // Create VFS object.
366         FileSystem fs;
367         if(preferences->renderfarm_vfs)
368         {
369                 fs_client = new RenderFarmFSClient(this);
370                 fs_client->initialize();
372                 for(Asset *asset = edl->assets->first;
373                         asset;
374                         asset = asset->next)
375                 {
376                         char string2[BCTEXTLEN];
377                         strcpy(string2, asset->path);
378                         sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", string2);
379                 }
380         }
382 //      for(Asset *asset = edl->assets->first;
383 //              asset;
384 //              asset = asset->next)
385 //      {
386 //              char string2[BCTEXTLEN];
387 //              strcpy(string2, asset->path);
388 //              fs.join_names(asset->path, preferences->renderfarm_mountpoint, string2);
389 //      }
392 //edl->dump();
395 int RenderFarmClientThread::read_package(int socket_fd, RenderPackage *package)
397         send_request_header(RENDERFARM_PACKAGE, 
398                 4);
400         unsigned char datagram[5];
401         int i = 0;
404 // Fails if -ieee isn't set.
405         int64_t fixed = !EQUIV(frames_per_second, 0.0) ? 
406                 (int64_t)(frames_per_second * 65536.0) : 0;
407         STORE_INT32(fixed);
408         write_socket((char*)datagram, 4, RENDERFARM_TIMEOUT);
411         char *data;
412         unsigned char *data_ptr;
413         read_string(socket_fd, data);
415 // Signifies end of session.
416         if(!data) 
417         {
418 //              printf(_("RenderFarmClientThread::read_package no output path recieved.\n"));
419                 return 1;
420         }
424         data_ptr = (unsigned char*)data;
425         strcpy(package->path, data);
426         data_ptr += strlen(package->path);
427         data_ptr++;
428         package->audio_start = READ_INT32(data_ptr);
429         data_ptr += 4;
430         package->audio_end = READ_INT32(data_ptr);
431         data_ptr += 4;
432         package->video_start = READ_INT32(data_ptr);
433         data_ptr += 4;
434         package->video_end = READ_INT32(data_ptr);
435         data_ptr += 4;
436         package->use_brender = READ_INT32(data_ptr);
438         delete [] data;
440         return 0;
443 int RenderFarmClientThread::send_completion(int socket_fd)
445         return send_request_header(RENDERFARM_DONE, 
446                 0);
452 void RenderFarmClientThread::main_loop(int socket_fd)
454          this->socket_fd = socket_fd;
455          Thread::start();
458 void RenderFarmClientThread::run()
460 // Create new memory space
461         int pid = fork();
462         if(pid != 0)
463         {
464                 int return_value;
465                 waitpid(pid, &return_value, 0);
466                 return;
467         }
474         int socket_fd = this->socket_fd;
475 //printf("RenderFarmClientThread::run 1\n");
476         EDL *edl;
477         RenderPackage *package;
478         Asset *default_asset;
479         Preferences *preferences;
480         FarmPackageRenderer package_renderer(this, socket_fd);
481         int result = 0;
483 //printf("RenderFarmClientThread::run 2\n");
484 // Read settings
485         preferences = new Preferences;
486         default_asset = new Asset;
487         package = new RenderPackage;
488         edl = new EDL;
489         edl->create_objects();
491 //printf("RenderFarmClientThread::run 3\n");
499         read_preferences(socket_fd, preferences);
500 //printf("RenderFarmClientThread::run 3\n");
501         read_asset(socket_fd, default_asset);
502 //printf("RenderFarmClientThread::run 3\n");
503         read_edl(socket_fd, edl, preferences);
504 //edl->dump();
512 //printf("RenderFarmClientThread::run 4\n");
514         package_renderer.initialize(0,
515                         edl, 
516                         preferences, 
517                         default_asset,
518                         client->plugindb);
519 //printf("RenderFarmClientThread::run 5\n");
521 // Read packages
522         while(1)
523         {
524                 result = read_package(socket_fd, package);
525 //printf("RenderFarmClientThread::run 6 %d\n", result);
528 // Finished list
529                 if(result)
530                 {
531 //printf("RenderFarmClientThread::run 7 %d\n", result);
533                         result = send_completion(socket_fd);
534                         break;
535                 }
537                 Timer timer;
538                 timer.update();
540 // Error
541                 if(package_renderer.render_package(package))
542                 {
543 //printf("RenderFarmClientThread::run 8\n");
544                         result = send_completion(socket_fd);
545                         break;
546                 }
548                 frames_per_second = (double)(package->video_end - package->video_start) / 
549                         ((double)timer.get_difference() / 1000);
551 //printf("RenderFarmClientThread::run 9\n");
555         }
558 //printf("RenderFarmClientThread::run 9\n");
559         delete default_asset;
560 //printf("RenderFarmClientThread::run 10\n");
561         delete edl;
562 //printf("RenderFarmClientThread::run 11\n");
563         delete preferences;
564 //printf("RenderFarmClientThread::run 12\n");
565 printf(_("RenderFarmClientThread::run: Session finished.\n"));
567 // Socket error should be the only cause of this
568         if(result)
569         {
570                 ;
571         }
573         _exit(0);
583 FarmPackageRenderer::FarmPackageRenderer(RenderFarmClientThread *thread,
584                 int socket_fd)
585  : PackageRenderer()
587         this->thread = thread;
588         this->socket_fd = socket_fd;
593 FarmPackageRenderer::~FarmPackageRenderer()
598 int FarmPackageRenderer::get_result()
600         thread->lock();
601         thread->send_request_header(RENDERFARM_GET_RESULT, 
602                 0);
603         unsigned char data[1];
604         data[0] = 1;
605         if(thread->read_socket((char*)data, 1, RENDERFARM_TIMEOUT) != 1)
606         {
607                 thread->unlock();
608                 return 1;
609         }
610         thread->unlock();
611         return data[0];
614 void FarmPackageRenderer::set_result(int value)
616         thread->lock();
617         thread->send_request_header(RENDERFARM_SET_RESULT, 
618                 1);
619         unsigned char data[1];
620         data[0] = value;
621         thread->write_socket((char*)data, 1, RENDERFARM_TIMEOUT);
622         thread->unlock();
625 void FarmPackageRenderer::set_progress(int64_t total_samples)
627         thread->lock();
628         thread->send_request_header(RENDERFARM_PROGRESS, 
629                 4);
630         unsigned char datagram[4];
631         int i = 0;
632         STORE_INT32(total_samples);
633         thread->write_socket((char*)datagram, 4, RENDERFARM_TIMEOUT);
634         thread->unlock();
637 void FarmPackageRenderer::set_video_map(int64_t position, int value)
639         thread->lock();
640         thread->send_request_header(RENDERFARM_SET_VMAP, 
641                 8);
642         unsigned char datagram[8];
643         int i = 0;
644         STORE_INT32(position);
645         STORE_INT32(value);
646         thread->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT);
647         thread->unlock();