r858: Merge 2.1:
[cinelerra_cv.git] / cinelerra / renderfarmclient.C
bloba0a402a6b1fb8e881095a3491c1fef12b1af0bd8
1 #include "asset.h"
2 #include "assets.h"
3 #include "clip.h"
4 #include "bchash.h"
5 #include "edl.h"
6 #include "filesystem.h"
7 #include "filexml.h"
8 #include "language.h"
9 #include "mutex.h"
10 #include "mwindow.h"
11 #include "pluginserver.h"
12 #include "preferences.h"
13 #include "renderfarm.h"
14 #include "renderfarmclient.h"
15 //#include "renderfarmfsclient.h"
16 #include "sighandler.h"
18 #include <arpa/inet.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
34 // The render client waits for connections from the server.
35 // Then it starts a thread for each connection.
36 RenderFarmClient::RenderFarmClient(int port, 
37         char *deamon_path, 
38         int nice_value,
39         char *config_path)
41         this->port = port;
42         this->deamon_path = deamon_path;
43         SigHandler *signals = new SigHandler;
44         signals->initialize();
46         this_pid = getpid();
47         nice(nice_value);
49         thread = new RenderFarmClientThread(this);
51         MWindow::init_defaults(boot_defaults, config_path);
52         boot_preferences = new Preferences;
53         boot_preferences->load_defaults(boot_defaults);
54         MWindow::init_plugins(boot_preferences, plugindb, 0);
60 RenderFarmClient::~RenderFarmClient()
62         delete thread;
63         delete boot_defaults;
64         delete boot_preferences;
65         plugindb->remove_all_objects();
66         delete plugindb;
70 void RenderFarmClient::main_loop()
72         int socket_fd;
76 // Open listening port
78         if(!deamon_path)
79         {
80                 struct sockaddr_in addr;
82                 addr.sin_family = AF_INET;
83                 addr.sin_port = htons((unsigned short)port);
84                 addr.sin_addr.s_addr = htonl(INADDR_ANY);
86                 if((socket_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
87                 {
88                         perror(_("RenderFarmClient::main_loop: socket"));
89                         return;
90                 }
92                 if(bind(socket_fd, 
93                         (struct sockaddr*)&addr, 
94                         sizeof(addr)) < 0)
95                 {
96                         fprintf(stderr, 
97                                 _("RenderFarmClient::main_loop: bind port %d: %s"),
98                                 port,
99                                 strerror(errno));
100                         return;
101                 }
102         }
103         else
104         {
105                 struct sockaddr_un addr;
106                 addr.sun_family = AF_FILE;
107                 strcpy(addr.sun_path, deamon_path);
108                 int size = (offsetof(struct sockaddr_un, sun_path) + 
109                         strlen(deamon_path) + 1);
111                 if((socket_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
112                 {
113                         perror(_("RenderFarmClient::main_loop: socket"));
114                         return;
115                 }
117                 if(bind(socket_fd, 
118                         (struct sockaddr*)&addr, 
119                         size) < 0)
120                 {
121                         fprintf(stderr, 
122                                 _("RenderFarmClient::main_loop: bind path %s: %s\n"),
123                                 deamon_path,
124                                 strerror(errno));
125                         return;
126                 }
127         }
129 // Wait for connections
130         printf("RenderFarmClient::main_loop: client started\n");
131         while(1)
132         {
133                 if(listen(socket_fd, 256) < 0)
134         {
135                 perror(_("RenderFarmClient::main_loop: listen"));
136                 return;
137         }
139                 int new_socket_fd;
143                 if(!deamon_path)
144                 {
145                         struct sockaddr_in clientname;
146                         socklen_t size = sizeof(clientname);
147                 if((new_socket_fd = accept(socket_fd,
148                                 (struct sockaddr*)&clientname, 
149                                                 &size)) < 0)
150                 {
151                         perror(_("RenderFarmClient::main_loop: accept"));
152                         return;
153                 }
154                         else
155                         {
156 //printf("RenderFarmClient::main_loop: Session started from %s\n", inet_ntoa(clientname.sin_addr));
157                                 thread->main_loop(new_socket_fd);
158                         }
159                 }
160                 else
161                 {
162                         struct sockaddr_un clientname;
163                         socklen_t size = sizeof(clientname);
164                 if((new_socket_fd = accept(socket_fd,
165                                 (struct sockaddr*)&clientname, 
166                                                 &size)) < 0)
167                 {
168                         perror(_("RenderFarmClient::main_loop: accept"));
169                         return;
170                 }
171                         else
172                         {
173 //printf("RenderFarmClient::main_loop: Session started from %s\n", clientname.sun_path);
174                                 thread->main_loop(new_socket_fd);
175                         }
176                 }
177         }
180 void RenderFarmClient::kill_client()
182 printf("RenderFarmClient::kill_client 1\n");
183         if(deamon_path)
184         {
185 printf("RenderFarmClient::kill_client 2\n");
186                 remove(deamon_path);
187                 kill(this_pid, SIGKILL);
188         }
201 // The thread requests jobs from the server until the job table is empty
202 // or the server reports an error.  This thread must poll the server
203 // after every frame for the error status.
204 // Detaches when finished.
205 RenderFarmClientThread::RenderFarmClientThread(RenderFarmClient *client)
206  : Thread()
208         this->client = client;
209         frames_per_second = 0;
210         Thread::set_synchronous(0);
211 //      fs_client = 0;
212         mutex_lock = new Mutex("RenderFarmClientThread::mutex_lock");
215 RenderFarmClientThread::~RenderFarmClientThread()
217 //      if(fs_client) delete fs_client;
218         delete mutex_lock;
222 int RenderFarmClientThread::send_request_header(int request, 
223         int len)
225         unsigned char datagram[5];
226         datagram[0] = request;
228         int i = 1;
229         STORE_INT32(len);
230 // printf("RenderFarmClientThread::send_request_header %d %02x%02x%02x%02x%02x\n",
231 // request, datagram[0], datagram[1], datagram[2], datagram[3], datagram[4]);
233         return (write_socket((char*)datagram, 
234                 5, 
235                 RENDERFARM_TIMEOUT) != 5);
238 int RenderFarmClientThread::write_socket(char *data, int len, int timeout)
240         int result = RenderFarmServerThread::write_socket(socket_fd, 
241                 data, 
242                 len, 
243                 timeout);
244 // Assume the stream is offset and give up future accesses.
245         if(result <= 0) abort();
248 int RenderFarmClientThread::read_socket(char *data, int len, int timeout)
250         int result = RenderFarmServerThread::read_socket(socket_fd, 
251                 data, 
252                 len, 
253                 timeout);
254 // Assume the stream is offset and give up future accesses.
255         if(result <= 0) abort();
258 void RenderFarmClientThread::abort()
260         send_completion(socket_fd);
261         close(socket_fd);
262         exit(1);
265 void RenderFarmClientThread::lock(char *location)
267         mutex_lock->lock(location);
270 void RenderFarmClientThread::unlock()
272         mutex_lock->unlock();
275 void RenderFarmClientThread::read_string(int socket_fd, char* &string)
277         unsigned char header[4];
278         if(read_socket((char*)header, 4, RENDERFARM_TIMEOUT) != 4)
279         {
280                 string = 0;
281                 return;
282         }
284         int64_t len = (((u_int32_t)header[0]) << 24) | 
285                                 (((u_int32_t)header[1]) << 16) | 
286                                 (((u_int32_t)header[2]) << 8) | 
287                                 ((u_int32_t)header[3]);
289         if(len)
290         {
291                 string = new char[len];
292                 if(read_socket(string, len, RENDERFARM_TIMEOUT) != len)
293                 {
294                         delete [] string;
295                         string = 0;
296                 }
297         }
298         else
299                 string = 0;
304 void RenderFarmClientThread::read_preferences(int socket_fd, 
305         Preferences *preferences)
307         send_request_header(RENDERFARM_PREFERENCES, 
308                 0);
310         char *string;
311         read_string(socket_fd, string);
313         BC_Hash defaults;
314         defaults.load_string((char*)string);
315         preferences->load_defaults(&defaults);
317         delete [] string;
322 void RenderFarmClientThread::read_asset(int socket_fd, Asset *asset)
324         send_request_header(RENDERFARM_ASSET, 
325                 0);
327         char *string1;
328         char *string2;
329         read_string(socket_fd, string1);
330         read_string(socket_fd, string2);
334         FileXML file;
335         file.read_from_string((char*)string2);
336         asset->read(&file);
337         
340         BC_Hash defaults;
341         defaults.load_string((char*)string1);
342         asset->load_defaults(&defaults,
343                 0,
344                 1,
345                 1,
346                 1,
347                 1,
348                 1);
350         delete [] string1;
351         delete [] string2;
354 void RenderFarmClientThread::read_edl(int socket_fd, 
355         EDL *edl, 
356         Preferences *preferences)
358         send_request_header(RENDERFARM_EDL, 
359                 0);
361         char *string;
362         read_string(socket_fd, string);
365         FileXML file;
366         file.read_from_string((char*)string);
367         delete [] string;
376         edl->load_xml(client->plugindb,
377                 &file, 
378                 LOAD_ALL);
382 // Tag input paths for VFS here.
383 // Create VFS object.
384         FileSystem fs;
385 //      if(preferences->renderfarm_vfs)
386 //      {
387 //              fs_client = new RenderFarmFSClient(this);
388 //              fs_client->initialize();
389 // 
390 //              for(Asset *asset = edl->assets->first;
391 //                      asset;
392 //                      asset = asset->next)
393 //              {
394 //                      char string2[BCTEXTLEN];
395 //                      strcpy(string2, asset->path);
396 //                      sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", string2);
397 //              }
398 //      }
400 //      for(Asset *asset = edl->assets->first;
401 //              asset;
402 //              asset = asset->next)
403 //      {
404 //              char string2[BCTEXTLEN];
405 //              strcpy(string2, asset->path);
406 //              fs.join_names(asset->path, preferences->renderfarm_mountpoint, string2);
407 //      }
410 //edl->dump();
413 int RenderFarmClientThread::read_package(int socket_fd, RenderPackage *package)
415         send_request_header(RENDERFARM_PACKAGE, 
416                 4);
418         unsigned char datagram[5];
419         int i = 0;
422 // Fails if -ieee isn't set.
423         int64_t fixed = !EQUIV(frames_per_second, 0.0) ? 
424                 (int64_t)(frames_per_second * 65536.0) : 0;
425         STORE_INT32(fixed);
426         write_socket((char*)datagram, 4, RENDERFARM_TIMEOUT);
429 //printf("RenderFarmClientThread::read_package 1 %f %ld\n", frames_per_second, fixed);
430         char *data;
431         unsigned char *data_ptr;
432         read_string(socket_fd, data);
433 //printf("RenderFarmClientThread::read_package 2 %p\n", data);
434 // Signifies end of session.
435         if(!data) 
436         {
437 //              printf(_("RenderFarmClientThread::read_package no output path recieved.\n"));
438                 return 1;
439         }
441 //printf("RenderFarmClientThread::read_package 2\n");
444         data_ptr = (unsigned char*)data;
445         strcpy(package->path, data);
446         data_ptr += strlen(package->path);
447         data_ptr++;
448         package->audio_start = READ_INT32(data_ptr);
449         data_ptr += 4;
450         package->audio_end = READ_INT32(data_ptr);
451         data_ptr += 4;
452         package->video_start = READ_INT32(data_ptr);
453         data_ptr += 4;
454         package->video_end = READ_INT32(data_ptr);
455         data_ptr += 4;
456         package->use_brender = READ_INT32(data_ptr);
457         data_ptr += 4;
458         package->audio_do = READ_INT32(data_ptr);
459         data_ptr += 4;
460         package->video_do = READ_INT32(data_ptr);
462         delete [] data;
464         return 0;
467 int RenderFarmClientThread::send_completion(int socket_fd)
469         return send_request_header(RENDERFARM_DONE, 
470                 0);
476 void RenderFarmClientThread::main_loop(int socket_fd)
478          this->socket_fd = socket_fd;
480          Thread::start();
483 void RenderFarmClientThread::run()
485 // Create new memory space
486         int pid = fork();
487         if(pid != 0)
488         {
489                 int return_value;
490                 waitpid(pid, &return_value, 0);
491                 return;
492         }
499         int socket_fd = this->socket_fd;
502 //printf("RenderFarmClientThread::run command=%d\n", command);
504 SET_TRACE
507         EDL *edl;
508         RenderPackage *package;
509         Asset *default_asset;
510         Preferences *preferences;
514         FarmPackageRenderer package_renderer(this, socket_fd);
515         int result = 0;
519 //printf("RenderFarmClientThread::run 2\n");
520 // Read settings
521         preferences = new Preferences;
522         default_asset = new Asset;
523         package = new RenderPackage;
524         edl = new EDL;
525         edl->create_objects();
527 //printf("RenderFarmClientThread::run 3\n");
535         read_preferences(socket_fd, preferences);
536 //printf("RenderFarmClientThread::run 3\n");
537         read_asset(socket_fd, default_asset);
538 //printf("RenderFarmClientThread::run 3\n");
539         read_edl(socket_fd, edl, preferences);
540 //edl->dump();
548 //printf("RenderFarmClientThread::run 4\n");
550         package_renderer.initialize(0,
551                         edl, 
552                         preferences, 
553                         default_asset,
554                         client->plugindb);
555 //printf("RenderFarmClientThread::run 5\n");
557 // Read packages
558         while(1)
559         {
560                 result = read_package(socket_fd, package);
561 //printf("RenderFarmClientThread::run 6 %d\n", result);
564 // Finished list
565                 if(result)
566                 {
567 //printf("RenderFarmClientThread::run 7\n");
569                         result = send_completion(socket_fd);
570                         break;
571                 }
573                 Timer timer;
574                 timer.update();
576 // Error
577                 if(package_renderer.render_package(package))
578                 {
579 //printf("RenderFarmClientThread::run 8\n");
580                         result = send_completion(socket_fd);
581                         break;
582                 }
584                 frames_per_second = (double)(package->video_end - package->video_start) / 
585                         ((double)timer.get_difference() / 1000);
587 //printf("RenderFarmClientThread::run 9\n");
591         }
594 //printf("RenderFarmClientThread::run 9\n");
595         Garbage::delete_object(default_asset);
596 //printf("RenderFarmClientThread::run 10\n");
597         delete edl;
598 //printf("RenderFarmClientThread::run 11\n");
599         delete preferences;
600 printf(_("RenderFarmClientThread::run: Session finished.\n"));
602         _exit(0);
612 FarmPackageRenderer::FarmPackageRenderer(RenderFarmClientThread *thread,
613                 int socket_fd)
614  : PackageRenderer()
616         this->thread = thread;
617         this->socket_fd = socket_fd;
622 FarmPackageRenderer::~FarmPackageRenderer()
627 int FarmPackageRenderer::get_result()
629         thread->lock("FarmPackageRenderer::get_result");
630         thread->send_request_header(RENDERFARM_GET_RESULT, 
631                 0);
632         unsigned char data[1];
633         data[0] = 1;
634         if(thread->read_socket((char*)data, 1, RENDERFARM_TIMEOUT) != 1)
635         {
636                 thread->unlock();
637                 return 1;
638         }
639         thread->unlock();
640         return data[0];
643 void FarmPackageRenderer::set_result(int value)
645         thread->lock("FarmPackageRenderer::set_result");
646         thread->send_request_header(RENDERFARM_SET_RESULT, 
647                 1);
648         unsigned char data[1];
649         data[0] = value;
650         thread->write_socket((char*)data, 1, RENDERFARM_TIMEOUT);
651         thread->unlock();
654 void FarmPackageRenderer::set_progress(int64_t total_samples)
656         thread->lock("FarmPackageRenderer::set_progress");
657         thread->send_request_header(RENDERFARM_PROGRESS, 
658                 4);
659         unsigned char datagram[4];
660         int i = 0;
661         STORE_INT32(total_samples);
662         thread->write_socket((char*)datagram, 4, RENDERFARM_TIMEOUT);
663         thread->unlock();
666 int FarmPackageRenderer::set_video_map(int64_t position, int value)
668         int result = 0;
669         unsigned char datagram[8];
670         char return_value[1];
671         int i = 0;
673         thread->lock("FarmPackageRenderer::set_video_map");
674         thread->send_request_header(RENDERFARM_SET_VMAP, 
675                 8);
676         STORE_INT32(position);
677         STORE_INT32(value);
678         thread->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT);
680 // Get completion since the GUI may be locked for a long time.
681         if(!thread->read_socket(return_value, 1, RENDERFARM_TIMEOUT))
682         {
683                 result = 1;
684         }
686         thread->unlock();
687         return result;