4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "filesystem.h"
34 #include "pluginserver.h"
35 #include "preferences.h"
36 #include "renderfarm.h"
37 #include "renderfarmclient.h"
38 //#include "renderfarmfsclient.h"
39 #include "sighandler.h"
41 #include <arpa/inet.h>
45 #include <netinet/in.h>
48 #include <sys/socket.h>
49 #include <sys/types.h>
56 #define AF_FILE AF_LOCAL
59 // The render client waits for connections from the server.
60 // Then it starts a thread for each connection.
61 RenderFarmClient::RenderFarmClient(int port,
66 char string[BCTEXTLEN];
69 this->deamon_path = deamon_path;
70 SigHandler *signals = new SigHandler;
71 signals->initialize("/tmp/cinelerra_farm%d.dmp");
74 (void)nice(nice_value);
77 MWindow::init_defaults(boot_defaults, config_path);
78 boot_preferences = new Preferences;
79 boot_preferences->load_defaults(boot_defaults);
80 MWindow::init_plugins(0, boot_preferences);
81 MWindow::init_ladspa_plugins(0, boot_preferences);
82 BC_Signals::set_catch_segv(boot_preferences->trap_sigsegv);
83 BC_Signals::set_catch_intr(0);
84 if( boot_preferences->trap_sigsegv ) {
85 BC_Trace::enable_locks();
88 BC_Trace::disable_locks();
91 strcpy(string, boot_preferences->plugin_dir);
92 strcat(string, "/" FONT_SEARCHPATH);
93 BC_Resources::init_fontconfig(string);
99 RenderFarmClient::~RenderFarmClient()
101 delete boot_defaults;
102 delete boot_preferences;
106 void RenderFarmClient::main_loop()
109 BC_WindowBase::get_resources()->vframe_shm = 1;
112 // Open listening port
116 struct sockaddr_in addr;
118 addr.sin_family = AF_INET;
119 addr.sin_port = htons((unsigned short)port);
120 addr.sin_addr.s_addr = htonl(INADDR_ANY);
122 if((socket_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
124 perror(_("RenderFarmClient::main_loop: socket"));
130 if( setsockopt(socket_fd, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < 0 )
131 perror("RenderFarmClient::setsockopt:setlinger 0");
134 (struct sockaddr*)&addr,
138 _("RenderFarmClient::main_loop: bind port %d: %s"),
146 struct sockaddr_un addr;
147 addr.sun_family = AF_FILE;
148 strcpy(addr.sun_path, deamon_path);
149 int size = (offsetof(struct sockaddr_un, sun_path) +
150 strlen(deamon_path) + 1);
152 if((socket_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
154 perror(_("RenderFarmClient::main_loop: socket"));
160 if( setsockopt(socket_fd, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < 0 )
161 perror("RenderFarmClient::setsockopt:setlinger 1");
164 (struct sockaddr*)&addr,
168 _("RenderFarmClient::main_loop: bind path %s: %s\n"),
175 // Wait for connections
176 printf("RenderFarmClient::main_loop: client started\n");
179 if(listen(socket_fd, 256) < 0) {
180 perror(_("RenderFarmClient::main_loop: listen"));
188 struct sockaddr_in clientname;
189 socklen_t size = sizeof(clientname);
190 if( (new_socket_fd = accept(socket_fd,
191 (struct sockaddr*)&clientname, &size) ) < 0 ) {
192 perror(_("RenderFarmClient::main_loop: accept"));
195 printf("RenderFarmClient::main_loop: Session started from %s\n", inet_ntoa(clientname.sin_addr));
196 RenderFarmClientThread *thread =
197 new RenderFarmClientThread(this);
198 thread->main_loop(new_socket_fd);
202 struct sockaddr_un clientname;
203 socklen_t size = sizeof(clientname);
204 if( (new_socket_fd = accept(socket_fd,
205 (struct sockaddr*)&clientname, &size)) < 0 ) {
206 perror(_("RenderFarmClient::main_loop: accept"));
209 printf("RenderFarmClient::main_loop: Session started from %s\n", clientname.sun_path);
210 RenderFarmClientThread *thread =
211 new RenderFarmClientThread(this);
212 thread->main_loop(new_socket_fd);
217 void RenderFarmClient::kill_client()
219 printf("RenderFarmClient::kill_client 1\n");
222 printf("RenderFarmClient::kill_client 2\n");
224 kill(this_pid, SIGKILL);
229 // The thread requests jobs from the server until the job table is empty
230 // or the server reports an error. This thread must poll the server
231 // after every frame for the error status.
232 // Detaches when finished.
233 RenderFarmClientThread::RenderFarmClientThread(RenderFarmClient *client)
236 this->client = client;
238 frames_per_second = 0;
239 Thread::set_synchronous(0);
241 mutex_lock = new Mutex("RenderFarmClientThread::mutex_lock");
246 RenderFarmClientThread::~RenderFarmClientThread()
248 // if(fs_client) delete fs_client;
255 int RenderFarmClientThread::send_request_header(int request,
258 unsigned char datagram[5];
259 datagram[0] = request;
263 // printf("RenderFarmClientThread::send_request_header %d %02x%02x%02x%02x%02x\n",
264 // request, datagram[0], datagram[1], datagram[2], datagram[3], datagram[4]);
266 return (write_socket((char*)datagram, 5) != 5);
269 int RenderFarmClientThread::write_socket(char *data, int len)
271 //printf("RenderFarmClientThread::write_socket 1\n");
272 int result = write(socket_fd, data, len);
273 //printf("RenderFarmClientThread::write_socket 10\n");
277 int RenderFarmClientThread::read_socket(char *data, int len)
281 //printf("RenderFarmClientThread::read_socket 1\n");
283 watchdog->begin_request();
284 while(len > 0 && bytes_read >= 0)
286 bytes_read = read(socket_fd, data + offset, len);
290 offset += bytes_read;
299 watchdog->end_request();
300 //printf("RenderFarmClientThread::read_socket 10\n");
305 int RenderFarmClientThread::write_int64(int64_t value)
307 unsigned char data[sizeof(int64_t)];
308 data[0] = (value >> 56) & 0xff;
309 data[1] = (value >> 48) & 0xff;
310 data[2] = (value >> 40) & 0xff;
311 data[3] = (value >> 32) & 0xff;
312 data[4] = (value >> 24) & 0xff;
313 data[5] = (value >> 16) & 0xff;
314 data[6] = (value >> 8) & 0xff;
315 data[7] = value & 0xff;
316 return (write_socket((char*)data, sizeof(int64_t)) != sizeof(int64_t));
319 int64_t RenderFarmClientThread::read_int64(int *error)
322 if(!error) error = &temp;
324 unsigned char data[sizeof(int64_t)];
325 *error = (read_socket((char*)data, sizeof(int64_t)) != sizeof(int64_t));
327 // Make it return 1 if error so it can be used to read a result code from the
332 result = (((int64_t)data[0]) << 56) |
333 (((uint64_t)data[1]) << 48) |
334 (((uint64_t)data[2]) << 40) |
335 (((uint64_t)data[3]) << 32) |
336 (((uint64_t)data[4]) << 24) |
337 (((uint64_t)data[5]) << 16) |
338 (((uint64_t)data[6]) << 8) |
344 void RenderFarmClientThread::read_string(char* &string)
346 unsigned char header[4];
347 if(read_socket((char*)header, 4) != 4)
353 int64_t len = (((u_int32_t)header[0]) << 24) |
354 (((u_int32_t)header[1]) << 16) |
355 (((u_int32_t)header[2]) << 8) |
356 ((u_int32_t)header[3]);
360 string = new char[len];
361 if(read_socket(string, len) != len)
372 void RenderFarmClientThread::abort()
374 send_completion(socket_fd);
379 void RenderFarmClientThread::lock(const char *location)
381 mutex_lock->lock(location);
384 void RenderFarmClientThread::unlock()
386 mutex_lock->unlock();
389 void RenderFarmClientThread::get_command(int socket_fd, int *command)
392 *command = read_int64(&error);
401 void RenderFarmClientThread::read_preferences(int socket_fd,
402 Preferences *preferences)
404 lock("RenderFarmClientThread::read_preferences");
405 send_request_header(RENDERFARM_PREFERENCES,
412 defaults.load_string((char*)string);
413 preferences->load_defaults(&defaults);
421 void RenderFarmClientThread::read_asset(int socket_fd, Asset *asset)
423 lock("RenderFarmClientThread::read_asset");
424 send_request_header(RENDERFARM_ASSET,
429 read_string(string1);
430 read_string(string2);
435 file.read_from_string((char*)string2);
441 defaults.load_string((char*)string1);
442 asset->load_defaults(&defaults, 0, 1, 1, 1, 1, 1);
444 //printf("RenderFarmClientThread::read_asset %d\n", __LINE__);
452 void RenderFarmClientThread::read_edl(int socket_fd,
453 EDL *edl, Preferences *preferences)
455 lock("RenderFarmClientThread::read_edl");
456 send_request_header(RENDERFARM_EDL, 0);
462 file.read_from_string((char*)string);
465 edl->load_xml(&file, LOAD_ALL);
469 int RenderFarmClientThread::read_package(int socket_fd, RenderPackage *package)
471 lock("RenderFarmClientThread::read_package");
472 send_request_header(RENDERFARM_PACKAGE,
475 unsigned char datagram[5];
479 // Fails if -ieee isn't set.
480 int64_t fixed = !EQUIV(frames_per_second, 0.0) ?
481 (int64_t)(frames_per_second * 65536.0) : 0;
483 write_socket((char*)datagram, 4);
486 //printf("RenderFarmClientThread::read_package 1 %f %ld\n", frames_per_second, fixed);
488 unsigned char *data_ptr;
490 //printf("RenderFarmClientThread::read_package 2 %p\n", data);
491 // Signifies end of session.
494 // printf(_("RenderFarmClientThread::read_package no output path received.\n"));
499 //printf("RenderFarmClientThread::read_package 2\n");
502 data_ptr = (unsigned char*)data;
503 strcpy(package->path, data);
504 data_ptr += strlen(package->path);
506 package->audio_start = READ_INT32(data_ptr);
508 package->audio_end = READ_INT32(data_ptr);
510 package->video_start = READ_INT32(data_ptr);
512 package->video_end = READ_INT32(data_ptr);
514 package->use_brender = READ_INT32(data_ptr);
516 package->audio_do = READ_INT32(data_ptr);
518 package->video_do = READ_INT32(data_ptr);
526 int RenderFarmClientThread::send_completion(int socket_fd)
528 lock("RenderFarmClientThread::send_completion");
529 int result = send_request_header(RENDERFARM_DONE, 0);
535 void RenderFarmClientThread::ping_server()
537 lock("RenderFarmClientThread::ping_server");
538 send_request_header(RENDERFARM_KEEPALIVE, 0);
544 void RenderFarmClientThread::main_loop(int socket_fd)
546 this->socket_fd = socket_fd;
551 void RenderFarmClientThread::run()
553 // Create new memory space
558 waitpid(pid, &return_value, 0);
562 // Get the pid of the fork if inside the fork
564 BC_Signals::set_trap_hook(trap_hook, this);
567 int socket_fd = this->socket_fd;
568 int watchdog_timeout = client->boot_preferences->renderfarm_watchdog_timeout;
569 if( watchdog_timeout > 0 )
570 init_client_keepalive(watchdog_timeout);
572 // Get command to run
574 lock("RenderFarmClientThread::run");
575 get_command(socket_fd, &command);
578 //printf("RenderFarmClientThread::run command=%d\n", command);
582 case RENDERFARM_TUNER:
585 case RENDERFARM_PACKAGES:
586 do_packages(socket_fd);
594 void RenderFarmClientThread::init_client_keepalive(int timeout_secs)
596 keep_alive = new RenderFarmKeepalive(this);
598 watchdog = new RenderFarmWatchdog(timeout_secs, 0, this);
604 void RenderFarmClientThread::do_tuner(int socket_fd)
606 // Currently only 1 tuner driver. Maybe more someday.
607 // DVBTune server(this);
608 // server.main_loop();
609 // ::close(socket_fd);
613 void RenderFarmClientThread::do_packages(int socket_fd)
615 RenderPackage *package;
616 Asset *default_asset;
617 Preferences *preferences;
621 FarmPackageRenderer package_renderer(this, socket_fd);
626 //printf("RenderFarmClientThread::run 2\n");
628 preferences = new Preferences;
629 default_asset = new Asset;
630 package = new RenderPackage;
632 edl->create_objects();
634 //printf("RenderFarmClientThread::run 3\n");
635 read_preferences(socket_fd, preferences);
636 //printf("RenderFarmClientThread::run 4\n");
637 read_asset(socket_fd, default_asset);
638 //printf("RenderFarmClientThread::run 5\n");
639 read_edl(socket_fd, edl, preferences);
641 //printf("RenderFarmClientThread::run 6\n");
643 package_renderer.initialize(0, edl, preferences, default_asset);
648 //printf("RenderFarmClientThread::run 5\n");
649 result = read_package(socket_fd, package);
650 //printf("RenderFarmClientThread::run 6 %d\n", result);
656 //printf("RenderFarmClientThread::run 7\n");
658 result = send_completion(socket_fd);
666 if(package_renderer.render_package(package))
668 //printf("RenderFarmClientThread::run 8\n");
669 result = send_completion(socket_fd);
674 frames_per_second = package_renderer.frames_per_second;
675 // frames_per_second = (double)(package->video_end - package->video_start) /
676 // ((double)timer.get_difference() / 1000);
678 //printf("RenderFarmClientThread::run 9\n");
685 //printf("RenderFarmClientThread::run 9\n");
686 default_asset->Garbage::remove_user();
687 //printf("RenderFarmClientThread::run 10\n");
688 edl->Garbage::remove_user();
690 //printf("RenderFarmClientThread::run 11\n");
692 printf(_("RenderFarmClientThread::run: Session finished.\n"));
695 void RenderFarmClientThread::trap_hook(FILE *fp, void *vp)
697 RenderFarmClientThread *thread = (RenderFarmClientThread*)vp;
698 fprintf(fp, "\nEDL:\n");
699 if( thread->edl ) thread->edl->dump(fp);
704 RenderFarmKeepalive::RenderFarmKeepalive(
705 RenderFarmClientThread *client_thread)
708 this->client_thread = client_thread;
712 RenderFarmKeepalive::~RenderFarmKeepalive()
719 void RenderFarmKeepalive::run()
727 //printf("RenderFarmKeepalive::run 1\n");
728 // watchdog thread kills this if it gets stuck
729 client_thread->ping_server();
730 //printf("RenderFarmKeepalive::run 10\n");
736 FarmPackageRenderer::FarmPackageRenderer(RenderFarmClientThread *thread,
740 this->thread = thread;
741 this->socket_fd = socket_fd;
745 FarmPackageRenderer::~FarmPackageRenderer()
750 int FarmPackageRenderer::get_result()
752 thread->lock("FarmPackageRenderer::get_result");
753 thread->send_request_header(RENDERFARM_GET_RESULT,
755 unsigned char data[1];
757 if(thread->read_socket((char*)data, 1) != 1)
766 void FarmPackageRenderer::set_result(int value)
768 thread->lock("FarmPackageRenderer::set_result");
769 thread->send_request_header(RENDERFARM_SET_RESULT,
771 unsigned char data[1];
773 thread->write_socket((char*)data, 1);
777 void FarmPackageRenderer::set_progress(int64_t total_samples)
779 thread->lock("FarmPackageRenderer::set_progress");
780 thread->send_request_header(RENDERFARM_PROGRESS,
782 unsigned char datagram[8];
784 STORE_INT32(total_samples);
787 int64_t fixed = (!EQUIV(frames_per_second, 0.0)) ?
788 (int64_t)(frames_per_second * 65536.0) : 0;
792 thread->write_socket((char*)datagram, 8);
796 int FarmPackageRenderer::set_video_map(int64_t position, int value)
799 unsigned char datagram[8];
800 char return_value[1];
803 thread->lock("FarmPackageRenderer::set_video_map");
804 thread->send_request_header(RENDERFARM_SET_VMAP,
806 STORE_INT32(position);
808 thread->write_socket((char*)datagram, 8);
810 // Get completion since the GUI may be locked for a long time.
811 if(!thread->read_socket(return_value, 1))