Titan Core Initial Contribution
[deliverable/titan.core.git] / mctr2 / mctr / MainController.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 //
9 // Description: Implementation file for MainController
10 // Author: Janos Zoltan Szabo
11 // mail: tmpjsz@eth.ericsson.se
12 //
13 // Copyright Ericsson Telecom AB 2000-2014
14 //
15 //----------------------------------------------------------------------------
16
17 #include "MainController.h"
18 #include "UserInterface.h"
19
20 #include "../../common/memory.h"
21 #include "../../common/version.h"
22 #include "../../common/version_internal.h"
23 #include "../../core/Message_types.hh"
24 #include "../../core/Error.hh"
25 #include "../../core/Textbuf.hh"
26 #include "../../core/Logger.hh"
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <stdarg.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <pthread.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/time.h>
39 #ifdef USE_EPOLL
40 #include <sys/epoll.h>
41 #else
42 #include <sys/poll.h>
43 #endif
44 #include <sys/utsname.h>
45 #include <netinet/in.h>
46 #include <netinet/tcp.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #include <sys/un.h>
50 #include <signal.h>
51
52 reffer::reffer(const char*) {}
53
54 //----------------------------------------------------------------------------
55
56 namespace mctr {
57
58 //----------------------------------------------------------------------------
59
60 /* Static variables */
61
62 UserInterface *MainController::ui;
63 NetworkHandler MainController::nh;
64
65 mc_state_enum MainController::mc_state;
66 char *MainController::mc_hostname;
67
68 struct sigaction MainController::new_action, MainController::old_action;
69
70 int MainController::server_fd;
71 int MainController::server_fd_unix = -1;
72 boolean MainController::server_fd_disabled;
73
74 void MainController::disable_server_fd()
75 {
76 if (!server_fd_disabled) {
77 remove_poll_fd(server_fd);
78 server_fd_disabled = TRUE;
79 }
80 }
81
82 void MainController::enable_server_fd()
83 {
84 if (server_fd_disabled) {
85 add_poll_fd(server_fd);
86 server_fd_disabled = FALSE;
87 }
88 }
89
90 pthread_mutex_t MainController::mutex;
91
92 void MainController::lock()
93 {
94 int result = pthread_mutex_lock(&mutex);
95 if (result > 0) {
96 fatal_error("MainController::lock: "
97 "pthread_mutex_lock failed with code %d.", result);
98 }
99 }
100
101 void MainController::unlock()
102 {
103 int result = pthread_mutex_unlock(&mutex);
104 if (result > 0) {
105 fatal_error("MainController::unlock: "
106 "pthread_mutex_unlock failed with code %d.", result);
107 }
108 }
109
110 #ifdef USE_EPOLL
111 epoll_event *MainController::epoll_events;
112 int MainController::epfd;
113 #else
114 unsigned int MainController::nfds, MainController::new_nfds;
115 struct pollfd *MainController::ufds, *MainController::new_ufds;
116 boolean MainController::pollfds_modified;
117 #endif //USE_EPOLL
118
119 #ifdef USE_EPOLL
120 void MainController::add_poll_fd(int fd)
121 {
122 if (fd < 0) return;
123 epoll_event event;
124 event.events = EPOLLIN;
125 event.data.fd = fd;
126 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) < 0)
127 fatal_error("MainController::add_poll_fd: system call epoll_ctl"
128 " failed on file descriptor %d.", fd);
129 }
130
131 void MainController::remove_poll_fd(int fd)
132 {
133 if (fd < 0) return;
134 epoll_event event;
135 event.events = EPOLLIN;
136 event.data.fd = fd;
137 if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &event) < 0)
138 fatal_error("MainController::remove_poll_fd: system call epoll_ctl"
139 " failed on file descriptor %d.", fd);
140 }
141 #else // ! defined USE_EPOLL
142 void MainController::add_poll_fd(int fd)
143 {
144 if (fd < 0) return;
145 if (pollfds_modified) {
146 int i;
147 for (i = new_nfds - 1; i >= 0; i--) {
148 if (new_ufds[i].fd < fd) break;
149 else if (new_ufds[i].fd == fd) return;
150 }
151 i++;
152 new_ufds = (struct pollfd*)Realloc(new_ufds, (new_nfds + 1) *
153 sizeof(struct pollfd));
154 memmove(new_ufds + i + 1, new_ufds + i, (new_nfds - i) *
155 sizeof(struct pollfd));
156 new_ufds[i].fd = fd;
157 new_ufds[i].events = POLLIN;
158 new_ufds[i].revents = 0;
159 new_nfds++;
160 } else {
161 int i;
162 for (i = nfds - 1; i >= 0; i--) {
163 if (ufds[i].fd < fd) break;
164 else if (ufds[i].fd == fd) return;
165 }
166 i++;
167 new_nfds = nfds + 1;
168 new_ufds = (struct pollfd*)Malloc(new_nfds * sizeof(struct pollfd));
169 memcpy(new_ufds, ufds, i * sizeof(struct pollfd));
170 new_ufds[i].fd = fd;
171 new_ufds[i].events = POLLIN;
172 new_ufds[i].revents = 0;
173 memcpy(new_ufds + i + 1, ufds + i, (nfds - i) * sizeof(struct pollfd));
174 pollfds_modified = TRUE;
175 }
176 }
177
178 void MainController::remove_poll_fd(int fd)
179 {
180 if (fd < 0) return;
181 if (pollfds_modified) {
182 int i;
183 for (i = new_nfds - 1; i >= 0; i--) {
184 if (new_ufds[i].fd == fd) break;
185 else if (new_ufds[i].fd < fd) return;
186 }
187 if (i < 0) return;
188 new_nfds--;
189 memmove(new_ufds + i, new_ufds + i + 1, (new_nfds - i) *
190 sizeof(struct pollfd));
191 new_ufds = (struct pollfd*)Realloc(new_ufds, new_nfds *
192 sizeof(struct pollfd));
193 } else {
194 int i;
195 for (i = nfds - 1; i >= 0; i--) {
196 if (ufds[i].fd == fd) break;
197 else if (ufds[i].fd < fd) return;
198 }
199 if (i < 0) return;
200 new_nfds = nfds - 1;
201 new_ufds = (struct pollfd*)Malloc(new_nfds * sizeof(struct pollfd));
202 memcpy(new_ufds, ufds, i * sizeof(struct pollfd));
203 memcpy(new_ufds + i, ufds + i + 1, (new_nfds - i) *
204 sizeof(struct pollfd));
205 pollfds_modified = TRUE;
206 }
207 }
208
209 void MainController::update_pollfds()
210 {
211 if (pollfds_modified) {
212 nfds = new_nfds;
213 new_nfds = 0;
214 Free(ufds);
215 ufds = new_ufds;
216 new_ufds = NULL;
217 pollfds_modified = FALSE;
218 }
219 }
220 #endif //USE_EPOLL
221
222 int MainController::fd_table_size;
223 fd_table_struct *MainController::fd_table;
224
225 void MainController::add_fd_to_table(int fd)
226 {
227 if (fd >= fd_table_size) {
228 fd_table = (fd_table_struct *)Realloc(fd_table, (fd + 1) *
229 sizeof(fd_table_struct));
230 for (int i = fd_table_size; i <= fd; i++) {
231 fd_table[i].fd_type = FD_UNUSED;
232 fd_table[i].dummy_ptr = NULL;
233 }
234 fd_table_size = fd + 1;
235 }
236 }
237
238 void MainController::remove_fd_from_table(int fd)
239 {
240 if (fd < fd_table_size) {
241 fd_table[fd].fd_type = FD_UNUSED;
242 int i;
243 for (i = fd_table_size - 1; i >= 0 ; i--) {
244 if (fd_table[i].fd_type != FD_UNUSED) break;
245 }
246 if (i < fd_table_size - 1) {
247 fd_table_size = i + 1;
248 fd_table = (fd_table_struct *)Realloc(fd_table, fd_table_size *
249 sizeof(fd_table_struct));
250 }
251 }
252 }
253
254 void MainController::set_close_on_exec(int fd)
255 {
256 int flags = fcntl(fd, F_GETFD);
257 if (flags < 0) fatal_error("MainController::set_close_on_exec: system call "
258 "fcntl(F_GETFD) failed on file descriptor %d.", fd);
259
260 flags |= FD_CLOEXEC;
261
262 if (fcntl(fd, F_SETFD, flags) == -1)
263 fatal_error("MainController::set_close_on_exec: system call "
264 "fcntl(F_SETFD) failed on file descriptor %d.", fd);
265 }
266
267 unknown_connection *MainController::unknown_head, *MainController::unknown_tail;
268
269 unknown_connection *MainController::new_unknown_connection(
270 bool unix_socket)
271 {
272 unknown_connection *conn = new unknown_connection;
273 conn->unix_socket = unix_socket;
274 conn->prev = unknown_tail;
275 conn->next = NULL;
276 if (unknown_tail != NULL) unknown_tail->next = conn;
277 else unknown_head = conn;
278 unknown_tail = conn;
279 return conn;
280 }
281
282 void MainController::delete_unknown_connection(unknown_connection *conn)
283 {
284 if (conn->prev != NULL) conn->prev->next = conn->next;
285 else unknown_head = conn->next;
286 if (conn->next != NULL) conn->next->prev = conn->prev;
287 else unknown_tail = conn->prev;
288 delete conn;
289 }
290
291 void MainController::close_unknown_connection(unknown_connection *conn)
292 {
293 remove_poll_fd(conn->fd);
294 close(conn->fd);
295 remove_fd_from_table(conn->fd);
296 delete conn->text_buf;
297 delete_unknown_connection(conn);
298 enable_server_fd();
299 }
300
301 void MainController::init_string_set(string_set *set)
302 {
303 set->n_elements = 0;
304 set->elements = NULL;
305 }
306
307 void MainController::free_string_set(string_set *set)
308 {
309 for (int i = 0; i < set->n_elements; i++) Free(set->elements[i]);
310 Free(set->elements);
311 set->n_elements = 0;
312 set->elements = NULL;
313 }
314
315 void MainController::add_string_to_set(string_set *set, const char *str)
316 {
317 int i;
318 for (i = 0; i < set->n_elements; i++) {
319 int result = strcmp(set->elements[i], str);
320 if (result > 0) break;
321 else if (result == 0) return;
322 }
323 set->elements = (char**)Realloc(set->elements,
324 (set->n_elements + 1) * sizeof(*set->elements));
325 memmove(set->elements + i + 1, set->elements + i,
326 (set->n_elements - i) * sizeof(*set->elements));
327 set->elements[i] = mcopystr(str);
328 set->n_elements++;
329 }
330
331 void MainController::remove_string_from_set(string_set *set,
332 const char *str)
333 {
334 for (int i = 0; i < set->n_elements; i++) {
335 int result = strcmp(set->elements[i], str);
336 if (result < 0) continue;
337 else if (result == 0) {
338 Free(set->elements[i]);
339 set->n_elements--;
340 memmove(set->elements + i, set->elements + i + 1,
341 (set->n_elements - i) * sizeof(*set->elements));
342 set->elements = (char**)Realloc(set->elements,
343 set->n_elements * sizeof(*set->elements));
344 }
345 return;
346 }
347 }
348
349 boolean MainController::set_has_string(const string_set *set,
350 const char *str)
351 {
352 if(str == NULL) return FALSE;
353 for (int i = 0; i < set->n_elements; i++) {
354 int result = strcmp(set->elements[i], str);
355 if (result == 0) return TRUE;
356 else if (result > 0) break;
357 }
358 return FALSE;
359 }
360
361 const char *MainController::get_string_from_set(const string_set *set,
362 int index)
363 {
364 if (index >= 0 && index < set->n_elements) return set->elements[index];
365 else return NULL;
366 }
367
368 int MainController::n_host_groups;
369 host_group_struct *MainController::host_groups;
370 string_set MainController::assigned_components;
371 boolean MainController::all_components_assigned;
372
373 host_group_struct *MainController::add_host_group(const char *group_name)
374 {
375 int i;
376 for (i = 0 ; i < n_host_groups; i++) {
377 host_group_struct *group = host_groups + i;
378 int result = strcmp(group->group_name, group_name);
379 if (result > 0) break;
380 else if (result == 0) return group;
381 }
382 host_groups = (host_group_struct*)Realloc(host_groups,
383 (n_host_groups + 1) * sizeof(*host_groups));
384 host_group_struct *new_group = host_groups + i;
385 memmove(new_group + 1, new_group,
386 (n_host_groups - i) * sizeof(*host_groups));
387 new_group->group_name = mcopystr(group_name);
388 new_group->has_all_hosts = FALSE;
389 new_group->has_all_components = FALSE;
390 init_string_set(&new_group->host_members);
391 init_string_set(&new_group->assigned_components);
392 n_host_groups++;
393 return new_group;
394 }
395
396 host_group_struct *MainController::lookup_host_group(const char *group_name)
397 {
398 for (int i = 0; i < n_host_groups; i++) {
399 host_group_struct *group = host_groups + i;
400 int result = strcmp(group->group_name, group_name);
401 if (result == 0) return group;
402 else if (result > 0) break;
403 }
404 return NULL;
405 }
406
407 boolean MainController::is_similar_hostname(const char *host1,
408 const char *host2)
409 {
410 for (size_t i = 0; ; i++) {
411 unsigned char c1 = host1[i], c2 = host2[i];
412 if (c1 == '\0') {
413 // if host2 is the longer one it may contain an additional domain
414 // name with a leading dot (e.g. "foo" is similar to "foo.bar.com")
415 // note: empty string is similar with empty string only
416 if (c2 == '\0' || (i > 0 && c2 == '.')) return TRUE;
417 else return FALSE;
418 } else if (c2 == '\0') {
419 // or vice versa
420 if (c1 == '\0' || (i > 0 && c1 == '.')) return TRUE;
421 else return FALSE;
422 } else {
423 // case insensitive comparison of the characters
424 if (tolower(c1) != tolower(c2)) return FALSE;
425 // continue the evaluation if they are matching
426 }
427 }
428 }
429
430 boolean MainController::host_has_name(const host_struct *host, const char *name)
431 {
432 // name might resemble to host->hostname
433 if (is_similar_hostname(host->hostname, name)) return TRUE;
434 // to avoid returning true in situations when name is "foo.bar.com", but
435 // host->hostname is "foo.other.com" and host->hostname_local is "foo"
436 // name might resemble to host->hostname_local
437 if (host->local_hostname_different &&
438 is_similar_hostname(host->hostname_local, name)) return TRUE;
439 // name might be an IP address or a DNS alias
440 IPAddress *ip_addr = IPAddress::create_addr(nh.get_family());
441 if (ip_addr->set_addr(name)) {
442 // check if IP addresses match
443 if (*ip_addr == *(host->ip_addr)) {
444 delete ip_addr;
445 return TRUE;
446 }
447 // try to handle such strange situations when the local hostname is
448 // mapped to a loopback address by /etc/hosts
449 // (i.e. host->ip_addr contains 127.x.y.z)
450 // but the given name contains the real IP address of the host
451 const char *canonical_name = ip_addr->get_host_str();
452 if (is_similar_hostname(host->hostname, canonical_name)) {
453 delete ip_addr;
454 return TRUE;
455 }
456 if (host->local_hostname_different &&
457 is_similar_hostname(host->hostname_local, canonical_name)) {
458 delete ip_addr;
459 return TRUE;
460 }
461 }
462 delete ip_addr;
463 return FALSE;
464 }
465
466 boolean MainController::member_of_group(const host_struct *host,
467 const host_group_struct *group)
468 {
469 if (group->has_all_hosts) return TRUE;
470 for (int i = 0; ; i++) {
471 const char *member_name = get_string_from_set(&group->host_members, i);
472 if (member_name != NULL) {
473 if (host_has_name(host, member_name)) return TRUE;
474 } else if (i == 0) {
475 // empty group: the group name is considered as a hostname
476 return host_has_name(host, group->group_name);
477 } else {
478 // no more members
479 break;
480 }
481 }
482 return FALSE;
483 }
484
485 void MainController::add_allowed_components(host_struct *host)
486 {
487 init_string_set(&host->allowed_components);
488 host->all_components_allowed = FALSE;
489 for (int i = 0; i < n_host_groups; i++) {
490 host_group_struct *group = host_groups + i;
491 if (!member_of_group(host, group)) continue;
492 for (int j = 0; ; j++) {
493 const char *component_id =
494 get_string_from_set(&group->assigned_components, j);
495 if (component_id == NULL) break;
496 add_string_to_set(&host->allowed_components, component_id);
497 }
498 if (group->has_all_components) host->all_components_allowed = TRUE;
499 }
500 }
501
502 host_struct *MainController::choose_ptc_location(const char *component_type,
503 const char *component_name, const char *component_location)
504 {
505 host_struct *best_candidate = NULL;
506 int load_on_best_candidate = 0;
507 boolean has_constraint =
508 set_has_string(&assigned_components, component_type) ||
509 set_has_string(&assigned_components, component_name);
510 host_group_struct *group;
511 if (component_location != NULL)
512 group = lookup_host_group(component_location);
513 else group = NULL;
514 for (int i = 0; i < n_hosts; i++) {
515 host_struct *host = hosts[i];
516 if (host->hc_state != HC_ACTIVE) continue;
517 if (best_candidate != NULL &&
518 host->n_active_components >= load_on_best_candidate) continue;
519 if (component_location != NULL) {
520 // the explicit location has precedence over the constraints
521 if (group != NULL) {
522 if (!member_of_group(host, group)) continue;
523 } else {
524 if (!host_has_name(host, component_location)) continue;
525 }
526 } else if (has_constraint) {
527 if (!set_has_string(&host->allowed_components, component_type) &&
528 !set_has_string(&host->allowed_components, component_name))
529 continue;
530 } else if (all_components_assigned) {
531 if (!host->all_components_allowed) continue;
532 }
533 best_candidate = host;
534 load_on_best_candidate = host->n_active_components;
535 }
536 return best_candidate;
537 }
538
539 int MainController::n_hosts;
540 host_struct **MainController::hosts;
541
542 host_struct *MainController::add_new_host(unknown_connection *conn)
543 {
544 Text_Buf *text_buf = conn->text_buf;
545 int fd = conn->fd;
546
547 host_struct *new_host = new host_struct;
548
549 new_host->ip_addr = conn->ip_addr;
550 new_host->hostname = mcopystr(new_host->ip_addr->get_host_str());
551 new_host->hostname_local = text_buf->pull_string();
552 new_host->machine_type = text_buf->pull_string();
553 new_host->system_name = text_buf->pull_string();
554 new_host->system_release = text_buf->pull_string();
555 new_host->system_version = text_buf->pull_string();
556 for (int i = 0; i < TRANSPORT_NUM; i++)
557 new_host->transport_supported[i] = FALSE;
558 int n_supported_transports = text_buf->pull_int().get_val();
559 for (int i = 0; i < n_supported_transports; i++) {
560 int transport_type = text_buf->pull_int().get_val();
561 if (transport_type >= 0 && transport_type < TRANSPORT_NUM) {
562 if (new_host->transport_supported[transport_type]) {
563 send_error(fd, "Malformed VERSION message was received: "
564 "Transport type %s was specified more than once.",
565 get_transport_name((transport_type_enum)transport_type));
566 } else new_host->transport_supported[transport_type] = TRUE;
567 } else {
568 send_error(fd, "Malformed VERSION message was received: "
569 "Transport type code %d is invalid.", transport_type);
570 }
571 }
572 if (!new_host->transport_supported[TRANSPORT_LOCAL]) {
573 send_error(fd, "Malformed VERSION message was received: "
574 "Transport type %s must be supported anyway.",
575 get_transport_name(TRANSPORT_LOCAL));
576 }
577 if (!new_host->transport_supported[TRANSPORT_INET_STREAM]) {
578 send_error(fd, "Malformed VERSION message was received: "
579 "Transport type %s must be supported anyway.",
580 get_transport_name(TRANSPORT_INET_STREAM));
581 }
582 new_host->log_source = mprintf("HC@%s", new_host->hostname_local);
583 new_host->hc_state = HC_IDLE;
584 new_host->hc_fd = fd;
585 new_host->text_buf = text_buf;
586 new_host->n_components = 0;
587 new_host->components = NULL;
588 // in most cases hostname and hostname_local are similar ("foo.bar.com" vs.
589 // "foo") and it is enough to compare only the (fully qualified) hostname
590 // when evaluating PTC location constraints
591 new_host->local_hostname_different =
592 !is_similar_hostname(new_host->hostname, new_host->hostname_local);
593 add_allowed_components(new_host);
594 new_host->n_active_components = 0;
595
596 text_buf->cut_message();
597
598 delete_unknown_connection(conn);
599
600 n_hosts++;
601 hosts = (host_struct**)Realloc(hosts, n_hosts * sizeof(*hosts));
602 hosts[n_hosts - 1] = new_host;
603
604 fd_table[fd].fd_type = FD_HC;
605 fd_table[fd].host_ptr = new_host;
606
607 notify("New HC connected from %s [%s]. %s: %s %s on %s.",
608 new_host->hostname, new_host->ip_addr->get_addr_str(),
609 new_host->hostname_local, new_host->system_name,
610 new_host->system_release, new_host->machine_type);
611
612 return new_host;
613 }
614
615 void MainController::close_hc_connection(host_struct *hc)
616 {
617 if (hc->hc_state != HC_DOWN) {
618 remove_poll_fd(hc->hc_fd);
619 close(hc->hc_fd);
620 remove_fd_from_table(hc->hc_fd);
621 hc->hc_fd = -1;
622 delete hc->text_buf;
623 hc->text_buf = NULL;
624 hc->hc_state = HC_DOWN;
625 enable_server_fd();
626 }
627 }
628
629 boolean MainController::is_hc_in_state(hc_state_enum checked_state)
630 {
631 for (int i = 0; i < n_hosts; i++)
632 if (hosts[i]->hc_state == checked_state) return TRUE;
633 return FALSE;
634 }
635
636 boolean MainController::all_hc_in_state(hc_state_enum checked_state)
637 {
638 for (int i = 0; i < n_hosts; i++)
639 if (hosts[i]->hc_state != checked_state) return FALSE;
640 return TRUE;
641 }
642
643 void MainController::configure_host(host_struct *host, boolean should_notify)
644 {
645 if(config_str == NULL)
646 fatal_error("MainController::configure_host: no config file");
647 hc_state_enum next_state = HC_CONFIGURING;
648 switch(host->hc_state) {
649 case HC_CONFIGURING:
650 case HC_CONFIGURING_OVERLOADED:
651 case HC_EXITING:
652 fatal_error("MainController::configure_host:"
653 " host %s is in wrong state.",
654 host->hostname);
655 break;
656 case HC_DOWN:
657 break;
658 case HC_OVERLOADED:
659 next_state = HC_CONFIGURING_OVERLOADED;
660 // no break
661 default:
662 host->hc_state = next_state;
663 if (should_notify) {
664 notify("Downloading configuration file to HC on host %s.",
665 host->hostname);
666 }
667 send_configure(host, config_str);
668 }
669 }
670
671 void MainController::check_all_hc_configured()
672 {
673 if (is_hc_in_state(HC_CONFIGURING) ||
674 is_hc_in_state(HC_CONFIGURING_OVERLOADED)) return;
675 if (is_hc_in_state(HC_IDLE)) {
676 error("There were errors during configuring HCs.");
677 mc_state = MC_HC_CONNECTED;
678 } else if (is_hc_in_state(HC_ACTIVE) || is_hc_in_state(HC_OVERLOADED)) {
679 notify("Configuration file was processed on all HCs.");
680 mc_state = MC_ACTIVE;
681 } else {
682 error("There is no HC connection after processing the configuration "
683 "file.");
684 mc_state = MC_LISTENING;
685 }
686 }
687
688 void MainController::add_component_to_host(host_struct *host,
689 component_struct *comp)
690 {
691 if (comp->comp_ref == MTC_COMPREF)
692 comp->log_source = mprintf("MTC@%s", host->hostname_local);
693 else if (comp->comp_name != NULL)
694 comp->log_source = mprintf("%s(%d)@%s", comp->comp_name,
695 comp->comp_ref, host->hostname_local);
696 else comp->log_source = mprintf("%d@%s", comp->comp_ref,
697 host->hostname_local);
698 comp->comp_location = host;
699 int i;
700 for (i = host->n_components; i > 0; i--) {
701 if (host->components[i - 1] < comp->comp_ref) break;
702 else if (host->components[i - 1] == comp->comp_ref) return;
703 }
704 host->components = (component*)Realloc(host->components,
705 (host->n_components + 1) * sizeof(component));
706 memmove(host->components + i + 1, host->components + i,
707 (host->n_components - i) * sizeof(component));
708 host->components[i] = comp->comp_ref;
709 host->n_components++;
710 }
711
712 void MainController::remove_component_from_host(component_struct *comp)
713 {
714 Free(comp->log_source);
715 comp->log_source = NULL;
716 host_struct *host = comp->comp_location;
717 if (host != NULL) {
718 component comp_ref = comp->comp_ref;
719 int i;
720 for (i = host->n_components - 1; i >= 0; i--) {
721 if (host->components[i] == comp_ref) break;
722 else if (host->components[i] < comp_ref) return;
723 }
724 if (i < 0) return;
725 host->n_components--;
726 memmove(host->components + i, host->components + i + 1,
727 (host->n_components - i) * sizeof(component));
728 host->components = (component*)Realloc(host->components,
729 host->n_components * sizeof(component));
730 }
731 }
732
733 boolean MainController::version_known;
734 int MainController::n_modules;
735 module_version_info *MainController::modules;
736
737 #ifdef TTCN3_BUILDNUMBER
738 #define TTCN3_BUILDNUMBER_SAFE TTCN3_BUILDNUMBER
739 #else
740 #define TTCN3_BUILDNUMBER_SAFE 0
741 #endif
742
743
744 boolean MainController::check_version(unknown_connection *conn)
745 {
746 Text_Buf& text_buf = *conn->text_buf;
747 int version_major = text_buf.pull_int().get_val();
748 int version_minor = text_buf.pull_int().get_val();
749 int version_patchlevel = text_buf.pull_int().get_val();
750 if (version_major != TTCN3_MAJOR || version_minor != TTCN3_MINOR ||
751 version_patchlevel != TTCN3_PATCHLEVEL) {
752 send_error(conn->fd, "Version mismatch: The TTCN-3 Main Controller has "
753 "version " PRODUCT_NUMBER ", but the ETS was built with version "
754 "%d.%d.pl%d.", version_major, version_minor, version_patchlevel);
755 return TRUE;
756 }
757 int version_buildnumber = text_buf.pull_int().get_val();
758 if (version_buildnumber != TTCN3_BUILDNUMBER_SAFE) {
759 if (version_buildnumber > 0) send_error(conn->fd, "Build number "
760 "mismatch: The TTCN-3 Main Controller has version " PRODUCT_NUMBER
761 ", but the ETS was built with %d.%d.pre%d build %d.",
762 version_major, version_minor, version_patchlevel,
763 version_buildnumber);
764 else send_error(conn->fd, "Build number mismatch: The TTCN-3 Main "
765 "Controller has version " PRODUCT_NUMBER ", but the ETS was built "
766 "with %d.%d.pl%d.", version_major, version_minor,
767 version_patchlevel);
768 return TRUE;
769 }
770 if (version_known) {
771 int new_n_modules = text_buf.pull_int().get_val();
772 if (n_modules != new_n_modules) {
773 send_error(conn->fd, "The number of modules in this ETS (%d) "
774 "differs from the number of modules in the firstly connected "
775 "ETS (%d).", new_n_modules, n_modules);
776 return TRUE;
777 }
778 for (int i = 0; i < n_modules; i++) {
779 char *module_name = text_buf.pull_string();
780 if (strcmp(module_name, modules[i].module_name)) {
781 send_error(conn->fd, "The module number %d in this ETS (%s) "
782 "has different name than in the firstly connected ETS (%s).",
783 i, module_name, modules[i].module_name);
784 delete [] module_name;
785 return TRUE;
786 }
787 boolean checksum_differs = FALSE;
788 int checksum_length = text_buf.pull_int().get_val();
789 unsigned char *module_checksum;
790 if (checksum_length != 0) {
791 module_checksum = new unsigned char[checksum_length];
792 text_buf.pull_raw(checksum_length, module_checksum);
793 } else module_checksum = NULL;
794 if (checksum_length != modules[i].checksum_length ||
795 memcmp(module_checksum, modules[i].module_checksum,
796 checksum_length)) checksum_differs = TRUE;
797 delete [] module_checksum;
798 if (checksum_differs) {
799 send_error(conn->fd, "The checksum of module %s in this ETS "
800 "is different than that of the firstly connected ETS.",
801 module_name);
802 }
803 delete [] module_name;
804 if (checksum_differs) return TRUE;
805 }
806 } else {
807 n_modules = text_buf.pull_int().get_val();
808 modules = new module_version_info[n_modules];
809 for (int i = 0; i < n_modules; i++) {
810 modules[i].module_name = text_buf.pull_string();
811 modules[i].checksum_length = text_buf.pull_int().get_val();
812 if (modules[i].checksum_length > 0) {
813 modules[i].module_checksum =
814 new unsigned char[modules[i].checksum_length];
815 text_buf.pull_raw(modules[i].checksum_length,
816 modules[i].module_checksum);
817 } else modules[i].module_checksum = NULL;
818 }
819 version_known = TRUE;
820 }
821 return FALSE;
822 }
823
824 int MainController::n_components, MainController::n_active_ptcs,
825 MainController::max_ptcs;
826 component_struct **MainController::components;
827 component_struct *MainController::mtc, *MainController::system;
828 component MainController::next_comp_ref, MainController::tc_first_comp_ref;
829
830 boolean MainController::any_component_done_requested,
831 MainController::any_component_done_sent,
832 MainController::all_component_done_requested,
833 MainController::any_component_killed_requested,
834 MainController::all_component_killed_requested;
835
836 void MainController::add_component(component_struct *comp)
837 {
838 component comp_ref = comp->comp_ref;
839 if (lookup_component(comp_ref) != NULL)
840 fatal_error("MainController::add_component: duplicate "
841 "component reference %d.", comp_ref);
842 if (n_components <= comp_ref) {
843 components = (component_struct**)Realloc(components, (comp_ref + 1) *
844 sizeof(component_struct*));
845 for (int i = n_components; i < comp_ref; i++) components[i] = NULL;
846 n_components = comp_ref + 1;
847 }
848 components[comp_ref] = comp;
849 }
850
851 component_struct *MainController::lookup_component(component comp_ref)
852 {
853 if (comp_ref >= 0 && comp_ref < n_components) return components[comp_ref];
854 else return NULL;
855 }
856
857 void MainController::destroy_all_components()
858 {
859 for (component i = 0; i < n_components; i++) {
860 component_struct *comp = components[i];
861 if (comp != NULL) {
862 close_tc_connection(comp);
863 remove_component_from_host(comp);
864 free_qualified_name(&comp->comp_type);
865 delete [] comp->comp_name;
866 free_qualified_name(&comp->tc_fn_name);
867 delete [] comp->return_type;
868 Free(comp->return_value);
869 if (comp->verdict_reason != NULL) {
870 delete [] comp->verdict_reason;
871 comp->verdict_reason = NULL;
872 }
873 switch (comp->tc_state) {
874 case TC_INITIAL:
875 delete [] comp->initial.location_str;
876 break;
877 case PTC_STARTING:
878 Free(comp->starting.arguments_ptr);
879 free_requestors(&comp->starting.cancel_done_sent_to);
880 break;
881 case TC_STOPPING:
882 case PTC_STOPPING_KILLING:
883 case PTC_KILLING:
884 free_requestors(&comp->stopping_killing.stop_requestors);
885 free_requestors(&comp->stopping_killing.kill_requestors);
886 default:
887 break;
888 }
889 free_requestors(&comp->done_requestors);
890 free_requestors(&comp->killed_requestors);
891 free_requestors(&comp->cancel_done_sent_for);
892 remove_all_connections(i);
893 delete comp;
894 }
895 }
896 Free(components);
897 components = NULL;
898 n_components = 0;
899 n_active_ptcs = 0;
900 mtc = NULL;
901 system = NULL;
902
903 for (int i = 0; i < n_hosts; i++) hosts[i]->n_active_components = 0;
904
905 next_comp_ref = FIRST_PTC_COMPREF;
906
907 any_component_done_requested = FALSE;
908 any_component_done_sent = FALSE;
909 all_component_done_requested = FALSE;
910 any_component_killed_requested = FALSE;
911 all_component_killed_requested = FALSE;
912 }
913
914 void MainController::close_tc_connection(component_struct *comp)
915 {
916 if (comp->tc_fd >= 0) {
917 remove_poll_fd(comp->tc_fd);
918 close(comp->tc_fd);
919 remove_fd_from_table(comp->tc_fd);
920 comp->tc_fd = -1;
921 delete comp->text_buf;
922 comp->text_buf = NULL;
923 enable_server_fd();
924 }
925 if (comp->kill_timer != NULL) {
926 cancel_timer(comp->kill_timer);
927 comp->kill_timer = NULL;
928 }
929 }
930
931 boolean MainController::stop_after_tc, MainController::stop_requested;
932
933 boolean MainController::ready_to_finish_testcase()
934 {
935 for (component i = tc_first_comp_ref; i < n_components; i++) {
936 switch (components[i]->tc_state) {
937 case TC_EXITED:
938 case PTC_STALE:
939 break;
940 default:
941 return FALSE;
942 }
943 }
944 return TRUE;
945 }
946
947 void MainController::finish_testcase()
948 {
949 if (stop_requested) {
950 send_ptc_verdict(FALSE);
951 send_stop(mtc);
952 mtc->tc_state = MTC_CONTROLPART;
953 mtc->stop_requested = TRUE;
954 start_kill_timer(mtc);
955 mc_state = MC_EXECUTING_CONTROL;
956 } else if (stop_after_tc) {
957 send_ptc_verdict(FALSE);
958 mtc->tc_state = MTC_PAUSED;
959 mc_state = MC_PAUSED;
960 notify("Execution has been paused.");
961 } else {
962 send_ptc_verdict(TRUE);
963 mtc->tc_state = MTC_CONTROLPART;
964 mc_state = MC_EXECUTING_CONTROL;
965 }
966
967 for (component i = tc_first_comp_ref; i < n_components; i++) {
968 components[i]->tc_state = PTC_STALE;
969 }
970 mtc->local_verdict = NONE;
971 free_qualified_name(&mtc->comp_type);
972 free_qualified_name(&mtc->tc_fn_name);
973 free_qualified_name(&system->comp_type);
974 }
975
976 boolean MainController::message_expected(component_struct *from,
977 const char *message_name)
978 {
979 switch (mc_state) {
980 case MC_EXECUTING_TESTCASE:
981 switch (mtc->tc_state) {
982 case MTC_ALL_COMPONENT_STOP:
983 case MTC_ALL_COMPONENT_KILL:
984 // silently ignore
985 return FALSE;
986 default:
987 return TRUE;
988 }
989 case MC_TERMINATING_TESTCASE:
990 // silently ignore
991 return FALSE;
992 default:
993 send_error(from->tc_fd, "Unexpected message %s was received.",
994 message_name);
995 return FALSE;
996 }
997 }
998
999 boolean MainController::request_allowed(component_struct *from,
1000 const char *message_name)
1001 {
1002 if (!message_expected(from, message_name)) return FALSE;
1003
1004 switch (from->tc_state) {
1005 case MTC_TESTCASE:
1006 if (from == mtc) return TRUE;
1007 else break;
1008 case PTC_FUNCTION:
1009 if (from != mtc) return TRUE;
1010 else break;
1011 case TC_STOPPING:
1012 case PTC_STOPPING_KILLING:
1013 case PTC_KILLING:
1014 // silently ignore
1015 return FALSE;
1016 default:
1017 break;
1018 }
1019 send_error(from->tc_fd, "The sender of message %s is in "
1020 "unexpected state.", message_name);
1021 return FALSE;
1022 }
1023
1024 boolean MainController::valid_endpoint(component component_reference,
1025 boolean new_connection, component_struct *requestor, const char *operation)
1026 {
1027 switch (component_reference) {
1028 case NULL_COMPREF:
1029 send_error(requestor->tc_fd, "The %s operation refers to the null "
1030 "component reference.", operation);
1031 return FALSE;
1032 case SYSTEM_COMPREF:
1033 send_error(requestor->tc_fd, "The %s operation refers to the system "
1034 "component reference.", operation);
1035 return FALSE;
1036 case ANY_COMPREF:
1037 send_error(requestor->tc_fd, "The %s operation refers to "
1038 "'any component'.", operation);
1039 return FALSE;
1040 case ALL_COMPREF:
1041 send_error(requestor->tc_fd, "The %s operation refers to "
1042 "'all component'.", operation);
1043 return FALSE;
1044 default:
1045 break;
1046 }
1047 component_struct *comp = lookup_component(component_reference);
1048 if (comp == NULL) {
1049 send_error(requestor->tc_fd, "The %s operation refers to "
1050 "invalid component reference %d.", operation,
1051 component_reference);
1052 return FALSE;
1053 }
1054 switch (comp->tc_state) {
1055 case TC_IDLE:
1056 case TC_CREATE:
1057 case TC_START:
1058 case TC_STOP:
1059 case TC_KILL:
1060 case TC_CONNECT:
1061 case TC_DISCONNECT:
1062 case TC_MAP:
1063 case TC_UNMAP:
1064 case TC_STOPPING:
1065 case MTC_TESTCASE:
1066 case PTC_FUNCTION:
1067 case PTC_STARTING:
1068 case PTC_STOPPED:
1069 return TRUE;
1070 case PTC_KILLING:
1071 case PTC_STOPPING_KILLING:
1072 if (new_connection) {
1073 send_error(requestor->tc_fd, "The %s operation refers to test "
1074 "component with component reference %d, which is currently "
1075 "being terminated.", operation, component_reference);
1076 return FALSE;
1077 } else return TRUE;
1078 case TC_EXITING:
1079 case TC_EXITED:
1080 if (new_connection) {
1081 send_error(requestor->tc_fd, "The %s operation refers to test "
1082 "component with component reference %d, which has already "
1083 "terminated.", operation, component_reference);
1084 return FALSE;
1085 } else return TRUE;
1086 case PTC_STALE:
1087 send_error(requestor->tc_fd, "The %s operation refers to component "
1088 "reference %d, which belongs to an earlier test case.",
1089 operation, component_reference);
1090 return FALSE;
1091 default:
1092 send_error(requestor->tc_fd, "The %s operation refers to component "
1093 "reference %d, which is in invalid state.",
1094 operation, component_reference);
1095 error("Test component with component reference %d is in invalid state "
1096 "when a %s operation was requested on a port of it.",
1097 component_reference, operation);
1098 return FALSE;
1099 }
1100 }
1101
1102 void MainController::destroy_connection(port_connection *conn,
1103 component_struct *tc)
1104 {
1105 switch (conn->conn_state) {
1106 case CONN_LISTENING:
1107 case CONN_CONNECTING:
1108 if (conn->transport_type != TRANSPORT_LOCAL &&
1109 conn->head.comp_ref != tc->comp_ref) {
1110 // shut down the server side if the client has terminated
1111 send_disconnect_to_server(conn);
1112 }
1113 send_error_to_connect_requestors(conn, "test component %d has "
1114 "terminated during connection setup.", tc->comp_ref);
1115 break;
1116 case CONN_CONNECTED:
1117 break;
1118 case CONN_DISCONNECTING:
1119 send_disconnect_ack_to_requestors(conn);
1120 break;
1121 default:
1122 error("The port connection %d:%s - %d:%s is in invalid state when "
1123 "test component %d has terminated.", conn->head.comp_ref,
1124 conn->head.port_name, conn->tail.comp_ref, conn->tail.port_name,
1125 tc->comp_ref);
1126 }
1127 remove_connection(conn);
1128 }
1129
1130 void MainController::destroy_mapping(port_connection *conn)
1131 {
1132 component tc_compref;
1133 const char *tc_port, *system_port;
1134 if (conn->head.comp_ref == SYSTEM_COMPREF) {
1135 tc_compref = conn->tail.comp_ref;
1136 tc_port = conn->tail.port_name;
1137 system_port = conn->head.port_name;
1138 } else {
1139 tc_compref = conn->head.comp_ref;
1140 tc_port = conn->head.port_name;
1141 system_port = conn->tail.port_name;
1142 }
1143 switch (conn->conn_state) {
1144 case CONN_UNMAPPING:
1145 for (int i = 0; ; i++) {
1146 component_struct *comp = get_requestor(&conn->requestors, i);
1147 if (comp == NULL) break;
1148 if (comp->tc_state == TC_UNMAP) {
1149 send_unmap_ack(comp);
1150 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
1151 else comp->tc_state = PTC_FUNCTION;
1152 }
1153 }
1154 break;
1155 case CONN_MAPPING:
1156 for (int i = 0; ; i++) {
1157 component_struct *comp = get_requestor(&conn->requestors, i);
1158 if (comp == NULL) break;
1159 if (comp->tc_state == TC_MAP) {
1160 send_error(comp->tc_fd, "Establishment of port mapping "
1161 "%d:%s - system:%s failed because the test component "
1162 "endpoint has terminated.", tc_compref, tc_port,
1163 system_port);
1164 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
1165 else comp->tc_state = PTC_FUNCTION;
1166 }
1167 }
1168 default:
1169 break;
1170 }
1171 remove_connection(conn);
1172 }
1173
1174 boolean MainController::stop_all_components()
1175 {
1176 boolean ready_for_ack = TRUE;
1177 for (component i = tc_first_comp_ref; i < n_components; i++) {
1178 component_struct *tc = components[i];
1179 switch (tc->tc_state) {
1180 case TC_INITIAL:
1181 // we do not have to termiate the PTC (and wait for the control
1182 // connection) if it is alive
1183 if (!tc->is_alive) ready_for_ack = FALSE;
1184 break;
1185 case TC_IDLE:
1186 // do nothing if the component is alive
1187 if (!tc->is_alive) {
1188 send_kill(tc);
1189 tc->tc_state = PTC_KILLING;
1190 tc->stop_requested = TRUE;
1191 init_requestors(&tc->stopping_killing.stop_requestors, NULL);
1192 init_requestors(&tc->stopping_killing.kill_requestors, NULL);
1193 start_kill_timer(tc);
1194 ready_for_ack = FALSE;
1195 }
1196 break;
1197 case TC_CREATE:
1198 case TC_START:
1199 case TC_STOP:
1200 case TC_KILL:
1201 case TC_CONNECT:
1202 case TC_DISCONNECT:
1203 case TC_MAP:
1204 case TC_UNMAP:
1205 case PTC_FUNCTION:
1206 // the PTC is executing behaviour
1207 if (tc->is_alive) {
1208 send_stop(tc);
1209 tc->tc_state = TC_STOPPING;
1210 } else {
1211 // STOP is never sent to non-alive PTCs
1212 send_kill(tc);
1213 tc->tc_state = PTC_STOPPING_KILLING;
1214 }
1215 tc->stop_requested = TRUE;
1216 init_requestors(&tc->stopping_killing.stop_requestors, NULL);
1217 init_requestors(&tc->stopping_killing.kill_requestors, NULL);
1218 start_kill_timer(tc);
1219 ready_for_ack = FALSE;
1220 break;
1221 case PTC_STARTING:
1222 // do nothing, just put it back to STOPPED state
1223 free_qualified_name(&tc->tc_fn_name);
1224 Free(tc->starting.arguments_ptr);
1225 free_requestors(&tc->starting.cancel_done_sent_to);
1226 tc->tc_state = PTC_STOPPED;
1227 break;
1228 case TC_STOPPING:
1229 case PTC_STOPPING_KILLING:
1230 free_requestors(&tc->stopping_killing.stop_requestors);
1231 free_requestors(&tc->stopping_killing.kill_requestors);
1232 ready_for_ack = FALSE;
1233 break;
1234 case PTC_KILLING:
1235 free_requestors(&tc->stopping_killing.stop_requestors);
1236 free_requestors(&tc->stopping_killing.kill_requestors);
1237 // we have to wait only if the PTC is non-alive
1238 if (!tc->is_alive) ready_for_ack = FALSE;
1239 break;
1240 case PTC_STOPPED:
1241 case TC_EXITING:
1242 case TC_EXITED:
1243 case PTC_STALE:
1244 break;
1245 default:
1246 error("Test Component %d is in invalid state when stopping all "
1247 "components.", tc->comp_ref);
1248 }
1249 // only mtc is preserved in done_requestors and killed_requestors
1250 boolean mtc_requested_done = has_requestor(&tc->done_requestors, mtc);
1251 free_requestors(&tc->done_requestors);
1252 if (mtc_requested_done) add_requestor(&tc->done_requestors, mtc);
1253 boolean mtc_requested_killed = has_requestor(&tc->killed_requestors,
1254 mtc);
1255 free_requestors(&tc->killed_requestors);
1256 if (mtc_requested_killed) add_requestor(&tc->killed_requestors, mtc);
1257 free_requestors(&tc->cancel_done_sent_for);
1258 }
1259 return ready_for_ack;
1260
1261 }
1262
1263 void MainController::check_all_component_stop()
1264 {
1265 // MTC has requested 'all component.stop'
1266 // we have to send acknowledgement to MTC only
1267 boolean ready_for_ack = TRUE;
1268 for (component i = tc_first_comp_ref; i < n_components; i++) {
1269 component_struct *comp = components[i];
1270 switch (comp->tc_state) {
1271 case TC_INITIAL:
1272 case PTC_KILLING:
1273 if (!comp->is_alive) ready_for_ack = FALSE;
1274 break;
1275 case TC_STOPPING:
1276 case PTC_STOPPING_KILLING:
1277 ready_for_ack = FALSE;
1278 break;
1279 case TC_EXITING:
1280 case TC_EXITED:
1281 case PTC_STOPPED:
1282 case PTC_STALE:
1283 break;
1284 case TC_IDLE:
1285 // only alive components can be in idle state
1286 if (comp->is_alive) break;
1287 default:
1288 error("PTC %d is in invalid state when performing "
1289 "'all component.stop' operation.", comp->comp_ref);
1290 }
1291 if (!ready_for_ack) break;
1292 }
1293 if (ready_for_ack) {
1294 send_stop_ack(mtc);
1295 mtc->tc_state = MTC_TESTCASE;
1296 }
1297 }
1298
1299 void MainController::send_stop_ack_to_requestors(component_struct *tc)
1300 {
1301 for (int i = 0; ; i++) {
1302 component_struct *requestor =
1303 get_requestor(&tc->stopping_killing.stop_requestors, i);
1304 if (requestor == NULL) break;
1305 if (requestor->tc_state == TC_STOP) {
1306 send_stop_ack(requestor);
1307 if (requestor == mtc) requestor->tc_state = MTC_TESTCASE;
1308 else requestor->tc_state = PTC_FUNCTION;
1309 }
1310 }
1311 free_requestors(&tc->stopping_killing.stop_requestors);
1312 }
1313
1314 boolean MainController::kill_all_components(boolean testcase_ends)
1315 {
1316 boolean ready_for_ack = TRUE;
1317 for (component i = tc_first_comp_ref; i < n_components; i++) {
1318 component_struct *tc = components[i];
1319 boolean is_inactive = FALSE;
1320 switch (tc->tc_state) {
1321 case TC_INITIAL:
1322 // the PTC does not have an identified control connection yet
1323 ready_for_ack = FALSE;
1324 break;
1325 case PTC_STARTING:
1326 free_qualified_name(&tc->tc_fn_name);
1327 Free(tc->starting.arguments_ptr);
1328 free_requestors(&tc->starting.cancel_done_sent_to);
1329 // no break
1330 case TC_IDLE:
1331 case PTC_STOPPED:
1332 is_inactive = TRUE;
1333 // no break
1334 case TC_CREATE:
1335 case TC_START:
1336 case TC_STOP:
1337 case TC_KILL:
1338 case TC_CONNECT:
1339 case TC_DISCONNECT:
1340 case TC_MAP:
1341 case TC_UNMAP:
1342 case PTC_FUNCTION:
1343 send_kill(tc);
1344 if (is_inactive) {
1345 // the PTC was inactive
1346 tc->tc_state = PTC_KILLING;
1347 if (!tc->is_alive) tc->stop_requested = TRUE;
1348 } else {
1349 // the PTC was active
1350 tc->tc_state = PTC_STOPPING_KILLING;
1351 tc->stop_requested = TRUE;
1352 }
1353 init_requestors(&tc->stopping_killing.stop_requestors, NULL);
1354 init_requestors(&tc->stopping_killing.kill_requestors, NULL);
1355 start_kill_timer(tc);
1356 ready_for_ack = FALSE;
1357 break;
1358 case TC_STOPPING:
1359 send_kill(tc);
1360 tc->tc_state = PTC_STOPPING_KILLING;
1361 if (tc->kill_timer != NULL) cancel_timer(tc->kill_timer);
1362 start_kill_timer(tc);
1363 // no break
1364 case PTC_KILLING:
1365 case PTC_STOPPING_KILLING:
1366 free_requestors(&tc->stopping_killing.stop_requestors);
1367 free_requestors(&tc->stopping_killing.kill_requestors);
1368 ready_for_ack = FALSE;
1369 break;
1370 case TC_EXITING:
1371 if (testcase_ends) ready_for_ack = FALSE;
1372 case TC_EXITED:
1373 case PTC_STALE:
1374 break;
1375 default:
1376 error("Test Component %d is in invalid state when killing all "
1377 "components.", tc->comp_ref);
1378 }
1379 if (testcase_ends) {
1380 free_requestors(&tc->done_requestors);
1381 free_requestors(&tc->killed_requestors);
1382 } else {
1383 // only mtc is preserved in done_requestors and killed_requestors
1384 boolean mtc_requested_done = has_requestor(&tc->done_requestors,
1385 mtc);
1386 free_requestors(&tc->done_requestors);
1387 if (mtc_requested_done) add_requestor(&tc->done_requestors, mtc);
1388 boolean mtc_requested_killed = has_requestor(&tc->killed_requestors,
1389 mtc);
1390 free_requestors(&tc->killed_requestors);
1391 if (mtc_requested_killed)
1392 add_requestor(&tc->killed_requestors, mtc);
1393 }
1394 free_requestors(&tc->cancel_done_sent_for);
1395 }
1396 return ready_for_ack;
1397 }
1398
1399 void MainController::check_all_component_kill()
1400 {
1401 // MTC has requested 'all component.kill'
1402 // we have to send acknowledgement to MTC only
1403 boolean ready_for_ack = TRUE;
1404 for (component i = tc_first_comp_ref; i < n_components; i++) {
1405 component_struct *comp = components[i];
1406 switch (comp->tc_state) {
1407 case TC_INITIAL:
1408 case PTC_STOPPING_KILLING:
1409 case PTC_KILLING:
1410 ready_for_ack = FALSE;
1411 case TC_EXITING:
1412 case TC_EXITED:
1413 case PTC_STALE:
1414 break;
1415 default:
1416 error("PTC %d is in invalid state when performing "
1417 "'all component.kill' operation.", comp->comp_ref);
1418 }
1419 if (!ready_for_ack) break;
1420 }
1421 if (ready_for_ack) {
1422 send_kill_ack(mtc);
1423 mtc->tc_state = MTC_TESTCASE;
1424 }
1425 }
1426
1427 void MainController::send_kill_ack_to_requestors(component_struct *tc)
1428 {
1429 for (int i = 0; ; i++) {
1430 component_struct *requestor =
1431 get_requestor(&tc->stopping_killing.kill_requestors, i);
1432 if (requestor == NULL) break;
1433 if (requestor->tc_state == TC_KILL) {
1434 send_kill_ack(requestor);
1435 if (requestor == mtc) requestor->tc_state = MTC_TESTCASE;
1436 else requestor->tc_state = PTC_FUNCTION;
1437 }
1438 }
1439 free_requestors(&tc->stopping_killing.kill_requestors);
1440 }
1441
1442 void MainController::send_component_status_to_requestor(component_struct *tc,
1443 component_struct *requestor, boolean done_status, boolean killed_status)
1444 {
1445 switch (requestor->tc_state) {
1446 case PTC_FUNCTION:
1447 case TC_CREATE:
1448 case TC_START:
1449 case TC_STOP:
1450 case TC_KILL:
1451 case TC_CONNECT:
1452 case TC_DISCONNECT:
1453 case TC_MAP:
1454 case TC_UNMAP:
1455 case TC_STOPPING:
1456 case PTC_STOPPED:
1457 case PTC_STARTING:
1458 if (done_status) {
1459 send_component_status_ptc(requestor, tc->comp_ref, TRUE,
1460 killed_status, tc->return_type, tc->return_value_len,
1461 tc->return_value);
1462 } else {
1463 send_component_status_ptc(requestor, tc->comp_ref, FALSE,
1464 killed_status, NULL, 0, NULL);
1465 }
1466 break;
1467 case PTC_STOPPING_KILLING:
1468 case PTC_KILLING:
1469 case TC_EXITING:
1470 case TC_EXITED:
1471 // the PTC requestor is not interested in the component status anymore
1472 break;
1473 default:
1474 error("PTC %d is in invalid state when sending out COMPONENT_STATUS "
1475 "message about PTC %d.", requestor->comp_ref, tc->comp_ref);
1476 }
1477 }
1478
1479 void MainController::component_stopped(component_struct *tc)
1480 {
1481 // checking and updating the state of tc
1482 tc_state_enum old_state = tc->tc_state;
1483 if (old_state == PTC_STOPPING_KILLING) tc->tc_state = PTC_KILLING;
1484 else {
1485 tc->tc_state = PTC_STOPPED;
1486 if (tc->kill_timer != NULL) {
1487 cancel_timer(tc->kill_timer);
1488 tc->kill_timer = NULL;
1489 }
1490 }
1491 switch (mc_state) {
1492 case MC_EXECUTING_TESTCASE:
1493 // this is the correct state
1494 break;
1495 case MC_TERMINATING_TESTCASE:
1496 // do nothing, we are waiting for the end of all PTC connections
1497 return;
1498 default:
1499 error("PTC %d stopped in invalid MC state.", tc->comp_ref);
1500 return;
1501 }
1502 if (!tc->is_alive) {
1503 send_error_str(tc->tc_fd, "Message STOPPED can only be sent by "
1504 "alive PTCs.");
1505 return;
1506 }
1507 // Note: the COMPONENT_STATUS message must be sent before STOP_ACK because
1508 // the latter may update the component status cache table to an inconsistent
1509 // state
1510 boolean send_status_to_mtc = FALSE, send_done_to_mtc = FALSE;
1511 // sending out COMPONENT_STATUS messages to PTCs
1512 for (int i = 0; ; i++) {
1513 component_struct *requestor = get_requestor(&tc->done_requestors, i);
1514 if (requestor == NULL) break;
1515 else if (requestor == mtc) {
1516 send_status_to_mtc = TRUE;
1517 send_done_to_mtc = TRUE;
1518 } else send_component_status_to_requestor(tc, requestor, TRUE, FALSE);
1519 }
1520 // do not send unsolicited 'any component.done' status
1521 if (any_component_done_requested) send_status_to_mtc = TRUE;
1522 boolean all_done_checked = FALSE, all_done_result = FALSE;
1523 if (all_component_done_requested) {
1524 all_done_checked = TRUE;
1525 all_done_result = !is_any_component_running();
1526 if (all_done_result) send_status_to_mtc = TRUE;
1527 }
1528 if (send_status_to_mtc) {
1529 if (!all_done_checked) all_done_result = !is_any_component_running();
1530 if (send_done_to_mtc) {
1531 // the return value was requested
1532 send_component_status_mtc(tc->comp_ref, TRUE, FALSE,
1533 any_component_done_requested, all_done_result, FALSE, FALSE,
1534 tc->return_type, tc->return_value_len, tc->return_value);
1535 } else {
1536 // the return value was not requested
1537 send_component_status_mtc(NULL_COMPREF, FALSE, FALSE,
1538 any_component_done_requested, all_done_result, FALSE, FALSE,
1539 NULL, 0, NULL);
1540 }
1541 if (any_component_done_requested) {
1542 any_component_done_requested = FALSE;
1543 any_component_done_sent = TRUE;
1544 }
1545 if (all_done_result) all_component_done_requested = FALSE;
1546 }
1547 // sending out STOP_ACK messages
1548 if (old_state != PTC_FUNCTION) {
1549 // the PTC was explicitly stopped and/or killed
1550 if (mtc->tc_state == MTC_ALL_COMPONENT_KILL) {
1551 // do nothing
1552 } else if (mtc->tc_state == MTC_ALL_COMPONENT_STOP) {
1553 check_all_component_stop();
1554 } else {
1555 send_stop_ack_to_requestors(tc);
1556 }
1557 }
1558 }
1559
1560 void MainController::component_terminated(component_struct *tc)
1561 {
1562 // the state variable of the PTC has to be updated first
1563 // because in case of 'all component.kill' or 'all component.stop'
1564 // we are walking through the states of all PTCs
1565 tc_state_enum old_state = tc->tc_state;
1566 tc->tc_state = TC_EXITING;
1567 n_active_ptcs--;
1568 tc->comp_location->n_active_components--;
1569 switch (mc_state) {
1570 case MC_EXECUTING_TESTCASE:
1571 // this is the correct state
1572 break;
1573 case MC_TERMINATING_TESTCASE:
1574 // do nothing, we are waiting for the end of all PTC connections
1575 return;
1576 default:
1577 error("PTC %d terminated in invalid MC state.", tc->comp_ref);
1578 return;
1579 }
1580 // sending out COMPONENT_STATUS messages
1581 // Notes:
1582 // - the COMPONENT_STATUS message must be sent before STOP_ACK and KILL_ACK
1583 // because the latter may update the component status cache table to an
1584 // inconsistent state
1585 // - unsolicited 'done' status and return value is never sent out
1586 // the flags below indicate whether a COMPONENT_STATUS message
1587 // (with or without the return value) has to be sent to the MTC
1588 boolean send_status_to_mtc = FALSE, send_done_to_mtc = TRUE;
1589 // first send out the COMPONENT_STATUS messages to PTCs
1590 for (int i = 0; ; i++) {
1591 component_struct *requestor = get_requestor(&tc->done_requestors, i);
1592 if (requestor == NULL) break;
1593 else if (requestor == mtc) {
1594 send_status_to_mtc = TRUE;
1595 send_done_to_mtc = TRUE;
1596 } else send_component_status_to_requestor(tc, requestor, TRUE, TRUE);
1597 }
1598 for (int i = 0; ; i++) {
1599 component_struct *requestor = get_requestor(&tc->killed_requestors, i);
1600 if (requestor == NULL) break;
1601 else if (requestor == mtc) send_status_to_mtc = TRUE;
1602 else if (!has_requestor(&tc->done_requestors, requestor)) {
1603 // do not send COMPONENT_STATUS twice to the same PTC
1604 send_component_status_to_requestor(tc, requestor, FALSE, TRUE);
1605 }
1606 }
1607 free_requestors(&tc->done_requestors);
1608 free_requestors(&tc->killed_requestors);
1609 // deciding whether to send a COMPONENT_STATUS message to MTC
1610 // 'any component.done' status can be safely sent out
1611 // it will not be cancelled later
1612 if (any_component_done_requested || any_component_killed_requested)
1613 send_status_to_mtc = TRUE;
1614 boolean all_done_checked = FALSE, all_done_result = FALSE;
1615 if (all_component_done_requested) {
1616 all_done_checked = TRUE;
1617 all_done_result = !is_any_component_running();
1618 if (all_done_result) send_status_to_mtc = TRUE;
1619 }
1620 boolean all_killed_checked = FALSE, all_killed_result = FALSE;
1621 if (all_component_killed_requested) {
1622 all_killed_checked = TRUE;
1623 all_killed_result = !is_any_component_alive();
1624 if (all_killed_result) send_status_to_mtc = TRUE;
1625 }
1626 // sending the COMPONENT_STATUS message to MTC if necessary
1627 if (send_status_to_mtc) {
1628 if (!all_done_checked) all_done_result = !is_any_component_running();
1629 if (!all_killed_checked) all_killed_result = !is_any_component_alive();
1630 if (send_done_to_mtc) {
1631 // the return value was requested
1632 send_component_status_mtc(tc->comp_ref, TRUE, TRUE, TRUE,
1633 all_done_result, TRUE, all_killed_result, tc->return_type,
1634 tc->return_value_len, tc->return_value);
1635 } else {
1636 // the return value was not requested
1637 send_component_status_mtc(tc->comp_ref, FALSE, TRUE, TRUE,
1638 all_done_result, TRUE, all_killed_result, NULL, 0, NULL);
1639 }
1640 any_component_done_requested = FALSE;
1641 any_component_done_sent = TRUE;
1642 any_component_killed_requested = FALSE;
1643 if (all_done_result) all_component_done_requested = FALSE;
1644 if (all_killed_result) all_component_killed_requested = FALSE;
1645 }
1646 // sending out STOP_ACK and KILL_ACK messages if necessary
1647 switch (old_state) {
1648 case TC_STOPPING:
1649 case PTC_STOPPING_KILLING:
1650 case PTC_KILLING:
1651 // the component was explicitly stopped and/or killed
1652 if (mtc->tc_state == MTC_ALL_COMPONENT_KILL) {
1653 check_all_component_kill();
1654 } else if (mtc->tc_state == MTC_ALL_COMPONENT_STOP) {
1655 check_all_component_stop();
1656 } else {
1657 send_stop_ack_to_requestors(tc);
1658 send_kill_ack_to_requestors(tc);
1659 }
1660 default:
1661 break;
1662 }
1663 // we should behave as we got all pending CANCEL_DONE_ACK messages from tc
1664 for (int i = 0; ; i++) {
1665 component_struct *comp = get_requestor(&tc->cancel_done_sent_for, i);
1666 if (comp == NULL) break;
1667 done_cancelled(tc, comp);
1668 }
1669 free_requestors(&tc->cancel_done_sent_for);
1670 // destroy all connections and mappings of the component
1671 // and send out the related messages
1672 while (tc->conn_head_list != NULL) {
1673 if (tc->conn_head_list->tail.comp_ref == SYSTEM_COMPREF)
1674 destroy_mapping(tc->conn_head_list);
1675 else destroy_connection(tc->conn_head_list, tc);
1676 }
1677 while (tc->conn_tail_list != NULL) {
1678 if (tc->conn_tail_list->head.comp_ref == SYSTEM_COMPREF)
1679 destroy_mapping(tc->conn_tail_list);
1680 else destroy_connection(tc->conn_tail_list, tc);
1681 }
1682 // drop the name of the currently executed function
1683 free_qualified_name(&tc->tc_fn_name);
1684 }
1685
1686 void MainController::done_cancelled(component_struct *from,
1687 component_struct *started_tc)
1688 {
1689 // do nothing if the PTC to be started is not in starting state anymore
1690 if (started_tc->tc_state != PTC_STARTING) return;
1691 remove_requestor(&started_tc->starting.cancel_done_sent_to, from);
1692 // do nothing if we are waiting for more CANCEL_DONE_ACK messages
1693 if (get_requestor(&started_tc->starting.cancel_done_sent_to, 0) != NULL)
1694 return;
1695 send_start(started_tc, started_tc->tc_fn_name,
1696 started_tc->starting.arguments_len, started_tc->starting.arguments_ptr);
1697 component_struct *start_requestor = started_tc->starting.start_requestor;
1698 if (start_requestor->tc_state == TC_START) {
1699 send_start_ack(start_requestor);
1700 if (start_requestor == mtc) start_requestor->tc_state = MTC_TESTCASE;
1701 else start_requestor->tc_state = PTC_FUNCTION;
1702 }
1703 Free(started_tc->starting.arguments_ptr);
1704 free_requestors(&started_tc->starting.cancel_done_sent_to);
1705 started_tc->tc_state = PTC_FUNCTION;
1706 status_change();
1707 }
1708
1709 boolean MainController::component_is_alive(component_struct *tc)
1710 {
1711 switch (tc->tc_state) {
1712 case TC_INITIAL:
1713 case TC_IDLE:
1714 case TC_CREATE:
1715 case TC_START:
1716 case TC_STOP:
1717 case TC_KILL:
1718 case TC_CONNECT:
1719 case TC_DISCONNECT:
1720 case TC_MAP:
1721 case TC_UNMAP:
1722 case TC_STOPPING:
1723 case PTC_FUNCTION:
1724 case PTC_STARTING:
1725 case PTC_STOPPED:
1726 case PTC_KILLING:
1727 case PTC_STOPPING_KILLING:
1728 return TRUE;
1729 case TC_EXITING:
1730 case TC_EXITED:
1731 return FALSE;
1732 default:
1733 error("PTC %d is in invalid state when checking whether it is alive.",
1734 tc->comp_ref);
1735 return FALSE;
1736 }
1737 }
1738
1739 boolean MainController::component_is_running(component_struct *tc)
1740 {
1741 switch (tc->tc_state) {
1742 case TC_CREATE:
1743 case TC_START:
1744 case TC_STOP:
1745 case TC_KILL:
1746 case TC_CONNECT:
1747 case TC_DISCONNECT:
1748 case TC_MAP:
1749 case TC_UNMAP:
1750 case TC_STOPPING:
1751 case PTC_FUNCTION:
1752 case PTC_STARTING:
1753 case PTC_STOPPING_KILLING:
1754 return TRUE;
1755 case TC_INITIAL:
1756 case TC_IDLE:
1757 case TC_EXITING:
1758 case TC_EXITED:
1759 case PTC_STOPPED:
1760 case PTC_KILLING:
1761 return FALSE;
1762 default:
1763 error("PTC %d is in invalid state when checking whether it is running.",
1764 tc->comp_ref);
1765 return FALSE;
1766 }
1767 }
1768
1769 boolean MainController::component_is_done(component_struct *tc)
1770 {
1771 switch (tc->tc_state) {
1772 case TC_EXITING:
1773 case TC_EXITED:
1774 case PTC_STOPPED:
1775 return TRUE;
1776 case TC_INITIAL:
1777 case TC_IDLE:
1778 case TC_CREATE:
1779 case TC_START:
1780 case TC_STOP:
1781 case TC_KILL:
1782 case TC_CONNECT:
1783 case TC_DISCONNECT:
1784 case TC_MAP:
1785 case TC_UNMAP:
1786 case TC_STOPPING:
1787 case PTC_FUNCTION:
1788 case PTC_STARTING:
1789 case PTC_KILLING:
1790 case PTC_STOPPING_KILLING:
1791 return FALSE;
1792 default:
1793 error("PTC %d is in invalid state when checking whether it is done.",
1794 tc->comp_ref);
1795 return FALSE;
1796 }
1797 }
1798
1799 boolean MainController::is_any_component_alive()
1800 {
1801 for (component i = tc_first_comp_ref; i < n_components; i++)
1802 if (component_is_alive(components[i])) return TRUE;
1803 return FALSE;
1804 }
1805
1806 boolean MainController::is_all_component_alive()
1807 {
1808 for (component i = tc_first_comp_ref; i < n_components; i++)
1809 if (!component_is_alive(components[i])) return FALSE;
1810 return TRUE;
1811 }
1812
1813 boolean MainController::is_any_component_running()
1814 {
1815 for (component i = tc_first_comp_ref; i < n_components; i++)
1816 if (component_is_running(components[i])) return TRUE;
1817 return FALSE;
1818 }
1819
1820 boolean MainController::is_all_component_running()
1821 {
1822 for (component i = tc_first_comp_ref; i < n_components; i++) {
1823 component_struct *tc = components[i];
1824 if (tc->stop_requested) continue;
1825 switch (tc->tc_state) {
1826 case TC_EXITING:
1827 case TC_EXITED:
1828 case PTC_STOPPED:
1829 return FALSE;
1830 default:
1831 break;
1832 }
1833 }
1834 return TRUE;
1835 }
1836
1837 boolean MainController::is_any_component_done()
1838 {
1839 for (component i = tc_first_comp_ref; i < n_components; i++)
1840 if (component_is_done(components[i])) return TRUE;
1841 return FALSE;
1842 }
1843
1844 void MainController::start_kill_timer(component_struct *tc)
1845 {
1846 if (kill_timer > 0.0) {
1847 timer_struct *timer = new timer_struct;
1848 timer->expiration = time_now() + kill_timer;
1849 timer->timer_argument.component_ptr = tc;
1850 tc->kill_timer = timer;
1851 register_timer(timer);
1852 } else tc->kill_timer = NULL;
1853 }
1854
1855 void MainController::init_connections(component_struct *tc)
1856 {
1857 tc->conn_head_list = NULL;
1858 tc->conn_tail_list = NULL;
1859 tc->conn_head_count = 0;
1860 tc->conn_tail_count = 0;
1861 }
1862
1863 void MainController::add_connection(port_connection *c)
1864 {
1865 // Canonical ordering of endpoints so that head <= tail
1866 if (c->head.comp_ref > c->tail.comp_ref) {
1867 component tmp_comp = c->head.comp_ref;
1868 c->head.comp_ref = c->tail.comp_ref;
1869 c->tail.comp_ref = tmp_comp;
1870 char *tmp_port = c->head.port_name;
1871 c->head.port_name = c->tail.port_name;
1872 c->tail.port_name = tmp_port;
1873 } else if (c->head.comp_ref == c->tail.comp_ref &&
1874 strcmp(c->head.port_name, c->tail.port_name) > 0) {
1875 char *tmp_port = c->head.port_name;
1876 c->head.port_name = c->tail.port_name;
1877 c->tail.port_name = tmp_port;
1878 }
1879 // Double-chain in according to c->head
1880 component_struct *head_component = lookup_component(c->head.comp_ref);
1881 port_connection *head_connection = head_component->conn_head_list;
1882 if (head_connection == NULL) {
1883 c->head.next = c;
1884 c->head.prev = c;
1885 } else {
1886 c->head.prev = head_connection->head.prev;
1887 head_connection->head.prev = c;
1888 c->head.next = head_connection;
1889 c->head.prev->head.next = c;
1890 }
1891 head_component->conn_head_list = c;
1892 head_component->conn_head_count++;
1893 // Double-chain in according to c->tail
1894 component_struct *tail_component = lookup_component(c->tail.comp_ref);
1895 port_connection *tail_connection = tail_component->conn_tail_list;
1896 if (tail_connection == NULL) {
1897 c->tail.next = c;
1898 c->tail.prev = c;
1899 } else {
1900 c->tail.prev = tail_connection->tail.prev;
1901 tail_connection->tail.prev = c;
1902 c->tail.next = tail_connection;
1903 c->tail.prev->tail.next = c;
1904 }
1905 tail_component->conn_tail_list = c;
1906 tail_component->conn_tail_count++;
1907 }
1908
1909 void MainController::remove_connection(port_connection *c)
1910 {
1911 // Remove from conn_head_list
1912 component_struct *head_component = lookup_component(c->head.comp_ref);
1913 if (c->head.next == c) {
1914 head_component->conn_head_list = NULL;
1915 head_component->conn_head_count = 0;
1916 } else {
1917 c->head.prev->head.next = c->head.next;
1918 c->head.next->head.prev = c->head.prev;
1919 head_component->conn_head_list = c->head.next;
1920 head_component->conn_head_count--;
1921 }
1922 // Remove from conn_tail_list
1923 component_struct *tail_component = lookup_component(c->tail.comp_ref);
1924 if (c->tail.next == c) {
1925 tail_component->conn_tail_list = NULL;
1926 tail_component->conn_tail_count = 0;
1927 } else {
1928 c->tail.prev->tail.next = c->tail.next;
1929 c->tail.next->tail.prev = c->tail.prev;
1930 tail_component->conn_tail_list = c->tail.next;
1931 tail_component->conn_tail_count--;
1932 }
1933 // Delete the data members
1934 delete [] c->head.port_name;
1935 delete [] c->tail.port_name;
1936 free_requestors(&c->requestors);
1937 delete c;
1938 }
1939
1940 port_connection *MainController::find_connection(component head_comp,
1941 const char *head_port, component tail_comp, const char *tail_port)
1942 {
1943 // Canonical ordering of parameters so that head <= tail
1944 if (head_comp > tail_comp) {
1945 component tmp_comp = head_comp;
1946 head_comp = tail_comp;
1947 tail_comp = tmp_comp;
1948 const char *tmp_port = head_port;
1949 head_port = tail_port;
1950 tail_port = tmp_port;
1951 } else if (head_comp == tail_comp && strcmp(head_port, tail_port) > 0) {
1952 const char *tmp_port = head_port;
1953 head_port = tail_port;
1954 tail_port = tmp_port;
1955 }
1956 // Check whether one of the endpoints' list is empty
1957 component_struct *head_component = lookup_component(head_comp);
1958 port_connection *head_connection = head_component->conn_head_list;
1959 if (head_connection == NULL) return NULL;
1960 component_struct *tail_component = lookup_component(tail_comp);
1961 port_connection *tail_connection = tail_component->conn_tail_list;
1962 if (tail_connection == NULL) return NULL;
1963 // Start searching on the shorter list
1964 if (head_component->conn_head_count <= tail_component->conn_tail_count) {
1965 port_connection *iter = head_connection;
1966 do {
1967 if (iter->tail.comp_ref == tail_comp &&
1968 !strcmp(iter->head.port_name, head_port) &&
1969 !strcmp(iter->tail.port_name, tail_port)) return iter;
1970 iter = iter->head.next;
1971 } while (iter != head_connection);
1972 return NULL;
1973 } else {
1974 port_connection *iter = tail_connection;
1975 do {
1976 if (iter->head.comp_ref == head_comp &&
1977 !strcmp(iter->head.port_name, head_port) &&
1978 !strcmp(iter->tail.port_name, tail_port)) return iter;
1979 iter = iter->tail.next;
1980 } while (iter != tail_connection);
1981 return NULL;
1982 }
1983 }
1984
1985 void MainController::remove_all_connections(component head_or_tail)
1986 {
1987 component_struct *comp = lookup_component(head_or_tail);
1988 while (comp->conn_head_list != NULL)
1989 remove_connection(comp->conn_head_list);
1990 while (comp->conn_tail_list != NULL)
1991 remove_connection(comp->conn_tail_list);
1992 }
1993
1994 transport_type_enum MainController::choose_port_connection_transport(
1995 component head_comp, component tail_comp)
1996 {
1997 host_struct *head_location = components[head_comp]->comp_location;
1998 // use the most efficient software loop if the two endpoints are in the
1999 // same component and the host supports it
2000 if (head_comp == tail_comp &&
2001 head_location->transport_supported[TRANSPORT_LOCAL])
2002 return TRANSPORT_LOCAL;
2003 host_struct *tail_location = components[tail_comp]->comp_location;
2004 // use the efficient UNIX domain socket if the two endpoints are on the
2005 // same host and it is supported by the host
2006 if (head_location == tail_location &&
2007 head_location->transport_supported[TRANSPORT_UNIX_STREAM])
2008 return TRANSPORT_UNIX_STREAM;
2009 // use TCP if it is supported by the host of both endpoints
2010 if (head_location->transport_supported[TRANSPORT_INET_STREAM] &&
2011 tail_location->transport_supported[TRANSPORT_INET_STREAM])
2012 return TRANSPORT_INET_STREAM;
2013 // no suitable transport was found, return an erroneous type
2014 return TRANSPORT_NUM;
2015 }
2016
2017 void MainController::send_connect_ack_to_requestors(port_connection *conn)
2018 {
2019 for (int i = 0; ; i++) {
2020 component_struct *comp = get_requestor(&conn->requestors, i);
2021 if (comp == NULL) break;
2022 else if (comp->tc_state == TC_CONNECT) {
2023 send_connect_ack(comp);
2024 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
2025 else comp->tc_state = PTC_FUNCTION;
2026 }
2027 }
2028 free_requestors(&conn->requestors);
2029 }
2030
2031 void MainController::send_error_to_connect_requestors(port_connection *conn,
2032 const char *fmt, ...)
2033 {
2034 char *reason = mprintf("Establishment of port connection %d:%s - %d:%s "
2035 "failed because ", conn->head.comp_ref, conn->head.port_name,
2036 conn->tail.comp_ref, conn->tail.port_name);
2037 va_list ap;
2038 va_start(ap, fmt);
2039 reason = mputprintf_va_list(reason, fmt, ap);
2040 va_end(ap);
2041 for (int i = 0; ; i++) {
2042 component_struct *comp = get_requestor(&conn->requestors, i);
2043 if (comp == NULL) break;
2044 else if (comp->tc_state == TC_CONNECT) {
2045 send_error_str(comp->tc_fd, reason);
2046 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
2047 else comp->tc_state = PTC_FUNCTION;
2048 }
2049 }
2050 Free(reason);
2051 free_requestors(&conn->requestors);
2052 }
2053
2054 void MainController::send_disconnect_to_server(port_connection *conn)
2055 {
2056 component_struct *comp = components[conn->head.comp_ref];
2057 switch (comp->tc_state) {
2058 case TC_IDLE:
2059 case TC_CREATE:
2060 case TC_START:
2061 case TC_STOP:
2062 case TC_KILL:
2063 case TC_CONNECT:
2064 case TC_DISCONNECT:
2065 case TC_MAP:
2066 case TC_UNMAP:
2067 case TC_STOPPING:
2068 case MTC_TESTCASE:
2069 case PTC_FUNCTION:
2070 case PTC_STARTING:
2071 case PTC_STOPPED:
2072 send_disconnect(comp, conn->head.port_name, conn->tail.comp_ref,
2073 conn->tail.port_name);
2074 default:
2075 break;
2076 }
2077 }
2078
2079 void MainController::send_disconnect_ack_to_requestors(port_connection *conn)
2080 {
2081 for (int i = 0; ; i++) {
2082 component_struct *comp = get_requestor(&conn->requestors, i);
2083 if (comp == NULL) break;
2084 else if (comp->tc_state == TC_DISCONNECT) {
2085 send_disconnect_ack(comp);
2086 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
2087 else comp->tc_state = PTC_FUNCTION;
2088 }
2089 }
2090 free_requestors(&conn->requestors);
2091 }
2092
2093 void MainController::init_requestors(requestor_struct *reqs,
2094 component_struct *tc)
2095 {
2096 if (tc != NULL) {
2097 reqs->n_components = 1;
2098 reqs->the_component = tc;
2099 } else reqs->n_components = 0;
2100 }
2101
2102 void MainController::add_requestor(requestor_struct *reqs, component_struct *tc)
2103 {
2104 switch (reqs->n_components) {
2105 case 0:
2106 reqs->n_components = 1;
2107 reqs->the_component = tc;
2108 break;
2109 case 1:
2110 if (reqs->the_component != tc) {
2111 reqs->n_components = 2;
2112 component_struct *tmp = reqs->the_component;
2113 reqs->components =
2114 (component_struct**)Malloc(2 * sizeof(*reqs->components));
2115 reqs->components[0] = tmp;
2116 reqs->components[1] = tc;
2117 }
2118 break;
2119 default:
2120 for (int i = 0; i < reqs->n_components; i++)
2121 if (reqs->components[i] == tc) return;
2122 reqs->n_components++;
2123 reqs->components = (component_struct**)Realloc(reqs->components,
2124 reqs->n_components * sizeof(*reqs->components));
2125 reqs->components[reqs->n_components - 1] = tc;
2126 }
2127 }
2128
2129 void MainController::remove_requestor(requestor_struct *reqs,
2130 component_struct *tc)
2131 {
2132 switch (reqs->n_components) {
2133 case 0:
2134 break;
2135 case 1:
2136 if (reqs->the_component == tc) reqs->n_components = 0;
2137 break;
2138 case 2: {
2139 component_struct *tmp = NULL;
2140 if (reqs->components[0] == tc) tmp = reqs->components[1];
2141 else if (reqs->components[1] == tc) tmp = reqs->components[0];
2142 if (tmp != NULL) {
2143 Free(reqs->components);
2144 reqs->n_components = 1;
2145 reqs->the_component = tmp;
2146 }
2147 break; }
2148 default:
2149 for (int i = 0; i < reqs->n_components; i++)
2150 if (reqs->components[i] == tc) {
2151 reqs->n_components--;
2152 memmove(reqs->components + i, reqs->components + i + 1,
2153 (reqs->n_components - i) * sizeof(*reqs->components));
2154 reqs->components = (component_struct**)Realloc(reqs->components,
2155 reqs->n_components * sizeof(*reqs->components));
2156 break;
2157 }
2158 }
2159 }
2160
2161 boolean MainController::has_requestor(const requestor_struct *reqs,
2162 component_struct *tc)
2163 {
2164 switch (reqs->n_components) {
2165 case 0:
2166 return FALSE;
2167 case 1:
2168 return reqs->the_component == tc;
2169 default:
2170 for (int i = 0; i < reqs->n_components; i++)
2171 if (reqs->components[i] == tc) return TRUE;
2172 return FALSE;
2173 }
2174 }
2175
2176 component_struct *MainController::get_requestor(const requestor_struct *reqs,
2177 int index)
2178 {
2179 if (index >= 0 && index < reqs->n_components) {
2180 if (reqs->n_components == 1) return reqs->the_component;
2181 else return reqs->components[index];
2182 } else return NULL;
2183 }
2184
2185 void MainController::free_requestors(requestor_struct *reqs)
2186 {
2187 if (reqs->n_components > 1) Free(reqs->components);
2188 reqs->n_components = 0;
2189 }
2190
2191 void MainController::init_qualified_name(qualified_name *name)
2192 {
2193 name->module_name = NULL;
2194 name->definition_name = NULL;
2195 }
2196
2197 void MainController::free_qualified_name(qualified_name *name)
2198 {
2199 delete [] name->module_name;
2200 name->module_name = NULL;
2201 delete [] name->definition_name;
2202 name->definition_name = NULL;
2203 }
2204
2205 double MainController::kill_timer;
2206
2207 double MainController::time_now()
2208 {
2209 static boolean first_call = TRUE;
2210 static struct timeval first_time;
2211 if (first_call) {
2212 first_call = FALSE;
2213 if (gettimeofday(&first_time, NULL) < 0)
2214 fatal_error("MainController::time_now: gettimeofday() system call "
2215 "failed.");
2216 return 0.0;
2217 } else {
2218 struct timeval tv;
2219 if (gettimeofday(&tv, NULL) < 0)
2220 fatal_error("MainController::time_now: gettimeofday() system call "
2221 "failed.");
2222 return (tv.tv_sec - first_time.tv_sec) +
2223 1.0e-6 * (tv.tv_usec - first_time.tv_usec);
2224 }
2225 }
2226
2227 timer_struct *MainController::timer_head, *MainController::timer_tail;
2228
2229 void MainController::register_timer(timer_struct *timer)
2230 {
2231 timer_struct *iter;
2232 for (iter = timer_tail; iter != NULL; iter = iter->prev)
2233 if (iter->expiration <= timer->expiration) break;
2234 if (iter != NULL) {
2235 // inserting after iter
2236 timer->prev = iter;
2237 timer->next = iter->next;
2238 if (iter->next != NULL) iter->next->prev = timer;
2239 else timer_tail = timer;
2240 iter->next = timer;
2241 } else {
2242 // inserting at the beginning of list
2243 timer->prev = NULL;
2244 timer->next = timer_head;
2245 if (timer_head != NULL) timer_head->prev = timer;
2246 else timer_tail = timer;
2247 timer_head = timer;
2248 }
2249 }
2250
2251 void MainController::cancel_timer(timer_struct *timer)
2252 {
2253 if (timer->next != NULL) timer->next->prev = timer->prev;
2254 else timer_tail = timer->prev;
2255 if (timer->prev != NULL) timer->prev->next = timer->next;
2256 else timer_head = timer->next;
2257 delete timer;
2258 }
2259
2260 int MainController::get_poll_timeout()
2261 {
2262 if (timer_head != NULL) {
2263 double offset = timer_head->expiration - time_now();
2264 if (offset > 0.0) return (int)(1000.0 * offset);
2265 else return 0;
2266 } else return -1;
2267 }
2268
2269 void MainController::handle_expired_timers()
2270 {
2271 if (timer_head != NULL) {
2272 timer_struct *iter = timer_head;
2273 double now = time_now();
2274 do {
2275 if (iter->expiration > now) break;
2276 timer_struct *next = iter->next;
2277 handle_kill_timer(iter);
2278 iter = next;
2279 } while (iter != NULL);
2280 }
2281 }
2282
2283 void MainController::handle_kill_timer(timer_struct *timer)
2284 {
2285 component_struct *tc = timer->timer_argument.component_ptr;
2286 host_struct *host = tc->comp_location;
2287 boolean kill_process = FALSE;
2288 switch (tc->tc_state) {
2289 case TC_EXITED:
2290 // do nothing
2291 break;
2292 case TC_EXITING:
2293 if (tc == mtc) {
2294 error("MTC on host %s did not close its control connection in "
2295 "time. Trying to kill it using its HC.", host->hostname);
2296 } else {
2297 notify("PTC %d on host %s did not close its control connection in "
2298 "time. Trying to kill it using its HC.", tc->comp_ref,
2299 host->hostname);
2300 }
2301 kill_process = TRUE;
2302 break;
2303 case TC_STOPPING:
2304 case PTC_STOPPING_KILLING:
2305 case PTC_KILLING:
2306 // active PTCs with kill timer can be only in these states
2307 if (tc != mtc) {
2308 notify("PTC %d on host %s is not responding. Trying to kill it "
2309 "using its HC.", tc->comp_ref, host->hostname);
2310 kill_process = TRUE;
2311 break;
2312 }
2313 // no break
2314 default:
2315 // MTC can be in any state
2316 if (tc == mtc) {
2317 error("MTC on host %s is not responding. Trying to kill it using "
2318 "its HC. This will abort test execution.", host->hostname);
2319 kill_process = TRUE;
2320 } else {
2321 error("PTC %d is in invalid state when its kill timer expired.",
2322 tc->comp_ref);
2323 }
2324 }
2325 if (kill_process) {
2326 if (host->hc_state == HC_ACTIVE) {
2327 send_kill_process(host, tc->comp_ref);
2328 tc->process_killed = TRUE;
2329 } else {
2330 error("Test Component %d cannot be killed because the HC on host "
2331 "%s is not in active state. Kill the process manually or the "
2332 "test system may get into a deadlock.", tc->comp_ref,
2333 host->hostname);
2334 }
2335 }
2336 cancel_timer(timer);
2337 tc->kill_timer = NULL;
2338 }
2339
2340 void MainController::register_termination_handlers()
2341 {
2342 new_action.sa_handler = termination_handler;
2343 sigemptyset(&new_action.sa_mask);
2344 new_action.sa_flags = 0;
2345
2346 sigaction(SIGINT, NULL, &old_action);
2347 if (old_action.sa_handler != SIG_IGN)
2348 sigaction (SIGINT, &new_action, NULL);
2349 sigaction(SIGHUP, NULL, &old_action);
2350 if (old_action.sa_handler != SIG_IGN)
2351 sigaction (SIGHUP, &new_action, NULL);
2352 sigaction(SIGTERM, NULL, &old_action);
2353 if (old_action.sa_handler != SIG_IGN)
2354 sigaction(SIGTERM, &new_action, NULL);
2355 sigaction(SIGQUIT, NULL, &old_action);
2356 if (old_action.sa_handler != SIG_IGN)
2357 sigaction(SIGQUIT, &new_action, NULL);
2358 sigaction(SIGKILL, NULL, &old_action);
2359 if (old_action.sa_handler != SIG_IGN)
2360 sigaction(SIGKILL, &new_action, NULL);
2361 }
2362
2363 void MainController::termination_handler(int signum)
2364 {
2365 // Call shutdown_server() and reset handlers and re-raise the signal.
2366 // clean_up() or perform_shutdown() is state dependent and cannot be used
2367 // here... Related to HP67376.
2368 shutdown_server();
2369
2370 new_action.sa_handler = SIG_DFL;
2371 sigemptyset(&new_action.sa_mask);
2372 new_action.sa_flags = 0;
2373
2374 sigaction(SIGINT, &new_action, NULL);
2375 sigaction(SIGHUP, &new_action, NULL);
2376 sigaction(SIGTERM, &new_action, NULL);
2377 sigaction(SIGQUIT, &new_action, NULL);
2378 sigaction(SIGKILL, &new_action, NULL);
2379
2380 raise(signum);
2381 }
2382
2383 void MainController::error(const char *fmt, ...)
2384 {
2385 va_list ap;
2386 va_start(ap, fmt);
2387 char *str = mprintf_va_list(fmt, ap);
2388 va_end(ap);
2389 unlock();
2390 ui->error(/*severity*/ 0, str);
2391 lock();
2392 Free(str);
2393 }
2394
2395 void MainController::notify(const char *fmt, ...)
2396 {
2397 va_list ap;
2398 va_start(ap, fmt);
2399 char *str = mprintf_va_list(fmt, ap);
2400 va_end(ap);
2401 struct timeval tv;
2402 if (gettimeofday(&tv, NULL) < 0) fatal_error("MainController::notify: "
2403 "gettimeofday() system call failed.");
2404 notify(&tv, mc_hostname, TTCN_EXECUTOR, str);
2405 Free(str);
2406 }
2407
2408 void MainController::notify(const struct timeval *timestamp,
2409 const char *source, int severity, const char *message)
2410 {
2411 unlock();
2412 ui->notify(timestamp, source, severity, message);
2413 lock();
2414 }
2415
2416 void MainController::status_change()
2417 {
2418 unlock();
2419 ui->status_change();
2420 lock();
2421 }
2422
2423 void MainController::fatal_error(const char *fmt, ...)
2424 {
2425 va_list ap;
2426 va_start(ap, fmt);
2427 vfprintf(stderr, fmt, ap);
2428 va_end(ap);
2429 if (errno != 0) fprintf(stderr, " (%s)", strerror(errno));
2430 putc('\n', stderr);
2431 exit(EXIT_FAILURE);
2432 }
2433
2434 void *MainController::thread_main(void *)
2435 {
2436 lock();
2437 while (mc_state != MC_INACTIVE) {
2438 int fds_selected;
2439 for ( ; ; ) {
2440 int maxDtInMs = 0;
2441 #ifdef USE_EPOLL
2442 int timeout = get_poll_timeout();
2443 if (maxDtInMs != 0 && (timeout < 0 || maxDtInMs < timeout))
2444 timeout = maxDtInMs;
2445 unlock();
2446 fds_selected = epoll_wait(epfd, epoll_events, EPOLL_MAX_EVENTS,
2447 timeout);
2448 lock();
2449 if (fds_selected >= 0) break;
2450 if (errno != EINTR) fatal_error("epoll_wait() system call failed.");
2451 #else // ! defined USE_EPOLL
2452 update_pollfds();
2453 int timeout = get_poll_timeout();
2454 if (maxDtInMs != 0 && (timeout < 0 || maxDtInMs < timeout))
2455 timeout = maxDtInMs;
2456 unlock();
2457 fds_selected = poll(ufds, nfds, timeout);
2458 lock();
2459 if (fds_selected >= 0) break;
2460 if (errno != EINTR) fatal_error("poll() system call failed.");
2461 #endif //USE_EPOLL
2462 errno = 0;
2463 }
2464 switch (wakeup_reason) {
2465 case REASON_NOTHING:
2466 case REASON_MTC_KILL_TIMER:
2467 break;
2468 case REASON_SHUTDOWN:
2469 wakeup_reason = REASON_NOTHING;
2470 perform_shutdown();
2471 continue;
2472 default:
2473 error("Invalid wakeup reason (%d) was set.", wakeup_reason);
2474 wakeup_reason = REASON_NOTHING;
2475 }
2476 if (fds_selected == 0) {
2477 handle_expired_timers();
2478 continue;
2479 }
2480 #ifdef USE_EPOLL
2481 for (int i = 0; i < fds_selected; i++) {
2482 int fd = epoll_events[i].data.fd;
2483 if (epoll_events[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
2484 dispatch_socket_event(fd);
2485 }
2486 }
2487 #else // ! defined USE_EPOLL
2488 for (unsigned int i = 0; i < nfds; i++) {
2489 int fd = ufds[i].fd;
2490 if (ufds[i].revents & POLLNVAL) {
2491 fatal_error("Invalid file descriptor (%d) was given for "
2492 "poll() system call.", fd);
2493 } else if (ufds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
2494 dispatch_socket_event(fd);
2495 }
2496 }
2497 #endif //USE_EPOLL
2498 handle_expired_timers();
2499 }
2500 clean_up();
2501 notify("Shutdown complete.");
2502 unlock();
2503 // don't try to lock the mutex after ui->status_change() is completed
2504 // the main thread might call in turn terminate(), which destroys the mutex
2505 ui->status_change();
2506 return NULL;
2507 }
2508
2509 void MainController::dispatch_socket_event(int fd)
2510 {
2511 // a previous event might have closed the socket
2512 if (fd >= fd_table_size) return;
2513 switch (fd_table[fd].fd_type) {
2514 case FD_PIPE:
2515 handle_pipe();
2516 break;
2517 case FD_SERVER:
2518 handle_incoming_connection(fd);
2519 break;
2520 case FD_UNKNOWN:
2521 handle_unknown_data(fd_table[fd].unknown_ptr);
2522 break;
2523 case FD_HC:
2524 handle_hc_data(fd_table[fd].host_ptr, TRUE);
2525 break;
2526 case FD_TC:
2527 handle_tc_data(fd_table[fd].component_ptr, TRUE);
2528 break;
2529 default:
2530 fatal_error("Invalid file descriptor type (%d) for "
2531 "file descriptor %d.", fd_table[fd].fd_type, fd);
2532 }
2533 }
2534
2535 int MainController::pipe_fd[2];
2536 wakeup_reason_t MainController::wakeup_reason;
2537
2538 void MainController::wakeup_thread(wakeup_reason_t reason)
2539 {
2540 unsigned char msg = '\0';
2541 if (write(pipe_fd[1], &msg, 1) != 1) {
2542 fatal_error("MainController::wakeup_thread: writing to pipe failed.");
2543 }
2544 wakeup_reason = reason;
2545 }
2546
2547 void MainController::handle_pipe()
2548 {
2549 unsigned char buf;
2550 if (read(pipe_fd[0], &buf, 1) != 1) {
2551 fatal_error("MainController::handle_pipe: reading from pipe failed.");
2552 }
2553 }
2554
2555 void MainController::handle_incoming_connection(int p_server_fd)
2556 {
2557 IPAddress *remote_addr = IPAddress::create_addr(nh.get_family());
2558 int fd = remote_addr->accept(p_server_fd);
2559 if (fd > 0) {
2560 set_close_on_exec(fd);
2561 unknown_connection *new_connection =
2562 new_unknown_connection(p_server_fd != MainController::server_fd);
2563 new_connection->fd = fd;
2564 if (p_server_fd == MainController::server_fd)
2565 new_connection->ip_addr = remote_addr;
2566 else { // in case of unix domain socket connection
2567 delete remote_addr;
2568 new_connection->ip_addr = IPAddress::create_addr("127.0.0.1");
2569 }
2570 new_connection->text_buf = new Text_Buf;
2571 add_poll_fd(fd);
2572 add_fd_to_table(fd);
2573 fd_table[fd].fd_type = FD_UNKNOWN;
2574 fd_table[fd].unknown_ptr = new_connection;
2575 } else {
2576 delete remote_addr;
2577 switch (errno) {
2578 case EINTR:
2579 errno = 0;
2580 break;
2581 case EMFILE:
2582 case ENFILE:
2583 error("New incoming connection cannot be accepted "
2584 "because the maximum number of open files has been reached. "
2585 "Try to increase this limit.");
2586 disable_server_fd();
2587 error("No incoming connections will be accepted until at least "
2588 "one component terminates. This may result in deadlock.");
2589 break;
2590 default:
2591 fatal_error("MainController::handle_incoming_connection: "
2592 "system call accept() failed.");
2593 }
2594 }
2595 }
2596
2597 int MainController::recv_to_buffer(int fd, Text_Buf& text_buf,
2598 boolean recv_from_socket)
2599 {
2600 // if recv_from_socket is false we are checking the messages that are
2601 // already in text_buf so we are emulating that recv() was successful
2602 if (!recv_from_socket) return 1;
2603
2604 char *buf_ptr;
2605 int buf_len;
2606 text_buf.get_end(buf_ptr, buf_len);
2607
2608 int recv_len = recv(fd, buf_ptr, buf_len, 0);
2609
2610 if (recv_len > 0) text_buf.increase_length(recv_len);
2611
2612 return recv_len;
2613 }
2614
2615 void MainController::handle_unknown_data(unknown_connection *conn)
2616 {
2617 Text_Buf& text_buf = *conn->text_buf;
2618 int recv_len = recv_to_buffer(conn->fd, text_buf, TRUE);
2619 boolean error_flag = FALSE;
2620
2621 if (recv_len > 0) {
2622 try {
2623 while (text_buf.is_message()) {
2624 text_buf.pull_int(); // message length
2625 int message_type = text_buf.pull_int().get_val();
2626 // only the first message is processed in this loop
2627 // except when a generic message is received
2628 boolean process_more_messages = FALSE;
2629 switch (message_type) {
2630 case MSG_ERROR:
2631 process_error(conn);
2632 process_more_messages = TRUE;
2633 break;
2634 case MSG_LOG:
2635 process_log(conn);
2636 process_more_messages = TRUE;
2637 break;
2638 case MSG_VERSION:
2639 process_version(conn);
2640 break;
2641 case MSG_MTC_CREATED:
2642 process_mtc_created(conn);
2643 break;
2644 case MSG_PTC_CREATED:
2645 process_ptc_created(conn);
2646 break;
2647 default:
2648 error("Invalid message type (%d) was received on an "
2649 "unknown connection from %s [%s].", message_type,
2650 conn->ip_addr->get_host_str(),
2651 conn->ip_addr->get_addr_str());
2652 error_flag = TRUE;
2653 }
2654 if (process_more_messages) text_buf.cut_message();
2655 else break;
2656 }
2657 } catch (const TC_Error& tc_error) {
2658 error("Maleformed message was received on an unknown connection "
2659 "from %s [%s].", conn->ip_addr->get_host_str(),
2660 conn->ip_addr->get_addr_str());
2661 error_flag = TRUE;
2662 }
2663 if (error_flag) {
2664 send_error_str(conn->fd, "The received message was not understood "
2665 "by the MC.");
2666 }
2667 } else if (recv_len == 0) {
2668 error("Unexpected end of an unknown connection from %s [%s].",
2669 conn->ip_addr->get_host_str(), conn->ip_addr->get_addr_str());
2670 error_flag = TRUE;
2671 } else {
2672 error("Receiving of data failed on an unknown connection from %s [%s].",
2673 conn->ip_addr->get_host_str(), conn->ip_addr->get_addr_str());
2674 error_flag = TRUE;
2675 }
2676 if (error_flag) {
2677 close_unknown_connection(conn);
2678 }
2679 }
2680
2681 void MainController::handle_hc_data(host_struct *hc, boolean recv_from_socket)
2682 {
2683 Text_Buf& text_buf = *hc->text_buf;
2684 boolean error_flag = FALSE;
2685 int recv_len = recv_to_buffer(hc->hc_fd, text_buf, recv_from_socket);
2686
2687 if (recv_len > 0) {
2688 try {
2689 while (text_buf.is_message()) {
2690 text_buf.pull_int(); // message length
2691 int message_type = text_buf.pull_int().get_val();
2692 switch (message_type) {
2693 case MSG_ERROR:
2694 process_error(hc);
2695 break;
2696 case MSG_LOG:
2697 process_log(hc);
2698 break;
2699 case MSG_CONFIGURE_ACK:
2700 process_configure_ack(hc);
2701 break;
2702 case MSG_CONFIGURE_NAK:
2703 process_configure_nak(hc);
2704 break;
2705 case MSG_CREATE_NAK:
2706 process_create_nak(hc);
2707 break;
2708 case MSG_HC_READY:
2709 process_hc_ready(hc);
2710 break;
2711 default:
2712 error("Invalid message type (%d) was received on HC "
2713 "connection from %s [%s].", message_type,
2714 hc->hostname, hc->ip_addr->get_addr_str());
2715 error_flag = TRUE;
2716 }
2717 if (error_flag) break;
2718 text_buf.cut_message();
2719 }
2720 } catch (const TC_Error& tc_error) {
2721 error("Malformed message was received on HC connection "
2722 "from %s [%s].", hc->hostname, hc->ip_addr->get_addr_str());
2723 error_flag = TRUE;
2724 }
2725 if (error_flag) {
2726 send_error_str(hc->hc_fd, "The received message was not understood "
2727 "by the MC.");
2728 }
2729 } else if (recv_len == 0) {
2730 if (hc->hc_state == HC_EXITING) {
2731 close_hc_connection(hc);
2732 if (mc_state == MC_SHUTDOWN && all_hc_in_state(HC_DOWN))
2733 mc_state = MC_INACTIVE;
2734 } else {
2735 error("Unexpected end of HC connection from %s [%s].",
2736 hc->hostname, hc->ip_addr->get_addr_str());
2737 error_flag = TRUE;
2738 }
2739 } else {
2740 error("Receiving of data failed on HC connection from %s [%s].",
2741 hc->hostname, hc->ip_addr->get_addr_str());
2742 error_flag = TRUE;
2743 }
2744 if (error_flag) {
2745 close_hc_connection(hc);
2746 switch (mc_state) {
2747 case MC_INACTIVE:
2748 case MC_LISTENING:
2749 case MC_LISTENING_CONFIGURED:
2750 fatal_error("MC is in invalid state when a HC connection "
2751 "terminated.");
2752 case MC_HC_CONNECTED:
2753 if (all_hc_in_state(HC_DOWN)) mc_state = MC_LISTENING;
2754 break;
2755 case MC_CONFIGURING:
2756 check_all_hc_configured();
2757 break;
2758 case MC_ACTIVE:
2759 if (all_hc_in_state(HC_DOWN)) mc_state = MC_LISTENING_CONFIGURED;
2760 else if (!is_hc_in_state(HC_ACTIVE) &&
2761 !is_hc_in_state(HC_OVERLOADED)) mc_state = MC_HC_CONNECTED;
2762 break;
2763 default:
2764 if (!is_hc_in_state(HC_ACTIVE)) notify("There is no active HC "
2765 "connection. Further create operations will fail.");
2766 }
2767 status_change();
2768 }
2769 }
2770
2771 void MainController::handle_tc_data(component_struct *tc,
2772 boolean recv_from_socket)
2773 {
2774 Text_Buf& text_buf = *tc->text_buf;
2775 boolean close_connection = FALSE;
2776 int recv_len = recv_to_buffer(tc->tc_fd, text_buf, recv_from_socket);
2777
2778 if (recv_len > 0) {
2779 try {
2780 while (text_buf.is_message()) {
2781 int message_len = text_buf.pull_int().get_val();
2782 int message_end = text_buf.get_pos() + message_len;
2783 int message_type = text_buf.pull_int().get_val();
2784 // these messages can be received both from MTC and PTCs
2785 switch (message_type) {
2786 case MSG_ERROR:
2787 process_error(tc);
2788 break;
2789 case MSG_LOG:
2790 process_log(tc);
2791 break;
2792 case MSG_CREATE_REQ:
2793 process_create_req(tc);
2794 break;
2795 case MSG_START_REQ:
2796 process_start_req(tc, message_end);
2797 break;
2798 case MSG_STOP_REQ:
2799 process_stop_req(tc);
2800 break;
2801 case MSG_KILL_REQ:
2802 process_kill_req(tc);
2803 break;
2804 case MSG_IS_RUNNING:
2805 process_is_running(tc);
2806 break;
2807 case MSG_IS_ALIVE:
2808 process_is_alive(tc);
2809 break;
2810 case MSG_DONE_REQ:
2811 process_done_req(tc);
2812 break;
2813 case MSG_KILLED_REQ:
2814 process_killed_req(tc);
2815 break;
2816 case MSG_CANCEL_DONE_ACK:
2817 process_cancel_done_ack(tc);
2818 break;
2819 case MSG_CONNECT_REQ:
2820 process_connect_req(tc);
2821 break;
2822 case MSG_CONNECT_LISTEN_ACK:
2823 process_connect_listen_ack(tc, message_end);
2824 break;
2825 case MSG_CONNECTED:
2826 process_connected(tc);
2827 break;
2828 case MSG_CONNECT_ERROR:
2829 process_connect_error(tc);
2830 break;
2831 case MSG_DISCONNECT_REQ:
2832 process_disconnect_req(tc);
2833 break;
2834 case MSG_DISCONNECTED:
2835 process_disconnected(tc);
2836 break;
2837 case MSG_MAP_REQ:
2838 process_map_req(tc);
2839 break;
2840 case MSG_MAPPED:
2841 process_mapped(tc);
2842 break;
2843 case MSG_UNMAP_REQ:
2844 process_unmap_req(tc);
2845 break;
2846 case MSG_UNMAPPED:
2847 process_unmapped(tc);
2848 break;
2849 default:
2850 if (tc == mtc) {
2851 // these messages can be received only from the MTC
2852 switch (message_type) {
2853 case MSG_TESTCASE_STARTED:
2854 process_testcase_started();
2855 break;
2856 case MSG_TESTCASE_FINISHED:
2857 process_testcase_finished();
2858 break;
2859 case MSG_MTC_READY:
2860 process_mtc_ready();
2861 break;
2862 default:
2863 error("Invalid message type (%d) was received "
2864 "from the MTC at %s [%s].", message_type,
2865 mtc->comp_location->hostname,
2866 mtc->comp_location->ip_addr->get_addr_str());
2867 close_connection = TRUE;
2868 }
2869 } else {
2870 // these messages can be received only from PTCs
2871 switch (message_type) {
2872 case MSG_STOPPED:
2873 process_stopped(tc, message_end);
2874 break;
2875 case MSG_STOPPED_KILLED:
2876 process_stopped_killed(tc, message_end);
2877 break;
2878 case MSG_KILLED:
2879 process_killed(tc);
2880 break;
2881 default:
2882 notify("Invalid message type (%d) was received from "
2883 "PTC %d at %s [%s].", message_type,
2884 tc->comp_ref, tc->comp_location->hostname,
2885 tc->comp_location->ip_addr->get_addr_str());
2886 close_connection = TRUE;
2887 }
2888 }
2889 }
2890 if (close_connection) break;
2891 text_buf.cut_message();
2892 }
2893 } catch (const TC_Error& tc_error) {
2894 if (tc == mtc) {
2895 error("Malformed message was received from the MTC at %s "
2896 "[%s].", mtc->comp_location->hostname,
2897 mtc->comp_location->ip_addr->get_addr_str());
2898 } else {
2899 notify("Malformed message was received from PTC %d at %s [%s].",
2900 tc->comp_ref, tc->comp_location->hostname,
2901 tc->comp_location->ip_addr->get_addr_str());
2902 }
2903 close_connection = TRUE;
2904 }
2905 if (close_connection) {
2906 send_error_str(tc->tc_fd, "The received message was not understood "
2907 "by the MC.");
2908 }
2909 } else if (recv_len == 0) {
2910 // TCP connection is closed by peer
2911 if (tc->tc_state != TC_EXITING && !tc->process_killed) {
2912 if (tc == mtc) {
2913 error("Unexpected end of MTC connection from %s [%s].",
2914 mtc->comp_location->hostname,
2915 mtc->comp_location->ip_addr->get_addr_str());
2916 } else {
2917 notify("Unexpected end of PTC connection (%d) from %s [%s].",
2918 tc->comp_ref, tc->comp_location->hostname,
2919 tc->comp_location->ip_addr->get_addr_str());
2920 }
2921 }
2922 close_connection = TRUE;
2923 } else {
2924 if (tc->process_killed && errno == ECONNRESET) {
2925 // ignore TCP resets if the process was killed
2926 // because the last STOP or KILL message can stuck in TCP buffers
2927 // if the process did not receive any data
2928 } else {
2929 if (tc == mtc) {
2930 error("Receiving of data failed from the MTC at %s [%s]: %s",
2931 mtc->comp_location->hostname,
2932 mtc->comp_location->ip_addr->get_addr_str(), strerror(errno));
2933 } else {
2934 notify("Receiving of data failed from PTC %d at %s [%s]: %s",
2935 tc->comp_ref, tc->comp_location->hostname,
2936 tc->comp_location->ip_addr->get_addr_str(), strerror(errno));
2937 }
2938 }
2939 close_connection = TRUE;
2940 }
2941 if (close_connection) {
2942 close_tc_connection(tc);
2943 remove_component_from_host(tc);
2944 if (tc == mtc) {
2945 if (mc_state != MC_TERMINATING_MTC) {
2946 notify("The control connection to MTC is lost. "
2947 "Destroying all PTC connections.");
2948 }
2949 destroy_all_components();
2950 notify("MTC terminated.");
2951 if (is_hc_in_state(HC_CONFIGURING)) mc_state = MC_CONFIGURING;
2952 else if (is_hc_in_state(HC_IDLE)) mc_state = MC_HC_CONNECTED;
2953 else if (is_hc_in_state(HC_ACTIVE) ||
2954 is_hc_in_state(HC_OVERLOADED)) mc_state = MC_ACTIVE;
2955 else mc_state = MC_LISTENING_CONFIGURED;
2956 stop_requested = FALSE;
2957 } else {
2958 if (tc->tc_state != TC_EXITING) {
2959 // we have no idea about the final verdict of the PTC
2960 tc->local_verdict = ERROR;
2961 component_terminated(tc);
2962 }
2963 tc->tc_state = TC_EXITED;
2964 if (mc_state == MC_TERMINATING_TESTCASE &&
2965 ready_to_finish_testcase()) finish_testcase();
2966 }
2967 status_change();
2968 }
2969 }
2970
2971 void MainController::unlink_unix_socket(int socket_fd) {
2972 struct sockaddr_un local_addr;
2973 // querying the local pathname used by socket_fd
2974 socklen_type addr_len = sizeof(local_addr);
2975 if (getsockname(socket_fd, (struct sockaddr*)&local_addr, &addr_len)) {
2976 } else if (local_addr.sun_family != AF_UNIX) {
2977 } else if (unlink(local_addr.sun_path)) {
2978 errno = 0;
2979 }
2980 }
2981
2982 void MainController::shutdown_server()
2983 {
2984 if (server_fd >= 0) {
2985 remove_poll_fd(server_fd);
2986 remove_fd_from_table(server_fd);
2987 close(server_fd);
2988 server_fd = -1;
2989 }
2990
2991 if (server_fd_unix >= 0) {
2992 unlink_unix_socket(server_fd_unix);
2993 remove_poll_fd(server_fd_unix);
2994 remove_fd_from_table(server_fd_unix);
2995 close(server_fd_unix);
2996 server_fd_unix = -1;
2997 }
2998 }
2999
3000 void MainController::perform_shutdown()
3001 {
3002 boolean shutdown_complete = TRUE;
3003 switch (mc_state) {
3004 case MC_HC_CONNECTED:
3005 case MC_ACTIVE:
3006 for (int i = 0; i < n_hosts; i++) {
3007 host_struct *host = hosts[i];
3008 if (host->hc_state != HC_DOWN) {
3009 send_exit_hc(host);
3010 host->hc_state = HC_EXITING;
3011 shutdown_complete = FALSE;
3012 }
3013 }
3014 // no break
3015 case MC_LISTENING:
3016 case MC_LISTENING_CONFIGURED:
3017 shutdown_server();
3018 // don't call status_change() if shutdown is complete
3019 // it will be called from thread_main() later
3020 if (shutdown_complete) mc_state = MC_INACTIVE;
3021 else {
3022 mc_state = MC_SHUTDOWN;
3023 status_change();
3024 }
3025 break;
3026 default:
3027 fatal_error("MainController::perform_shutdown: called in wrong state.");
3028 }
3029 }
3030
3031 void MainController::clean_up()
3032 {
3033 shutdown_server();
3034
3035 while (unknown_head != NULL) close_unknown_connection(unknown_head);
3036
3037 destroy_all_components();
3038
3039 for (int i = 0; i < n_hosts; i++) {
3040 host_struct *host = hosts[i];
3041 close_hc_connection(host);
3042 Free(host->hostname);
3043 delete host->ip_addr;
3044 delete [] host->hostname_local;
3045 delete [] host->machine_type;
3046 delete [] host->system_name;
3047 delete [] host->system_release;
3048 delete [] host->system_version;
3049 Free(host->log_source);
3050 Free(host->components);
3051 free_string_set(&host->allowed_components);
3052 delete host;
3053 }
3054 Free(hosts);
3055 n_hosts = 0;
3056 hosts = NULL;
3057 Free(config_str);
3058 config_str = NULL;
3059
3060 while (timer_head != NULL) cancel_timer(timer_head);
3061
3062 for (int i = 0; i < n_modules; i++) {
3063 delete [] modules[i].module_name;
3064 delete [] modules[i].module_checksum;
3065 }
3066 delete [] modules;
3067 n_modules = 0;
3068 modules = NULL;
3069 version_known = FALSE;
3070
3071 #ifdef USE_EPOLL
3072 if (epfd >= 0) {
3073 if (close(epfd) < 0)
3074 error("MainController::clean_up: Error while closing epoll"
3075 " fd %d", epfd);
3076 epfd = -1;
3077 }
3078 Free(epoll_events);
3079 epoll_events = NULL;
3080 #else // ! defined USE_EPOLL
3081 nfds = 0;
3082 Free(ufds);
3083 ufds = NULL;
3084 new_nfds = 0;
3085 Free(new_ufds);
3086 new_ufds = NULL;
3087 pollfds_modified = FALSE;
3088 #endif
3089
3090 fd_table_size = 0;
3091 Free(fd_table);
3092 fd_table = NULL;
3093
3094 mc_state = MC_INACTIVE;
3095
3096 if (pipe_fd[1] >= 0) {
3097 close(pipe_fd[1]);
3098 pipe_fd[1] = -1;
3099 }
3100 if (pipe_fd[0] >= 0) {
3101 close(pipe_fd[1]);
3102 pipe_fd[0] = -1;
3103 }
3104 }
3105
3106 void MainController::send_configure(host_struct *hc, const char *config_file)
3107 {
3108 Text_Buf text_buf;
3109 text_buf.push_int(MSG_CONFIGURE);
3110 text_buf.push_string(config_file);
3111 send_message(hc->hc_fd, text_buf);
3112 }
3113
3114 void MainController::send_exit_hc(host_struct *hc)
3115 {
3116 Text_Buf text_buf;
3117 text_buf.push_int(MSG_EXIT_HC);
3118 send_message(hc->hc_fd, text_buf);
3119 }
3120
3121 void MainController::send_create_mtc(host_struct *hc)
3122 {
3123 Text_Buf text_buf;
3124 text_buf.push_int(MSG_CREATE_MTC);
3125 send_message(hc->hc_fd, text_buf);
3126 }
3127
3128 void MainController::send_create_ptc(host_struct *hc,
3129 component component_reference, const qualified_name& component_type,
3130 const char *component_name, boolean is_alive,
3131 const qualified_name& current_testcase)
3132 {
3133 Text_Buf text_buf;
3134 text_buf.push_int(MSG_CREATE_PTC);
3135 text_buf.push_int(component_reference);
3136 text_buf.push_qualified_name(component_type);
3137 text_buf.push_string(component_name);
3138 text_buf.push_int(is_alive ? 1 : 0);
3139 text_buf.push_qualified_name(current_testcase);
3140 send_message(hc->hc_fd, text_buf);
3141 }
3142
3143 void MainController::send_kill_process(host_struct *hc,
3144 component component_reference)
3145 {
3146 Text_Buf text_buf;
3147 text_buf.push_int(MSG_KILL_PROCESS);
3148 text_buf.push_int(component_reference);
3149 send_message(hc->hc_fd, text_buf);
3150 }
3151
3152 void MainController::send_create_ack(component_struct *tc,
3153 component component_reference)
3154 {
3155 Text_Buf text_buf;
3156 text_buf.push_int(MSG_CREATE_ACK);
3157 text_buf.push_int(component_reference);
3158 send_message(tc->tc_fd, text_buf);
3159 }
3160
3161 void MainController::send_start_ack(component_struct *tc)
3162 {
3163 Text_Buf text_buf;
3164 text_buf.push_int(MSG_START_ACK);
3165 send_message(tc->tc_fd, text_buf);
3166 }
3167
3168 void MainController::send_stop(component_struct *tc)
3169 {
3170 Text_Buf text_buf;
3171 text_buf.push_int(MSG_STOP);
3172 send_message(tc->tc_fd, text_buf);
3173 }
3174
3175 void MainController::send_stop_ack(component_struct *tc)
3176 {
3177 Text_Buf text_buf;
3178 text_buf.push_int(MSG_STOP_ACK);
3179 send_message(tc->tc_fd, text_buf);
3180 }
3181
3182 void MainController::send_kill_ack(component_struct *tc)
3183 {
3184 Text_Buf text_buf;
3185 text_buf.push_int(MSG_KILL_ACK);
3186 send_message(tc->tc_fd, text_buf);
3187 }
3188
3189 void MainController::send_running(component_struct *tc, boolean answer)
3190 {
3191 Text_Buf text_buf;
3192 text_buf.push_int(MSG_RUNNING);
3193 text_buf.push_int(answer ? 1 : 0);
3194 send_message(tc->tc_fd, text_buf);
3195 }
3196
3197 void MainController::send_alive(component_struct *tc, boolean answer)
3198 {
3199 Text_Buf text_buf;
3200 text_buf.push_int(MSG_ALIVE);
3201 text_buf.push_int(answer ? 1 : 0);
3202 send_message(tc->tc_fd, text_buf);
3203 }
3204
3205 void MainController::send_done_ack(component_struct *tc, boolean answer,
3206 const char *return_type, int return_value_len, const void *return_value)
3207 {
3208 Text_Buf text_buf;
3209 text_buf.push_int(MSG_DONE_ACK);
3210 text_buf.push_int(answer ? 1 : 0);
3211 text_buf.push_string(return_type);
3212 text_buf.push_raw(return_value_len, return_value);
3213 send_message(tc->tc_fd, text_buf);
3214 }
3215
3216 void MainController::send_killed_ack(component_struct *tc, boolean answer)
3217 {
3218 Text_Buf text_buf;
3219 text_buf.push_int(MSG_KILLED_ACK);
3220 text_buf.push_int(answer ? 1 : 0);
3221 send_message(tc->tc_fd, text_buf);
3222 }
3223
3224 void MainController::send_connect_listen(component_struct *tc,
3225 const char *local_port, component remote_comp, const char *remote_comp_name,
3226 const char *remote_port, transport_type_enum transport_type)
3227 {
3228 Text_Buf text_buf;
3229 text_buf.push_int(MSG_CONNECT_LISTEN);
3230 text_buf.push_string(local_port);
3231 text_buf.push_int(remote_comp);
3232 text_buf.push_string(remote_comp_name);
3233 text_buf.push_string(remote_port);
3234 text_buf.push_int(transport_type);
3235 send_message(tc->tc_fd, text_buf);
3236 }
3237
3238 void MainController::send_connect(component_struct *tc,
3239 const char *local_port, component remote_comp, const char *remote_comp_name,
3240 const char *remote_port, transport_type_enum transport_type,
3241 int remote_address_len, const void *remote_address)
3242 {
3243 Text_Buf text_buf;
3244 text_buf.push_int(MSG_CONNECT);
3245 text_buf.push_string(local_port);
3246 text_buf.push_int(remote_comp);
3247 text_buf.push_string(remote_comp_name);
3248 text_buf.push_string(remote_port);
3249 text_buf.push_int(transport_type);
3250 text_buf.push_raw(remote_address_len, remote_address);
3251 send_message(tc->tc_fd, text_buf);
3252 }
3253
3254 void MainController::send_connect_ack(component_struct *tc)
3255 {
3256 Text_Buf text_buf;
3257 text_buf.push_int(MSG_CONNECT_ACK);
3258 send_message(tc->tc_fd, text_buf);
3259 }
3260
3261 void MainController::send_disconnect(component_struct *tc,
3262 const char *local_port, component remote_comp, const char *remote_port)
3263 {
3264 Text_Buf text_buf;
3265 text_buf.push_int(MSG_DISCONNECT);
3266 text_buf.push_string(local_port);
3267 text_buf.push_int(remote_comp);
3268 text_buf.push_string(remote_port);
3269 send_message(tc->tc_fd, text_buf);
3270 }
3271
3272 void MainController::send_disconnect_ack(component_struct *tc)
3273 {
3274 Text_Buf text_buf;
3275 text_buf.push_int(MSG_DISCONNECT_ACK);
3276 send_message(tc->tc_fd, text_buf);
3277 }
3278
3279 void MainController::send_map(component_struct *tc,
3280 const char *local_port, const char *system_port)
3281 {
3282 Text_Buf text_buf;
3283 text_buf.push_int(MSG_MAP);
3284 text_buf.push_string(local_port);
3285 text_buf.push_string(system_port);
3286 send_message(tc->tc_fd, text_buf);
3287 }
3288
3289 void MainController::send_map_ack(component_struct *tc)
3290 {
3291 Text_Buf text_buf;
3292 text_buf.push_int(MSG_MAP_ACK);
3293 send_message(tc->tc_fd, text_buf);
3294 }
3295
3296 void MainController::send_unmap(component_struct *tc,
3297 const char *local_port, const char *system_port)
3298 {
3299 Text_Buf text_buf;
3300 text_buf.push_int(MSG_UNMAP);
3301 text_buf.push_string(local_port);
3302 text_buf.push_string(system_port);
3303 send_message(tc->tc_fd, text_buf);
3304 }
3305
3306 void MainController::send_unmap_ack(component_struct *tc)
3307 {
3308 Text_Buf text_buf;
3309 text_buf.push_int(MSG_UNMAP_ACK);
3310 send_message(tc->tc_fd, text_buf);
3311 }
3312
3313 void MainController::send_cancel_done_mtc(component component_reference,
3314 boolean cancel_any)
3315 {
3316 Text_Buf text_buf;
3317 text_buf.push_int(MSG_CANCEL_DONE);
3318 text_buf.push_int(component_reference);
3319 text_buf.push_int(cancel_any ? 1 : 0);
3320 send_message(mtc->tc_fd, text_buf);
3321 }
3322
3323 void MainController::send_component_status_mtc(component component_reference,
3324 boolean is_done, boolean is_killed, boolean is_any_done,
3325 boolean is_all_done, boolean is_any_killed, boolean is_all_killed,
3326 const char *return_type, int return_value_len, const void *return_value)
3327 {
3328 Text_Buf text_buf;
3329 text_buf.push_int(MSG_COMPONENT_STATUS);
3330 text_buf.push_int(component_reference);
3331 text_buf.push_int(is_done ? 1 : 0);
3332 text_buf.push_int(is_killed ? 1 : 0);
3333 text_buf.push_int(is_any_done ? 1 : 0);
3334 text_buf.push_int(is_all_done ? 1 : 0);
3335 text_buf.push_int(is_any_killed ? 1 : 0);
3336 text_buf.push_int(is_all_killed ? 1 : 0);
3337 text_buf.push_string(return_type);
3338 text_buf.push_raw(return_value_len, return_value);
3339 send_message(mtc->tc_fd, text_buf);
3340 }
3341
3342 void MainController::send_execute_control(const char *module_name)
3343 {
3344 Text_Buf text_buf;
3345 text_buf.push_int(MSG_EXECUTE_CONTROL);
3346 text_buf.push_string(module_name);
3347 send_message(mtc->tc_fd, text_buf);
3348 }
3349
3350 void MainController::send_execute_testcase(const char *module_name,
3351 const char *testcase_name)
3352 {
3353 Text_Buf text_buf;
3354 text_buf.push_int(MSG_EXECUTE_TESTCASE);
3355 text_buf.push_string(module_name);
3356 text_buf.push_string(testcase_name);
3357 send_message(mtc->tc_fd, text_buf);
3358 }
3359
3360 void MainController::send_ptc_verdict(boolean continue_execution)
3361 {
3362 Text_Buf text_buf;
3363 text_buf.push_int(MSG_PTC_VERDICT);
3364 int n_ptcs = 0;
3365 for (int i = tc_first_comp_ref; i < n_components; i++)
3366 if (components[i]->tc_state != PTC_STALE) n_ptcs++;
3367 text_buf.push_int(n_ptcs);
3368 for (int i = tc_first_comp_ref; i < n_components; i++) {
3369 if (components[i]->tc_state != PTC_STALE) {
3370 text_buf.push_int(components[i]->comp_ref);
3371 text_buf.push_string(components[i]->comp_name);
3372 text_buf.push_int(components[i]->local_verdict);
3373 if (components[i]->verdict_reason != NULL)
3374 text_buf.push_string(components[i]->verdict_reason);
3375 else
3376 text_buf.push_string("");
3377 }
3378 }
3379 text_buf.push_int(continue_execution ? 1 : 0);
3380 send_message(mtc->tc_fd, text_buf);
3381 }
3382
3383 void MainController::send_continue()
3384 {
3385 Text_Buf text_buf;
3386 text_buf.push_int(MSG_CONTINUE);
3387 send_message(mtc->tc_fd, text_buf);
3388 }
3389
3390 void MainController::send_exit_mtc()
3391 {
3392 Text_Buf text_buf;
3393 text_buf.push_int(MSG_EXIT_MTC);
3394 send_message(mtc->tc_fd, text_buf);
3395 }
3396
3397 void MainController::send_cancel_done_ptc(component_struct *tc,
3398 component component_reference)
3399 {
3400 Text_Buf text_buf;
3401 text_buf.push_int(MSG_CANCEL_DONE);
3402 text_buf.push_int(component_reference);
3403 send_message(tc->tc_fd, text_buf);
3404
3405 }
3406
3407 void MainController::send_component_status_ptc(component_struct *tc,
3408 component component_reference, boolean is_done, boolean is_killed,
3409 const char *return_type, int return_value_len, const void *return_value)
3410 {
3411 Text_Buf text_buf;
3412 text_buf.push_int(MSG_COMPONENT_STATUS);
3413 text_buf.push_int(component_reference);
3414 text_buf.push_int(is_done ? 1 : 0);
3415 text_buf.push_int(is_killed ? 1 : 0);
3416 text_buf.push_string(return_type);
3417 text_buf.push_raw(return_value_len, return_value);
3418 send_message(tc->tc_fd, text_buf);
3419 }
3420
3421 void MainController::send_start(component_struct *tc,
3422 const qualified_name& function_name, int arg_len, const void *arg_ptr)
3423 {
3424 Text_Buf text_buf;
3425 text_buf.push_int(MSG_START);
3426 text_buf.push_qualified_name(function_name);
3427 text_buf.push_raw(arg_len, arg_ptr);
3428 send_message(tc->tc_fd, text_buf);
3429 }
3430
3431 void MainController::send_kill(component_struct *tc)
3432 {
3433 Text_Buf text_buf;
3434 text_buf.push_int(MSG_KILL);
3435 send_message(tc->tc_fd, text_buf);
3436 }
3437
3438 void MainController::send_error(int fd, const char *fmt, ...)
3439 {
3440 va_list ap;
3441 va_start(ap, fmt);
3442 char *reason = mprintf_va_list(fmt, ap);
3443 va_end(ap);
3444 send_error_str(fd, reason);
3445 Free(reason);
3446 }
3447
3448 void MainController::send_error_str(int fd, const char *reason)
3449 {
3450 Text_Buf text_buf;
3451 text_buf.push_int((RInt)MSG_ERROR);
3452 text_buf.push_string(reason);
3453 send_message(fd, text_buf);
3454 }
3455
3456 void MainController::send_message(int fd, Text_Buf& text_buf)
3457 {
3458 text_buf.calculate_length();
3459 const char *send_ptr = text_buf.get_data();
3460 int send_len = text_buf.get_len();
3461 int sent_len = send(fd, send_ptr, send_len, 0);
3462 if (send_len != sent_len) {
3463 error("Sending of message failed: %s", strerror(errno));
3464 }
3465 }
3466
3467 void MainController::process_error(unknown_connection *conn)
3468 {
3469 Text_Buf& text_buf = *conn->text_buf;
3470 char *reason = text_buf.pull_string();
3471 error("Error message was received on an unknown connection from %s [%s]: "
3472 "%s.", conn->ip_addr->get_host_str(), conn->ip_addr->get_addr_str(), reason);
3473 delete [] reason;
3474 text_buf.cut_message();
3475 status_change();
3476 }
3477
3478 void MainController::process_log(unknown_connection *conn)
3479 {
3480 Text_Buf& text_buf = *conn->text_buf;
3481 struct timeval tv;
3482 tv.tv_sec = text_buf.pull_int().get_val();
3483 tv.tv_usec = text_buf.pull_int().get_val();
3484 char *source = mprintf("<unknown>@%s", conn->ip_addr->get_host_str());
3485 int severity = text_buf.pull_int().get_val();
3486 char *message = text_buf.pull_string();
3487 notify(&tv, source, severity, message);
3488 Free(source);
3489 delete [] message;
3490 }
3491
3492 void MainController::process_version(unknown_connection *conn)
3493 {
3494 if (check_version(conn)) {
3495 error("HC connection from %s [%s] was refused because of "
3496 "incorrect version.", conn->ip_addr->get_host_str(),
3497 conn->ip_addr->get_addr_str());
3498 close_unknown_connection(conn);
3499 return;
3500 }
3501 host_struct *hc = add_new_host(conn);
3502 switch (mc_state) {
3503 case MC_LISTENING:
3504 mc_state = MC_HC_CONNECTED;
3505 case MC_HC_CONNECTED:
3506 break;
3507 case MC_LISTENING_CONFIGURED:
3508 case MC_ACTIVE:
3509 configure_host(hc, TRUE);
3510 mc_state = MC_CONFIGURING;
3511 break;
3512 case MC_SHUTDOWN:
3513 send_exit_hc(hc);
3514 hc->hc_state = HC_EXITING;
3515 break;
3516 default:
3517 configure_host(hc, TRUE);
3518 }
3519 // handle the remaining messages that are in hc->text_buf
3520 handle_hc_data(hc, FALSE);
3521 status_change();
3522 }
3523
3524 void MainController::process_mtc_created(unknown_connection *conn)
3525 {
3526 int fd = conn->fd;
3527 if (mc_state != MC_CREATING_MTC) {
3528 send_error_str(fd, "Message MTC_CREATED arrived in invalid state.");
3529 close_unknown_connection(conn);
3530 return;
3531 }
3532 if (mtc == NULL || mtc->tc_state != TC_INITIAL)
3533 fatal_error("MainController::process_mtc_created: MTC is in invalid "
3534 "state.");
3535 if (!conn->unix_socket &&
3536 *(mtc->comp_location->ip_addr) != *(conn->ip_addr)) {
3537 send_error(fd, "Message MTC_CREATED arrived from an unexpected "
3538 "IP address. It is accepted only from %s.",
3539 mtc->comp_location->ip_addr->get_addr_str());
3540 close_unknown_connection(conn);
3541 return;
3542 }
3543
3544 mc_state = MC_READY;
3545 mtc->tc_state = TC_IDLE;
3546 mtc->tc_fd = fd;
3547 fd_table[fd].fd_type = FD_TC;
3548 fd_table[fd].component_ptr = mtc;
3549 Text_Buf *text_buf = conn->text_buf;
3550 text_buf->cut_message();
3551 mtc->text_buf = text_buf;
3552 delete [] mtc->initial.location_str;
3553
3554 delete_unknown_connection(conn);
3555
3556 notify("MTC is created.");
3557 // handle the remaining messages that are in text_buf
3558 handle_tc_data(mtc, FALSE);
3559 status_change();
3560 }
3561
3562 void MainController::process_ptc_created(unknown_connection *conn)
3563 {
3564 int fd = conn->fd;
3565
3566 switch (mc_state) {
3567 case MC_EXECUTING_TESTCASE:
3568 case MC_TERMINATING_TESTCASE:
3569 break;
3570 default:
3571 send_error_str(fd, "Message PTC_CREATED arrived in invalid state.");
3572 close_unknown_connection(conn);
3573 return;
3574 }
3575
3576 Text_Buf *text_buf = conn->text_buf;
3577 component component_reference = text_buf->pull_int().get_val();
3578
3579 switch (component_reference) {
3580 case NULL_COMPREF:
3581 send_error_str(fd, "Message PTC_CREATED refers to the null component "
3582 "reference.");
3583 close_unknown_connection(conn);
3584 return;
3585 case MTC_COMPREF:
3586 send_error_str(fd, "Message PTC_CREATED refers to the component "
3587 "reference of the MTC.");
3588 close_unknown_connection(conn);
3589 return;
3590 case SYSTEM_COMPREF:
3591 send_error_str(fd, "Message PTC_CREATED refers to the component "
3592 "reference of the system.");
3593 close_unknown_connection(conn);
3594 return;
3595 case ANY_COMPREF:
3596 send_error_str(fd, "Message PTC_CREATED refers to 'any component'.");
3597 close_unknown_connection(conn);
3598 return;
3599 case ALL_COMPREF:
3600 send_error_str(fd, "Message PTC_CREATED refers to 'all component'.");
3601 close_unknown_connection(conn);
3602 return;
3603 }
3604
3605 component_struct *tc = lookup_component(component_reference);
3606 if (tc == NULL) {
3607 send_error(fd, "Message PTC_CREATED refers to invalid component "
3608 "reference %d.", component_reference);
3609 close_unknown_connection(conn);
3610 return;
3611 } else if (tc->tc_state != TC_INITIAL) {
3612 send_error(fd, "Message PTC_CREATED refers to test component "
3613 "%d, which is not being created.", component_reference);
3614 close_unknown_connection(conn);
3615 return;
3616 } else if (!conn->unix_socket && *(conn->ip_addr) != *(tc->comp_location->ip_addr)) {
3617 char *real_hostname = mprintf("%s [%s]", conn->ip_addr->get_host_str(),
3618 conn->ip_addr->get_addr_str());
3619 char *expected_hostname = mprintf("%s [%s]",
3620 tc->comp_location->hostname, tc->comp_location->ip_addr->get_addr_str());
3621 send_error(fd, "Invalid source host (%s) for the control "
3622 "connection. Expected: %s.", real_hostname, expected_hostname);
3623 error("Connection of PTC %d arrived from an unexpected "
3624 "IP address (%s). Expected: %s.", component_reference,
3625 real_hostname, expected_hostname);
3626 Free(real_hostname);
3627 Free(expected_hostname);
3628 close_unknown_connection(conn);
3629 return;
3630 }
3631
3632 tc->tc_state = TC_IDLE;
3633 tc->tc_fd = fd;
3634 fd_table[fd].fd_type = FD_TC;
3635 fd_table[fd].component_ptr = tc;
3636 text_buf->cut_message();
3637 tc->text_buf = text_buf;
3638 delete [] tc->initial.location_str;
3639
3640 delete_unknown_connection(conn);
3641
3642 if (mc_state == MC_TERMINATING_TESTCASE || mtc->stop_requested ||
3643 mtc->tc_state == MTC_ALL_COMPONENT_KILL ||
3644 (mtc->tc_state == MTC_ALL_COMPONENT_STOP && !tc->is_alive)) {
3645 send_kill(tc);
3646 tc->tc_state = PTC_KILLING;
3647 if (!tc->is_alive) tc->stop_requested = TRUE;
3648 init_requestors(&tc->stopping_killing.stop_requestors, NULL);
3649 init_requestors(&tc->stopping_killing.kill_requestors, NULL);
3650 start_kill_timer(tc);
3651 } else {
3652 component_struct *create_requestor = tc->initial.create_requestor;
3653 if (create_requestor->tc_state == TC_CREATE) {
3654 send_create_ack(create_requestor, component_reference);
3655 if (create_requestor == mtc)
3656 create_requestor->tc_state = MTC_TESTCASE;
3657 else create_requestor->tc_state = PTC_FUNCTION;
3658 }
3659 }
3660 // handle the remaining messages that are in text_buf
3661 handle_tc_data(tc, FALSE);
3662 status_change();
3663 }
3664
3665 void MainController::process_error(host_struct *hc)
3666 {
3667 char *reason = hc->text_buf->pull_string();
3668 error("Error message was received from HC at %s [%s]: %s",
3669 hc->hostname, hc->ip_addr->get_addr_str(), reason);
3670 delete [] reason;
3671 }
3672
3673 void MainController::process_log(host_struct *hc)
3674 {
3675 Text_Buf& text_buf = *hc->text_buf;
3676 struct timeval tv;
3677 tv.tv_sec = text_buf.pull_int().get_val();
3678 tv.tv_usec = text_buf.pull_int().get_val();
3679 int severity = text_buf.pull_int().get_val();
3680 char *message = text_buf.pull_string();
3681 notify(&tv, hc->log_source, severity, message);
3682 delete [] message;
3683 }
3684
3685 void MainController::process_configure_ack(host_struct *hc)
3686 {
3687 switch (hc->hc_state) {
3688 case HC_CONFIGURING:
3689 hc->hc_state = HC_ACTIVE;
3690 break;
3691 case HC_CONFIGURING_OVERLOADED:
3692 hc->hc_state = HC_OVERLOADED;
3693 break;
3694 default:
3695 send_error_str(hc->hc_fd, "Unexpected message CONFIGURE_ACK was "
3696 "received.");
3697 return;
3698 }
3699 if (mc_state == MC_CONFIGURING) check_all_hc_configured();
3700 else notify("Host %s was configured successfully.", hc->hostname);
3701 status_change();
3702 }
3703
3704 void MainController::process_configure_nak(host_struct *hc)
3705 {
3706 switch (hc->hc_state) {
3707 case HC_CONFIGURING:
3708 case HC_CONFIGURING_OVERLOADED:
3709 hc->hc_state = HC_IDLE;
3710 break;
3711 default:
3712 send_error_str(hc->hc_fd, "Unexpected message CONFIGURE_NAK was "
3713 "received.");
3714 return;
3715 }
3716 if (mc_state == MC_CONFIGURING) check_all_hc_configured();
3717 else notify("Processing of configuration file failed on host %s.",
3718 hc->hostname);
3719 status_change();
3720 }
3721
3722 void MainController::process_create_nak(host_struct *hc)
3723 {
3724 switch (mc_state) {
3725 case MC_CREATING_MTC:
3726 case MC_EXECUTING_TESTCASE:
3727 case MC_TERMINATING_TESTCASE:
3728 break;
3729 default:
3730 send_error_str(hc->hc_fd, "Message CREATE_NAK arrived in invalid "
3731 "state.");
3732 return;
3733 }
3734
3735 switch (hc->hc_state) {
3736 case HC_ACTIVE:
3737 notify("Host %s is overloaded. New components will not be created "
3738 "there until further notice.", hc->hostname);
3739 hc->hc_state = HC_OVERLOADED;
3740 // no break
3741 case HC_OVERLOADED:
3742 break;
3743 default:
3744 send_error_str(hc->hc_fd, "Unexpected message CREATE_NAK was received: "
3745 "the sender is in invalid state.");
3746 return;
3747 }
3748
3749 Text_Buf& text_buf = *hc->text_buf;
3750 component component_reference = text_buf.pull_int().get_val();
3751
3752 switch (component_reference) {
3753 case NULL_COMPREF:
3754 send_error_str(hc->hc_fd, "Message CREATE_NAK refers to the null "
3755 "component reference.");
3756 return;
3757 case SYSTEM_COMPREF:
3758 send_error_str(hc->hc_fd, "Message CREATE_NAK refers to the component "
3759 "reference of the system.");
3760 return;
3761 case ANY_COMPREF:
3762 send_error_str(hc->hc_fd, "Message CREATE_NAK refers to "
3763 "'any component'.");
3764 return;
3765 case ALL_COMPREF:
3766 send_error_str(hc->hc_fd, "Message CREATE_NAK refers to "
3767 "'all component'.");
3768 return;
3769 }
3770
3771 component_struct *tc = lookup_component(component_reference);
3772 if (tc == NULL) {
3773 send_error(hc->hc_fd, "Message CREATE_NAK refers to invalid component "
3774 "reference %d.", component_reference);
3775 return;
3776 }
3777 if (tc->tc_state != TC_INITIAL) {
3778 send_error(hc->hc_fd, "Message CREATE_NAK refers to test component "
3779 "%d, which is not being created.", component_reference);
3780 return;
3781 }
3782 if (tc->comp_location != hc) {
3783 send_error(hc->hc_fd, "Message CREATE_NAK refers to test component "
3784 "%d, which was assigned to a different host (%s).",
3785 component_reference, tc->comp_location->hostname);
3786 return;
3787 }
3788
3789 remove_component_from_host(tc);
3790 hc->n_active_components--;
3791
3792 char *reason = text_buf.pull_string();
3793
3794 if (tc == mtc) {
3795 if (mc_state != MC_CREATING_MTC)
3796 fatal_error("MainController::process_create_nak: MC is in "
3797 "unexpected state when CREATE_NAK refers to MTC.");
3798 error("Creation of MTC failed on host %s: %s.", hc->hostname, reason);
3799 destroy_all_components();
3800 mc_state = MC_ACTIVE;
3801 } else {
3802 host_struct *new_host = choose_ptc_location(
3803 tc->comp_type.definition_name, tc->comp_name,
3804 tc->initial.location_str);
3805 if (new_host != NULL) {
3806 send_create_ptc(new_host, component_reference, tc->comp_type,
3807 tc->comp_name, tc->is_alive, mtc->tc_fn_name);
3808 notify("PTC with component reference %d was relocated from host "
3809 "%s to %s because of overload: %s.", component_reference,
3810 hc->hostname, new_host->hostname, reason);
3811 add_component_to_host(new_host, tc);
3812 new_host->n_active_components++;
3813 } else {
3814 char *comp_data = mprintf("component type: %s.%s",
3815 tc->comp_type.module_name, tc->comp_type.definition_name);
3816 if (tc->comp_name != NULL)
3817 comp_data = mputprintf(comp_data, ", name: %s", tc->comp_name);
3818 if (tc->initial.location_str != NULL &&
3819 tc->initial.location_str[0] != '\0')
3820 comp_data = mputprintf(comp_data, ", location: %s",
3821 tc->initial.location_str);
3822 component_struct *create_requestor = tc->initial.create_requestor;
3823 if (create_requestor->tc_state == TC_CREATE) {
3824 send_error(create_requestor->tc_fd, "Creation of the new PTC "
3825 "(%s) failed on host %s: %s. Other suitable hosts to "
3826 "relocate the component are not available.", comp_data,
3827 hc->hostname, reason);
3828 if (create_requestor == mtc)
3829 create_requestor->tc_state = MTC_TESTCASE;
3830 else create_requestor->tc_state = PTC_FUNCTION;
3831 }
3832 delete [] tc->initial.location_str;
3833 tc->tc_state = PTC_STALE;
3834 n_active_ptcs--;
3835 switch (mtc->tc_state) {
3836 case MTC_TERMINATING_TESTCASE:
3837 if (ready_to_finish_testcase()) finish_testcase();
3838 break;
3839 case MTC_ALL_COMPONENT_KILL:
3840 check_all_component_kill();
3841 break;
3842 case MTC_ALL_COMPONENT_STOP:
3843 check_all_component_stop();
3844 break;
3845 default:
3846 break;
3847 }
3848 notify("Creation of a PTC (%s) failed on host %s: %s. "
3849 "Relocation to other suitable host is not possible.",
3850 comp_data, hc->hostname, reason);
3851 Free(comp_data);
3852 }
3853 }
3854
3855 delete [] reason;
3856
3857 status_change();
3858 }
3859
3860 void MainController::process_hc_ready(host_struct *hc)
3861 {
3862 switch(hc->hc_state) {
3863 case HC_OVERLOADED:
3864 hc->hc_state = HC_ACTIVE;
3865 break;
3866 case HC_CONFIGURING_OVERLOADED:
3867 hc->hc_state = HC_CONFIGURING;
3868 break;
3869 default:
3870 send_error_str(hc->hc_fd, "Unexpected message HC_READY was received.");
3871 return;
3872 }
3873 notify("Host %s is no more overloaded.", hc->hostname);
3874 status_change();
3875 }
3876
3877 void MainController::process_error(component_struct *tc)
3878 {
3879 char *reason = tc->text_buf->pull_string();
3880 if (tc == mtc) {
3881 error("Error message was received from the MTC at %s [%s]: %s",
3882 mtc->comp_location->hostname,
3883 mtc->comp_location->ip_addr->get_addr_str(), reason);
3884 } else {
3885 notify("Error message was received from PTC %d at %s [%s]: %s",
3886 tc->comp_ref, tc->comp_location->hostname,
3887 tc->comp_location->ip_addr->get_addr_str(), reason);
3888 }
3889 delete [] reason;
3890 }
3891
3892 void MainController::process_log(component_struct *tc)
3893 {
3894 Text_Buf& text_buf = *tc->text_buf;
3895 struct timeval tv;
3896 tv.tv_sec = text_buf.pull_int().get_val();
3897 tv.tv_usec = text_buf.pull_int().get_val();
3898 int severity = text_buf.pull_int().get_val();
3899 char *message = text_buf.pull_string();
3900 notify(&tv, tc->log_source, severity, message);
3901 delete [] message;
3902 }
3903
3904 void MainController::process_create_req(component_struct *tc)
3905 {
3906 if (!request_allowed(tc, "CREATE_REQ")) return;
3907
3908 if (max_ptcs >= 0 && n_active_ptcs >= max_ptcs) {
3909 send_error(tc->tc_fd, "The license key does not allow more than %d "
3910 "simultaneously active PTCs.", max_ptcs);
3911 return;
3912 }
3913
3914 Text_Buf& text_buf = *tc->text_buf;
3915 qualified_name component_type;
3916 text_buf.pull_qualified_name(component_type);
3917 char *component_name = text_buf.pull_string();
3918 if (component_name[0] == '\0') {
3919 delete [] component_name;
3920 component_name = NULL;
3921 }
3922 char *component_location = text_buf.pull_string();
3923 if (component_location[0] == '\0') {
3924 delete [] component_location;
3925 component_location = NULL;
3926 }
3927 boolean is_alive = text_buf.pull_int().get_val();
3928
3929 host_struct *host = choose_ptc_location(component_type.definition_name,
3930 component_name, component_location);
3931
3932 if (host == NULL) {
3933 if (!is_hc_in_state(HC_ACTIVE)) {
3934 send_error_str(tc->tc_fd, "There is no active HC connection. "
3935 "Create operation cannot be performed.");
3936 } else {
3937 char *comp_data = mprintf("component type: %s.%s",
3938 component_type.module_name, component_type.definition_name);
3939 if (component_name != NULL)
3940 comp_data = mputprintf(comp_data, ", name: %s", component_name);
3941 if (component_location != NULL)
3942 comp_data = mputprintf(comp_data, ", location: %s",
3943 component_location);
3944 send_error(tc->tc_fd, "No suitable host was found to create a "
3945 "new PTC (%s).", comp_data);
3946 Free(comp_data);
3947 }
3948 free_qualified_name(&component_type);
3949 delete [] component_name;
3950 delete [] component_location;
3951 return;
3952 }
3953
3954 component comp_ref = next_comp_ref++;
3955 send_create_ptc(host, comp_ref, component_type, component_name, is_alive,
3956 mtc->tc_fn_name);
3957
3958 tc->tc_state = TC_CREATE;
3959
3960 component_struct *new_ptc = new component_struct;
3961 new_ptc->comp_ref = comp_ref;
3962 new_ptc->comp_type = component_type;
3963 new_ptc->comp_name = component_name;
3964 new_ptc->tc_state = TC_INITIAL;
3965 new_ptc->local_verdict = NONE;
3966 new_ptc->verdict_reason = NULL;
3967 new_ptc->tc_fd = -1;
3968 new_ptc->text_buf = NULL;
3969 init_qualified_name(&new_ptc->tc_fn_name);
3970 new_ptc->return_type = NULL;
3971 new_ptc->return_value_len = 0;
3972 new_ptc->return_value = NULL;
3973 new_ptc->is_alive = is_alive;
3974 new_ptc->stop_requested = FALSE;
3975 new_ptc->process_killed = FALSE;
3976 new_ptc->initial.create_requestor = tc;
3977 new_ptc->initial.location_str = component_location;
3978 init_requestors(&new_ptc->done_requestors, NULL);
3979 init_requestors(&new_ptc->killed_requestors, NULL);
3980 init_requestors(&new_ptc->cancel_done_sent_for, NULL);
3981 new_ptc->kill_timer = NULL;
3982 init_connections(new_ptc);
3983
3984 add_component(new_ptc);
3985 add_component_to_host(host, new_ptc);
3986 host->n_active_components++;
3987 n_active_ptcs++;
3988
3989 status_change();
3990 }
3991
3992 void MainController::process_start_req(component_struct *tc, int message_end)
3993 {
3994 if (!request_allowed(tc, "START_REQ")) return;
3995
3996 Text_Buf& text_buf = *tc->text_buf;
3997 component component_reference = text_buf.pull_int().get_val();
3998 switch (component_reference) {
3999 case NULL_COMPREF:
4000 send_error_str(tc->tc_fd, "Start operation was requested on the null "
4001 "component reference.");
4002 return;
4003 case MTC_COMPREF:
4004 send_error_str(tc->tc_fd, "Start operation was requested on the "
4005 "component reference of the MTC.");
4006 return;
4007 case SYSTEM_COMPREF:
4008 send_error_str(tc->tc_fd, "Start operation was requested on the "
4009 "component reference of the system.");
4010 return;
4011 case ANY_COMPREF:
4012 send_error_str(tc->tc_fd, "Start operation was requested on "
4013 "'any component'.");
4014 return;
4015 case ALL_COMPREF:
4016 send_error_str(tc->tc_fd, "Start operation was requested on "
4017 "'all component'.");
4018 return;
4019 }
4020 component_struct *target = lookup_component(component_reference);
4021 if (target == NULL) {
4022 send_error(tc->tc_fd, "Start operation was requested on invalid "
4023 "component reference: %d.", component_reference);
4024 return;
4025 }
4026 switch (target->tc_state) {
4027 case TC_IDLE:
4028 case PTC_STOPPED:
4029 // these states are correct
4030 break;
4031 case TC_CREATE:
4032 case TC_START:
4033 case TC_STOP:
4034 case TC_KILL:
4035 case TC_CONNECT:
4036 case TC_DISCONNECT:
4037 case TC_MAP:
4038 case TC_UNMAP:
4039 case PTC_FUNCTION:
4040 case PTC_STARTING:
4041 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4042 "started because it is already executing function %s.%s.",
4043 component_reference, target->tc_fn_name.module_name,
4044 target->tc_fn_name.definition_name);
4045 return;
4046 case TC_STOPPING:
4047 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4048 "started because it function %s.%s is currently being stopped on "
4049 "it.", component_reference, target->tc_fn_name.module_name,
4050 target->tc_fn_name.definition_name);
4051 return;
4052 case PTC_KILLING:
4053 case PTC_STOPPING_KILLING:
4054 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4055 "started because it is currently being killed.",
4056 component_reference);
4057 return;
4058 case TC_EXITING:
4059 case TC_EXITED:
4060 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4061 "started because it is not alive anymore.", component_reference);
4062 return;
4063 case PTC_STALE:
4064 send_error(tc->tc_fd, "The argument of start operation (%d) is a "
4065 "component reference that belongs to an earlier testcase.",
4066 component_reference);
4067 return;
4068 default:
4069 send_error(tc->tc_fd, "Start operation was requested on component "
4070 "reference %d, which is in invalid state.",
4071 component_reference);
4072 return;
4073 }
4074 text_buf.pull_qualified_name(target->tc_fn_name);
4075 target->stop_requested = FALSE;
4076 int arg_begin = text_buf.get_pos();
4077 int arg_len = message_end - arg_begin;
4078 const void *arg_ptr = text_buf.get_data() + arg_begin;
4079 boolean send_cancel_done = FALSE, cancel_any_component_done = FALSE;
4080 if (target->tc_state == PTC_STOPPED) {
4081 // updating the state of target because 'any component.done' cannot
4082 // consider this component anymore
4083 target->tc_state = PTC_STARTING;
4084 // cleaning up the previous return value
4085 delete [] target->return_type;
4086 target->return_type = NULL;
4087 target->return_value_len = 0;
4088 Free(target->return_value);
4089 target->return_value = NULL;
4090 // determining which components we need to send CANCEL_DONE to
4091 init_requestors(&target->starting.cancel_done_sent_to, NULL);
4092 for (int i = 0; ; i++) {
4093 component_struct *comp = get_requestor(&target->done_requestors, i);
4094 if (comp == NULL) break;
4095 else if (comp == tc) {
4096 // the start requestor shall cancel the done status locally
4097 // ignore it
4098 continue;
4099 }
4100 switch (comp->tc_state) {
4101 case TC_CREATE:
4102 case TC_START:
4103 case TC_STOP:
4104 case TC_KILL:
4105 case TC_CONNECT:
4106 case TC_DISCONNECT:
4107 case TC_MAP:
4108 case TC_UNMAP:
4109 case TC_STOPPING:
4110 case MTC_TESTCASE:
4111 case PTC_FUNCTION:
4112 case PTC_STARTING:
4113 case PTC_STOPPED:
4114 // a CANCEL_DONE message shall be sent to comp
4115 send_cancel_done = TRUE;
4116 add_requestor(&target->starting.cancel_done_sent_to, comp);
4117 break;
4118 case TC_EXITING:
4119 case TC_EXITED:
4120 case PTC_KILLING:
4121 case PTC_STOPPING_KILLING:
4122 // CANCEL_DONE will not be sent to comp
4123 break;
4124 default:
4125 error("Test Component %d is in invalid state when starting "
4126 "PTC %d.", comp->comp_ref, component_reference);
4127 }
4128 }
4129 // check whether 'any component.done' needs to be cancelled
4130 if (any_component_done_sent && !is_any_component_done()) {
4131 send_cancel_done = TRUE;
4132 cancel_any_component_done = TRUE;
4133 any_component_done_sent = FALSE;
4134 add_requestor(&target->starting.cancel_done_sent_to, mtc);
4135 }
4136 free_requestors(&target->done_requestors);
4137 }
4138 if (send_cancel_done) {
4139 for (int i = 0; ; i++) {
4140 component_struct *comp =
4141 get_requestor(&target->starting.cancel_done_sent_to, i);
4142 if (comp == NULL) break;
4143 else if (comp == mtc) send_cancel_done_mtc(component_reference,
4144 cancel_any_component_done);
4145 else send_cancel_done_ptc(comp, component_reference);
4146 add_requestor(&comp->cancel_done_sent_for, target);
4147 }
4148 target->starting.start_requestor = tc;
4149 target->starting.arguments_len = arg_len;
4150 target->starting.arguments_ptr = Malloc(arg_len);
4151 memcpy(target->starting.arguments_ptr, arg_ptr, arg_len);
4152 tc->tc_state = TC_START;
4153 } else {
4154 send_start(target, target->tc_fn_name, arg_len, arg_ptr);
4155 send_start_ack(tc);
4156 target->tc_state = PTC_FUNCTION;
4157 }
4158 status_change();
4159 }
4160
4161 void MainController::process_stop_req(component_struct *tc)
4162 {
4163 if (!request_allowed(tc, "STOP_REQ")) return;
4164
4165 component component_reference = tc->text_buf->pull_int().get_val();
4166 switch (component_reference) {
4167 case NULL_COMPREF:
4168 send_error_str(tc->tc_fd, "Stop operation was requested on the null "
4169 "component reference.");
4170 return;
4171 case MTC_COMPREF:
4172 // 'mtc.stop' initiated by a PTC terminates the current testcase
4173 if (tc != mtc) {
4174 if (!mtc->stop_requested) {
4175 send_stop(mtc);
4176 kill_all_components(TRUE);
4177 mtc->stop_requested = TRUE;
4178 start_kill_timer(mtc);
4179 notify("Test Component %d has requested to stop MTC. "
4180 "Terminating current testcase execution.", tc->comp_ref);
4181 status_change();
4182 }
4183 } else send_error_str(tc->tc_fd, "MTC has requested to stop itself.");
4184 return;
4185 case SYSTEM_COMPREF:
4186 send_error_str(tc->tc_fd, "Stop operation was requested on the "
4187 "component reference of the system.");
4188 return;
4189 case ANY_COMPREF:
4190 send_error_str(tc->tc_fd, "Stop operation was requested on "
4191 "'any component'.");
4192 return;
4193 case ALL_COMPREF:
4194 if (tc == mtc) {
4195 if (stop_all_components()) send_stop_ack(mtc);
4196 else {
4197 mtc->tc_state = MTC_ALL_COMPONENT_STOP;
4198 status_change();
4199 }
4200 } else send_error_str(tc->tc_fd, "Operation 'all component.stop' can "
4201 "only be performed on the MTC.");
4202 return;
4203 default:
4204 break;
4205 }
4206 // the operation refers to a specific PTC
4207 component_struct *target = lookup_component(component_reference);
4208 if (target == NULL) {
4209 send_error(tc->tc_fd, "The argument of stop operation is an "
4210 "invalid component reference: %d.", component_reference);
4211 return;
4212 } else if (target == tc) {
4213 send_error_str(tc->tc_fd, "Stop operation was requested on the "
4214 "requestor component itself.");
4215 return;
4216 }
4217 boolean target_inactive = FALSE;
4218 switch (target->tc_state) {
4219 case PTC_STOPPED:
4220 if (!target->is_alive) error("PTC %d cannot be in state STOPPED "
4221 "because it is not an alive type PTC.", component_reference);
4222 // no break
4223 case TC_IDLE:
4224 target_inactive = TRUE;
4225 // no break
4226 case TC_CREATE:
4227 case TC_START:
4228 case TC_STOP:
4229 case TC_KILL:
4230 case TC_CONNECT:
4231 case TC_DISCONNECT:
4232 case TC_MAP:
4233 case TC_UNMAP:
4234 case PTC_FUNCTION:
4235 if (target->is_alive) {
4236 if (target_inactive) {
4237 // do nothing, just send a STOP_ACK to tc
4238 send_stop_ack(tc);
4239 break;
4240 } else {
4241 send_stop(target);
4242 target->tc_state = TC_STOPPING;
4243 }
4244 } else {
4245 // the target is not an alive type PTC: stop operation means kill
4246 send_kill(target);
4247 if (target_inactive) target->tc_state = PTC_KILLING;
4248 else target->tc_state = PTC_STOPPING_KILLING;
4249 }
4250 // a STOP or KILL message was sent out
4251 target->stop_requested = TRUE;
4252 init_requestors(&target->stopping_killing.stop_requestors, tc);
4253 init_requestors(&target->stopping_killing.kill_requestors, NULL);
4254 start_kill_timer(target);
4255 tc->tc_state = TC_STOP;
4256 status_change();
4257 break;
4258 case PTC_KILLING:
4259 if (target->is_alive) {
4260 // do nothing if the PTC is alive
4261 send_stop_ack(tc);
4262 break;
4263 }
4264 // no break
4265 case TC_STOPPING:
4266 case PTC_STOPPING_KILLING:
4267 // the PTC is currently being stopped
4268 add_requestor(&target->stopping_killing.stop_requestors, tc);
4269 tc->tc_state = TC_STOP;
4270 status_change();
4271 break;
4272 case TC_EXITING:
4273 case TC_EXITED:
4274 // the PTC is already terminated, do nothing
4275 send_stop_ack(tc);
4276 break;
4277 case PTC_STARTING:
4278 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4279 "stopped because it is currently being started.",
4280 component_reference);
4281 break;
4282 case PTC_STALE:
4283 send_error(tc->tc_fd, "The argument of stop operation (%d) is a "
4284 "component reference that belongs to an earlier testcase.",
4285 component_reference);
4286 break;
4287 default:
4288 send_error(tc->tc_fd, "The test component that the stop operation "
4289 "refers to (%d) is in invalid state.", component_reference);
4290 }
4291 }
4292
4293 void MainController::process_kill_req(component_struct *tc)
4294 {
4295 if (!request_allowed(tc, "KILL_REQ")) return;
4296
4297 component component_reference = tc->text_buf->pull_int().get_val();
4298 switch (component_reference) {
4299 case NULL_COMPREF:
4300 send_error_str(tc->tc_fd, "Kill operation was requested on the null "
4301 "component reference.");
4302 return;
4303 case MTC_COMPREF:
4304 send_error_str(tc->tc_fd, "Kill operation was requested on the "
4305 "component reference of the MTC.");
4306 return;
4307 case SYSTEM_COMPREF:
4308 send_error_str(tc->tc_fd, "Kill operation was requested on the "
4309 "component reference of the system.");
4310 return;
4311 case ANY_COMPREF:
4312 send_error_str(tc->tc_fd, "Kill operation was requested on "
4313 "'any component'.");
4314 return;
4315 case ALL_COMPREF:
4316 if (tc == mtc) {
4317 if (kill_all_components(FALSE)) send_kill_ack(mtc);
4318 else {
4319 mtc->tc_state = MTC_ALL_COMPONENT_KILL;
4320 status_change();
4321 }
4322 } else send_error_str(tc->tc_fd, "Operation 'all component.kill' can "
4323 "only be performed on the MTC.");
4324 return;
4325 default:
4326 break;
4327 }
4328 // the operation refers to a specific PTC
4329 component_struct *target = lookup_component(component_reference);
4330 if (target == NULL) {
4331 send_error(tc->tc_fd, "The argument of kill operation is an "
4332 "invalid component reference: %d.", component_reference);
4333 return;
4334 } else if (target == tc) {
4335 send_error_str(tc->tc_fd, "Kill operation was requested on the "
4336 "requestor component itself.");
4337 return;
4338 }
4339 boolean target_inactive = FALSE;
4340 switch (target->tc_state) {
4341 case PTC_STOPPED:
4342 // the done status of this PTC is already sent out
4343 // and it will not be cancelled in the future
4344 free_requestors(&target->done_requestors);
4345 // no break
4346 case TC_IDLE:
4347 target_inactive = TRUE;
4348 // no break
4349 case TC_CREATE:
4350 case TC_START:
4351 case TC_STOP:
4352 case TC_KILL:
4353 case TC_CONNECT:
4354 case TC_DISCONNECT:
4355 case TC_MAP:
4356 case TC_UNMAP:
4357 case PTC_FUNCTION:
4358 send_kill(target);
4359 if (target_inactive) {
4360 // the PTC was inactive
4361 target->tc_state = PTC_KILLING;
4362 if (!target->is_alive) target->stop_requested = TRUE;
4363 } else {
4364 // the PTC was active
4365 target->tc_state = PTC_STOPPING_KILLING;
4366 target->stop_requested = TRUE;
4367 }
4368 init_requestors(&target->stopping_killing.stop_requestors, NULL);
4369 init_requestors(&target->stopping_killing.kill_requestors, tc);
4370 start_kill_timer(target);
4371 tc->tc_state = TC_KILL;
4372 status_change();
4373 break;
4374 case TC_STOPPING:
4375 // the PTC is currently being stopped
4376 send_kill(target);
4377 target->tc_state = PTC_STOPPING_KILLING;
4378 if (target->kill_timer != NULL) cancel_timer(target->kill_timer);
4379 start_kill_timer(target);
4380 // no break
4381 case PTC_KILLING:
4382 case PTC_STOPPING_KILLING:
4383 // the PTC is currently being terminated
4384 add_requestor(&target->stopping_killing.kill_requestors, tc);
4385 tc->tc_state = TC_KILL;
4386 status_change();
4387 break;
4388 case TC_EXITING:
4389 case TC_EXITED:
4390 // the PTC is already terminated
4391 send_kill_ack(tc);
4392 break;
4393 case PTC_STARTING:
4394 send_error(tc->tc_fd, "PTC with component reference %d cannot be "
4395 "killed because it is currently being started.",
4396 component_reference);
4397 break;
4398 case PTC_STALE:
4399 send_error(tc->tc_fd, "The argument of kill operation (%d) is a "
4400 "component reference that belongs to an earlier testcase.",
4401 component_reference);
4402 break;
4403 default:
4404 send_error(tc->tc_fd, "The test component that the kill operation "
4405 "refers to (%d) is in invalid state.", component_reference);
4406 }
4407 }
4408
4409 void MainController::process_is_running(component_struct *tc)
4410 {
4411 if (!request_allowed(tc, "IS_RUNNING")) return;
4412
4413 component component_reference = tc->text_buf->pull_int().get_val();
4414 switch (component_reference) {
4415 case NULL_COMPREF:
4416 send_error_str(tc->tc_fd, "Running operation was requested on the "
4417 "null component reference.");
4418 return;
4419 case MTC_COMPREF:
4420 send_error_str(tc->tc_fd, "Running operation was requested on the "
4421 "component reference of the MTC.");
4422 return;
4423 case SYSTEM_COMPREF:
4424 send_error_str(tc->tc_fd, "Running operation was requested on the "
4425 "component reference of the system.");
4426 return;
4427 case ANY_COMPREF:
4428 if (tc == mtc) send_running(mtc, is_any_component_running());
4429 else send_error_str(tc->tc_fd, "Operation 'any component.running' "
4430 "can only be performed on the MTC.");
4431 return;
4432 case ALL_COMPREF:
4433 if (tc == mtc) send_running(mtc, is_all_component_running());
4434 else send_error_str(tc->tc_fd, "Operation 'all component.running' "
4435 "can only be performed on the MTC.");
4436 return;
4437 default:
4438 break;
4439 }
4440 // the operation refers to a specific PTC
4441 component_struct *comp = lookup_component(component_reference);
4442 if (comp == NULL) {
4443 send_error(tc->tc_fd, "The argument of running operation is an "
4444 "invalid component reference: %d.", component_reference);
4445 return;
4446 }
4447 switch (comp->tc_state) {
4448 case TC_CREATE:
4449 case TC_START:
4450 case TC_STOP:
4451 case TC_KILL:
4452 case TC_CONNECT:
4453 case TC_DISCONNECT:
4454 case TC_MAP:
4455 case TC_UNMAP:
4456 case TC_STOPPING:
4457 case PTC_FUNCTION:
4458 case PTC_STARTING:
4459 case PTC_STOPPING_KILLING:
4460 send_running(tc, TRUE);
4461 break;
4462 case TC_IDLE:
4463 case TC_EXITING:
4464 case TC_EXITED:
4465 case PTC_STOPPED:
4466 case PTC_KILLING:
4467 send_running(tc, FALSE);
4468 break;
4469 case PTC_STALE:
4470 send_error(tc->tc_fd, "The argument of running operation (%d) is a "
4471 "component reference that belongs to an earlier testcase.",
4472 component_reference);
4473 break;
4474 default:
4475 send_error(tc->tc_fd, "The test component that the running operation "
4476 "refers to (%d) is in invalid state.", component_reference);
4477 }
4478 }
4479
4480 void MainController::process_is_alive(component_struct *tc)
4481 {
4482 if (!request_allowed(tc, "IS_ALIVE")) return;
4483
4484 component component_reference = tc->text_buf->pull_int().get_val();
4485 switch (component_reference) {
4486 case NULL_COMPREF:
4487 send_error_str(tc->tc_fd, "Alive operation was requested on the "
4488 "null component reference.");
4489 return;
4490 case MTC_COMPREF:
4491 send_error_str(tc->tc_fd, "Alive operation was requested on the "
4492 "component reference of the MTC.");
4493 return;
4494 case SYSTEM_COMPREF:
4495 send_error_str(tc->tc_fd, "Alive operation was requested on the "
4496 "component reference of the system.");
4497 return;
4498 case ANY_COMPREF:
4499 if (tc == mtc) send_alive(mtc, is_any_component_alive());
4500 else send_error_str(tc->tc_fd, "Operation 'any component.alive' "
4501 "can only be performed on the MTC.");
4502 return;
4503 case ALL_COMPREF:
4504 if (tc == mtc) send_alive(mtc, is_all_component_alive());
4505 else send_error_str(tc->tc_fd, "Operation 'all component.alive' "
4506 "can only be performed on the MTC.");
4507 return;
4508 default:
4509 break;
4510 }
4511 // the operation refers to a specific PTC
4512 component_struct *comp = lookup_component(component_reference);
4513 if (comp == NULL) {
4514 send_error(tc->tc_fd, "The argument of alive operation is an "
4515 "invalid component reference: %d.", component_reference);
4516 return;
4517 }
4518 switch (comp->tc_state) {
4519 case TC_IDLE:
4520 case TC_CREATE:
4521 case TC_START:
4522 case TC_STOP:
4523 case TC_KILL:
4524 case TC_CONNECT:
4525 case TC_DISCONNECT:
4526 case TC_MAP:
4527 case TC_UNMAP:
4528 case TC_STOPPING:
4529 case PTC_FUNCTION:
4530 case PTC_STARTING:
4531 case PTC_STOPPED:
4532 case PTC_KILLING:
4533 case PTC_STOPPING_KILLING:
4534 send_alive(tc, TRUE);
4535 break;
4536 case TC_EXITING:
4537 case TC_EXITED:
4538 send_alive(tc, FALSE);
4539 break;
4540 case PTC_STALE:
4541 send_error(tc->tc_fd, "The argument of alive operation (%d) is a "
4542 "component reference that belongs to an earlier testcase.",
4543 component_reference);
4544 break;
4545 default:
4546 send_error(tc->tc_fd, "The test component that the alive operation "
4547 "refers to (%d) is in invalid state.", component_reference);
4548 }
4549 }
4550
4551 void MainController::process_done_req(component_struct *tc)
4552 {
4553 if (!request_allowed(tc, "DONE_REQ")) return;
4554
4555 component component_reference = tc->text_buf->pull_int().get_val();
4556 switch (component_reference) {
4557 case NULL_COMPREF:
4558 send_error_str(tc->tc_fd, "Done operation was requested on the null "
4559 "component reference.");
4560 return;
4561 case MTC_COMPREF:
4562 send_error_str(tc->tc_fd, "Done operation was requested on the "
4563 "component reference of the MTC.");
4564 return;
4565 case SYSTEM_COMPREF:
4566 send_error_str(tc->tc_fd, "Done operation was requested on the "
4567 "component reference of the system.");
4568 return;
4569 case ANY_COMPREF:
4570 if (tc == mtc) {
4571 boolean answer = is_any_component_done();
4572 send_done_ack(mtc, answer, NULL, 0, NULL);
4573 if (answer) any_component_done_sent = TRUE;
4574 else any_component_done_requested = TRUE;
4575 } else send_error_str(tc->tc_fd, "Operation 'any component.done' can "
4576 "only be performed on the MTC.");
4577 return;
4578 case ALL_COMPREF:
4579 if (tc == mtc) {
4580 boolean answer = !is_any_component_running();
4581 send_done_ack(mtc, answer, NULL, 0, NULL);
4582 if (!answer) all_component_done_requested = TRUE;
4583 } else send_error_str(tc->tc_fd, "Operation 'all component.done' can "
4584 "only be performed on the MTC.");
4585 return;
4586 default:
4587 break;
4588 }
4589 // the operation refers to a specific PTC
4590 component_struct *comp = lookup_component(component_reference);
4591 if (comp == NULL) {
4592 send_error(tc->tc_fd, "The argument of done operation is an "
4593 "invalid component reference: %d.", component_reference);
4594 return;
4595 }
4596 switch (comp->tc_state) {
4597 case PTC_STOPPED:
4598 // this answer has to be cancelled when the component is re-started
4599 add_requestor(&comp->done_requestors, tc);
4600 // no break
4601 case TC_EXITING:
4602 case TC_EXITED:
4603 case PTC_KILLING:
4604 send_done_ack(tc, TRUE, comp->return_type, comp->return_value_len,
4605 comp->return_value);
4606 break;
4607 case TC_IDLE:
4608 case TC_CREATE:
4609 case TC_START:
4610 case TC_STOP:
4611 case TC_KILL:
4612 case TC_CONNECT:
4613 case TC_DISCONNECT:
4614 case TC_MAP:
4615 case TC_UNMAP:
4616 case TC_STOPPING:
4617 case PTC_FUNCTION:
4618 case PTC_STARTING:
4619 case PTC_STOPPING_KILLING:
4620 send_done_ack(tc, FALSE, NULL, 0, NULL);
4621 add_requestor(&comp->done_requestors, tc);
4622 break;
4623 case PTC_STALE:
4624 send_error(tc->tc_fd, "The argument of done operation (%d) is a "
4625 "component reference that belongs to an earlier testcase.",
4626 component_reference);
4627 break;
4628 default:
4629 send_error(tc->tc_fd, "The test component that the done operation "
4630 "refers to (%d) is in invalid state.", component_reference);
4631 }
4632 }
4633
4634 void MainController::process_killed_req(component_struct *tc)
4635 {
4636 if (!request_allowed(tc, "KILLED_REQ")) return;
4637
4638 component component_reference = tc->text_buf->pull_int().get_val();
4639 switch (component_reference) {
4640 case NULL_COMPREF:
4641 send_error_str(tc->tc_fd, "Killed operation was requested on the null "
4642 "component reference.");
4643 return;
4644 case MTC_COMPREF:
4645 send_error_str(tc->tc_fd, "Killed operation was requested on the "
4646 "component reference of the MTC.");
4647 return;
4648 case SYSTEM_COMPREF:
4649 send_error_str(tc->tc_fd, "Killed operation was requested on the "
4650 "component reference of the system.");
4651 return;
4652 case ANY_COMPREF:
4653 if (tc == mtc) {
4654 boolean answer = !is_all_component_alive();
4655 send_killed_ack(mtc, answer);
4656 if (!answer) any_component_killed_requested = TRUE;
4657 } else send_error_str(tc->tc_fd, "Operation 'any component.killed' can "
4658 "only be performed on the MTC.");
4659 return;
4660 case ALL_COMPREF:
4661 if (tc == mtc) {
4662 boolean answer = !is_any_component_alive();
4663 send_killed_ack(mtc, answer);
4664 if (!answer) all_component_killed_requested = TRUE;
4665 } else send_error_str(tc->tc_fd, "Operation 'all component.killed' can "
4666 "only be performed on the MTC.");
4667 return;
4668 default:
4669 break;
4670 }
4671 // the operation refers to a specific PTC
4672 component_struct *comp = lookup_component(component_reference);
4673 if (comp == NULL) {
4674 send_error(tc->tc_fd, "The argument of killed operation is an "
4675 "invalid component reference: %d.", component_reference);
4676 return;
4677 }
4678 switch (comp->tc_state) {
4679 case TC_EXITING:
4680 case TC_EXITED:
4681 send_killed_ack(tc, TRUE);
4682 break;
4683 case TC_IDLE:
4684 case TC_CREATE:
4685 case TC_START:
4686 case TC_STOP:
4687 case TC_KILL:
4688 case TC_CONNECT:
4689 case TC_DISCONNECT:
4690 case TC_MAP:
4691 case TC_UNMAP:
4692 case TC_STOPPING:
4693 case PTC_FUNCTION:
4694 case PTC_STARTING:
4695 case PTC_STOPPED:
4696 case PTC_KILLING:
4697 case PTC_STOPPING_KILLING:
4698 send_killed_ack(tc, FALSE);
4699 add_requestor(&comp->killed_requestors, tc);
4700 break;
4701 case PTC_STALE:
4702 send_error(tc->tc_fd, "The argument of killed operation (%d) is a "
4703 "component reference that belongs to an earlier testcase.",
4704 component_reference);
4705 break;
4706 default:
4707 send_error(tc->tc_fd, "The test component that the killed operation "
4708 "refers to (%d) is in invalid state.", component_reference);
4709 }
4710 }
4711
4712 void MainController::process_cancel_done_ack(component_struct *tc)
4713 {
4714 component component_reference = tc->text_buf->pull_int().get_val();
4715 switch (component_reference) {
4716 case NULL_COMPREF:
4717 send_error_str(tc->tc_fd, "Message CANCEL_DONE_ACK refers to the null "
4718 "component reference.");
4719 return;
4720 case MTC_COMPREF:
4721 send_error_str(tc->tc_fd, "Message CANCEL_DONE_ACK refers to the "
4722 "component reference of the MTC.");
4723 return;
4724 case SYSTEM_COMPREF:
4725 send_error_str(tc->tc_fd, "Message CANCEL_DONE_ACK refers to the "
4726 "component reference of the system.");
4727 return;
4728 case ANY_COMPREF:
4729 send_error_str(tc->tc_fd, "Message CANCEL_DONE_ACK refers to "
4730 "'any component'.");
4731 return;
4732 case ALL_COMPREF:
4733 send_error_str(tc->tc_fd, "Message CANCEL_DONE_ACK refers to "
4734 "'all component'.");
4735 return;
4736 default:
4737 break;
4738 }
4739 component_struct *started_tc = lookup_component(component_reference);
4740 if (started_tc == NULL) {
4741 send_error(tc->tc_fd, "Message CANCEL_DONE_ACK refers to an invalid "
4742 "component reference: %d.", component_reference);
4743 return;
4744 }
4745 done_cancelled(tc, started_tc);
4746 remove_requestor(&tc->cancel_done_sent_for, started_tc);
4747 }
4748
4749 void MainController::process_connect_req(component_struct *tc)
4750 {
4751 if (!request_allowed(tc, "CONNECT_REQ")) return;
4752
4753 Text_Buf& text_buf = *tc->text_buf;
4754 component src_compref = text_buf.pull_int().get_val();
4755 char *src_port = text_buf.pull_string();
4756 component dst_compref = text_buf.pull_int().get_val();
4757 char *dst_port = text_buf.pull_string();
4758
4759 if (!valid_endpoint(src_compref, TRUE, tc, "connect") ||
4760 !valid_endpoint(dst_compref, TRUE, tc, "connect")) {
4761 delete [] src_port;
4762 delete [] dst_port;
4763 return;
4764 }
4765
4766 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
4767 dst_port);
4768 if (conn == NULL) {
4769 conn = new port_connection;
4770 conn->transport_type =
4771 choose_port_connection_transport(src_compref, dst_compref);
4772 conn->head.comp_ref = src_compref;
4773 conn->head.port_name = src_port;
4774 conn->tail.comp_ref = dst_compref;
4775 conn->tail.port_name = dst_port;
4776 init_requestors(&conn->requestors, tc);
4777 add_connection(conn);
4778 // conn->head and tail is now in canonical order
4779 switch (conn->transport_type) {
4780 case TRANSPORT_LOCAL:
4781 // send an empty string instead of component name
4782 // the component should already know its own name
4783 send_connect(components[conn->head.comp_ref], conn->head.port_name,
4784 conn->tail.comp_ref, NULL, conn->tail.port_name,
4785 conn->transport_type, 0, NULL);
4786 conn->conn_state = CONN_CONNECTING;
4787 break;
4788 case TRANSPORT_UNIX_STREAM:
4789 case TRANSPORT_INET_STREAM:
4790 // conn->head will be the server side
4791 if (conn->tail.comp_ref != MTC_COMPREF &&
4792 conn->tail.comp_ref != conn->head.comp_ref) {
4793 // send the name of conn->tail
4794 send_connect_listen(components[conn->head.comp_ref],
4795 conn->head.port_name, conn->tail.comp_ref,
4796 components[conn->tail.comp_ref]->comp_name,
4797 conn->tail.port_name, conn->transport_type);
4798 } else {
4799 // send an empty string instead of the name of conn->tail if
4800 // it is known by conn->head
4801 send_connect_listen(components[conn->head.comp_ref],
4802 conn->head.port_name, conn->tail.comp_ref, NULL,
4803 conn->tail.port_name, conn->transport_type);
4804 }
4805 conn->conn_state = CONN_LISTENING;
4806 break;
4807 default:
4808 send_error(tc->tc_fd, "The port connection %d:%s - %d:%s cannot "
4809 "be established because no suitable transport mechanism is "
4810 "available on the corresponding host(s).", src_compref,
4811 src_port, dst_compref, dst_port);
4812 remove_connection(conn);
4813 return;
4814 }
4815 tc->tc_state = TC_CONNECT;
4816 status_change();
4817 } else {
4818 switch (conn->conn_state) {
4819 case CONN_LISTENING:
4820 case CONN_CONNECTING:
4821 add_requestor(&conn->requestors, tc);
4822 tc->tc_state = TC_CONNECT;
4823 status_change();
4824 break;
4825 case CONN_CONNECTED:
4826 send_connect_ack(tc);
4827 break;
4828 case CONN_DISCONNECTING:
4829 send_error(tc->tc_fd, "The port connection %d:%s - %d:%s cannot "
4830 "be established because a disconnect operation is in progress "
4831 "on it.", src_compref, src_port, dst_compref, dst_port);
4832 break;
4833 default:
4834 send_error(tc->tc_fd, "The port connection %d:%s - %d:%s cannot "
4835 "be established due to an internal error in the MC.",
4836 src_compref, src_port, dst_compref, dst_port);
4837 error("The port connection %d:%s - %d:%s is in invalid state "
4838 "when a connect operation was requested on it.", src_compref,
4839 src_port, dst_compref, dst_port);
4840 }
4841 delete [] src_port;
4842 delete [] dst_port;
4843 }
4844 }
4845
4846 void MainController::process_connect_listen_ack(component_struct *tc,
4847 int message_end)
4848 {
4849 if (!message_expected(tc, "CONNECT_LISTEN_ACK")) return;
4850
4851 Text_Buf& text_buf = *tc->text_buf;
4852 component src_compref = tc->comp_ref;
4853 char *src_port = text_buf.pull_string();
4854 component dst_compref = text_buf.pull_int().get_val();
4855 char *dst_port = text_buf.pull_string();
4856 transport_type_enum transport_type =
4857 (transport_type_enum)text_buf.pull_int().get_val();
4858 int local_addr_begin = text_buf.get_pos();
4859 int local_addr_len = message_end - local_addr_begin;
4860 const void *local_addr_ptr = text_buf.get_data() + local_addr_begin;
4861
4862 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
4863 dst_port);
4864 if (conn != NULL) {
4865 // this message must arrive in the right state
4866 // and from the server side (head)
4867 if (conn->conn_state != CONN_LISTENING ||
4868 conn->head.comp_ref != src_compref ||
4869 strcmp(conn->head.port_name, src_port)) {
4870 send_error(tc->tc_fd, "Unexpected message CONNECT_LISTEN_ACK was "
4871 "received for port connection %d:%s - %d:%s.",
4872 src_compref, src_port, dst_compref, dst_port);
4873 delete [] src_port;
4874 delete [] dst_port;
4875 return;
4876 } else if (conn->transport_type != transport_type) {
4877 send_error(tc->tc_fd, "Message CONNECT_LISTEN_ACK for port "
4878 "connection %d:%s - %d:%s contains wrong transport type: %s "
4879 "was expected instead of %s.", src_compref, src_port,
4880 dst_compref, dst_port, get_transport_name(conn->transport_type),
4881 get_transport_name(transport_type));
4882 delete [] src_port;
4883 delete [] dst_port;
4884 return;
4885 }
4886 component_struct *dst_comp = components[dst_compref];
4887 switch (dst_comp->tc_state) {
4888 case TC_IDLE:
4889 case TC_CREATE:
4890 case TC_START:
4891 case TC_STOP:
4892 case TC_KILL:
4893 case TC_CONNECT:
4894 case TC_DISCONNECT:
4895 case TC_MAP:
4896 case TC_UNMAP:
4897 case TC_STOPPING:
4898 case MTC_TESTCASE:
4899 case PTC_FUNCTION:
4900 case PTC_STARTING:
4901 case PTC_STOPPED:
4902 if (src_compref != MTC_COMPREF && src_compref != dst_compref) {
4903 // send the name of tc
4904 send_connect(dst_comp, dst_port, src_compref, tc->comp_name,
4905 src_port, transport_type, local_addr_len, local_addr_ptr);
4906 } else {
4907 // send an empty string instead of the name of tc if it is
4908 // known by dst_comp
4909 send_connect(dst_comp, dst_port, src_compref, NULL, src_port,
4910 transport_type, local_addr_len, local_addr_ptr);
4911 }
4912 conn->conn_state = CONN_CONNECTING;
4913 break;
4914 default:
4915 send_disconnect_to_server(conn);
4916 send_error_to_connect_requestors(conn, "test component %d has "
4917 "terminated during connection setup.", dst_compref);
4918 remove_connection(conn);
4919 }
4920 status_change();
4921 } else {
4922 // the connection does not exist anymore
4923 // check whether the transport type is valid
4924 switch (transport_type) {
4925 case TRANSPORT_LOCAL:
4926 send_error(tc->tc_fd, "Message CONNECT_LISTEN_ACK for port "
4927 "connection %d:%s - %d:%s cannot refer to transport type %s.",
4928 src_compref, src_port, dst_compref, dst_port,
4929 get_transport_name(transport_type));
4930 break;
4931 case TRANSPORT_INET_STREAM:
4932 case TRANSPORT_UNIX_STREAM:
4933 break;
4934 default:
4935 send_error(tc->tc_fd, "Message CONNECT_LISTEN_ACK for port "
4936 "connection %d:%s - %d:%s refers to invalid transport type %d.",
4937 src_compref, src_port, dst_compref, dst_port, transport_type);
4938 }
4939 }
4940
4941 delete [] src_port;
4942 delete [] dst_port;
4943 }
4944
4945 void MainController::process_connected(component_struct *tc)
4946 {
4947 if (!message_expected(tc, "CONNECTED")) return;
4948
4949 Text_Buf& text_buf = *tc->text_buf;
4950 component src_compref = tc->comp_ref;
4951 char *src_port = text_buf.pull_string();
4952 component dst_compref = text_buf.pull_int().get_val();
4953 char *dst_port = text_buf.pull_string();
4954
4955 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
4956 dst_port);
4957 if (conn != NULL) {
4958 // this message must arrive in the right state
4959 // and from the server side (head)
4960 if (conn->conn_state == CONN_CONNECTING &&
4961 conn->head.comp_ref == src_compref &&
4962 !strcmp(conn->head.port_name, src_port)) {
4963 send_connect_ack_to_requestors(conn);
4964 conn->conn_state = CONN_CONNECTED;
4965 status_change();
4966 } else {
4967 send_error(tc->tc_fd, "Unexpected CONNECTED message was "
4968 "received for port connection %d:%s - %d:%s.",
4969 src_compref, src_port, dst_compref, dst_port);
4970 }
4971 }
4972 // do nothing if the connection does not exist anymore
4973
4974 delete [] src_port;
4975 delete [] dst_port;
4976 }
4977
4978 void MainController::process_connect_error(component_struct *tc)
4979 {
4980 if (!message_expected(tc, "CONNECT_ERROR")) return;
4981
4982 Text_Buf& text_buf = *tc->text_buf;
4983 component src_compref = tc->comp_ref;
4984 char *src_port = text_buf.pull_string();
4985 component dst_compref = text_buf.pull_int().get_val();
4986 char *dst_port = text_buf.pull_string();
4987 char *reason = text_buf.pull_string();
4988
4989 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
4990 dst_port);
4991 if (conn != NULL) {
4992 switch (conn->conn_state) {
4993 case CONN_CONNECTING:
4994 // in this state both endpoints can report error
4995 if (conn->transport_type != TRANSPORT_LOCAL &&
4996 conn->tail.comp_ref == src_compref &&
4997 !strcmp(conn->tail.port_name, src_port)) {
4998 // shut down the server side (head) only if the error was reported
4999 // by the client side (tail)
5000 send_disconnect_to_server(conn);
5001 }
5002 break;
5003 case CONN_LISTENING:
5004 // in this state only the server side (head) can report the error
5005 if (conn->head.comp_ref == src_compref &&
5006 !strcmp(conn->head.port_name, src_port)) break;
5007 default:
5008 send_error(tc->tc_fd, "Unexpected message CONNECT_ERROR was "
5009 "received for port connection %d:%s - %d:%s.",
5010 src_compref, src_port, dst_compref, dst_port);
5011 delete [] src_port;
5012 delete [] dst_port;
5013 delete [] reason;
5014 return;
5015 }
5016 send_error_to_connect_requestors(conn, "test component %d reported "
5017 "error: %s", src_compref, reason);
5018 remove_connection(conn);
5019 status_change();
5020 }
5021 // do nothing if the connection does not exist anymore
5022
5023 delete [] src_port;
5024 delete [] dst_port;
5025 delete [] reason;
5026 }
5027
5028 void MainController::process_disconnect_req(component_struct *tc)
5029 {
5030 if (!request_allowed(tc, "DISCONNECT_REQ")) return;
5031
5032 Text_Buf& text_buf = *tc->text_buf;
5033 component src_compref = text_buf.pull_int().get_val();
5034 char *src_port = text_buf.pull_string();
5035 component dst_compref = text_buf.pull_int().get_val();
5036 char *dst_port = text_buf.pull_string();
5037
5038 if (!valid_endpoint(src_compref, FALSE, tc, "disconnect") ||
5039 !valid_endpoint(dst_compref, FALSE, tc, "disconnect")) {
5040 delete [] src_port;
5041 delete [] dst_port;
5042 return;
5043 }
5044
5045 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
5046 dst_port);
5047 if (conn != NULL) {
5048 switch (conn->conn_state) {
5049 case CONN_LISTENING:
5050 case CONN_CONNECTING:
5051 send_error(tc->tc_fd, "The port connection %d:%s - %d:%s cannot "
5052 "be destroyed because a connect operation is in progress "
5053 "on it.", src_compref, src_port, dst_compref, dst_port);
5054 break;
5055 case CONN_CONNECTED:
5056 send_disconnect(components[conn->tail.comp_ref],
5057 conn->tail.port_name, conn->head.comp_ref,
5058 conn->head.port_name);
5059 conn->conn_state = CONN_DISCONNECTING;
5060 // no break
5061 case CONN_DISCONNECTING:
5062 add_requestor(&conn->requestors, tc);
5063 tc->tc_state = TC_DISCONNECT;
5064 status_change();
5065 break;
5066 default:
5067 send_error(tc->tc_fd, "The port connection %d:%s - %d:%s cannot "
5068 "be destroyed due to an internal error in the MC.",
5069 src_compref, src_port, dst_compref, dst_port);
5070 error("The port connection %d:%s - %d:%s is in invalid state when "
5071 "a disconnect operation was requested on it.", src_compref,
5072 src_port, dst_compref, dst_port);
5073 }
5074 } else {
5075 // the connection is already terminated
5076 // send the acknowledgement immediately
5077 send_disconnect_ack(tc);
5078 }
5079
5080 delete [] src_port;
5081 delete [] dst_port;
5082 }
5083
5084 void MainController::process_disconnected(component_struct *tc)
5085 {
5086 if (!message_expected(tc, "DISCONNECTED")) return;
5087
5088 Text_Buf& text_buf = *tc->text_buf;
5089 component src_compref = tc->comp_ref;
5090 char *src_port = text_buf.pull_string();
5091 component dst_compref = text_buf.pull_int().get_val();
5092 char *dst_port = text_buf.pull_string();
5093
5094 port_connection *conn = find_connection(src_compref, src_port, dst_compref,
5095 dst_port);
5096 if (conn != NULL) {
5097 switch (conn->conn_state) {
5098 case CONN_LISTENING:
5099 // in this state only the server side (head) can report the end of
5100 // the connection
5101 if (conn->head.comp_ref != src_compref ||
5102 strcmp(conn->head.port_name, src_port)) {
5103 send_error(tc->tc_fd, "Unexpected message DISCONNECTED was "
5104 "received for port connection %d:%s - %d:%s.",
5105 src_compref, src_port, dst_compref, dst_port);
5106 break;
5107 }
5108 // no break
5109 case CONN_CONNECTING:
5110 // in this state both ends can report the end of the connection
5111 send_error_to_connect_requestors(conn, "test component %d "
5112 "reported end of the connection during connection setup.",
5113 src_compref);
5114 remove_connection(conn);
5115 status_change();
5116 break;
5117 case CONN_CONNECTED:
5118 remove_connection(conn);
5119 status_change();
5120 break;
5121 case CONN_DISCONNECTING:
5122 send_disconnect_ack_to_requestors(conn);
5123 remove_connection(conn);
5124 status_change();
5125 break;
5126 default:
5127 error("The port connection %d:%s - %d:%s is in invalid state when "
5128 "MC was notified about its termination.", src_compref, src_port,
5129 dst_compref, dst_port);
5130 }
5131 }
5132
5133 delete [] src_port;
5134 delete [] dst_port;
5135 status_change();
5136 }
5137
5138 void MainController::process_map_req(component_struct *tc)
5139 {
5140 if (!request_allowed(tc, "MAP_REQ")) return;
5141
5142 Text_Buf& text_buf = *tc->text_buf;
5143 component src_compref = text_buf.pull_int().get_val();
5144 char *src_port = text_buf.pull_string();
5145 char *system_port = text_buf.pull_string();
5146
5147 if (!valid_endpoint(src_compref, TRUE, tc, "map")) {
5148 delete [] src_port;
5149 delete [] system_port;
5150 return;
5151 }
5152
5153 port_connection *conn = find_connection(src_compref, src_port,
5154 SYSTEM_COMPREF, system_port);
5155 if (conn == NULL) {
5156 send_map(components[src_compref], src_port, system_port);
5157 conn = new port_connection;
5158 conn->head.comp_ref = src_compref;
5159 conn->head.port_name = src_port;
5160 conn->tail.comp_ref = SYSTEM_COMPREF;
5161 conn->tail.port_name = system_port;
5162 conn->conn_state = CONN_MAPPING;
5163 init_requestors(&conn->requestors, tc);
5164 add_connection(conn);
5165 tc->tc_state = TC_MAP;
5166 status_change();
5167 } else {
5168 switch (conn->conn_state) {
5169 case CONN_MAPPING:
5170 add_requestor(&conn->requestors, tc);
5171 tc->tc_state = TC_MAP;
5172 status_change();
5173 break;
5174 case CONN_MAPPED:
5175 send_map_ack(tc);
5176 break;
5177 case CONN_UNMAPPING:
5178 send_error(tc->tc_fd, "The port mapping %d:%s - system:%s cannot "
5179 "be established because an unmap operation is in progress "
5180 "on it.", src_compref, src_port, system_port);
5181 break;
5182 default:
5183 send_error(tc->tc_fd, "The port mapping %d:%s - system:%s is in "
5184 "invalid state.", src_compref, src_port, system_port);
5185 }
5186 delete [] src_port;
5187 delete [] system_port;
5188 }
5189 }
5190
5191 void MainController::process_mapped(component_struct *tc)
5192 {
5193 if (!message_expected(tc, "MAPPED")) return;
5194
5195 Text_Buf& text_buf = *tc->text_buf;
5196 component src_compref = tc->comp_ref;
5197 char *src_port = text_buf.pull_string();
5198 char *system_port = text_buf.pull_string();
5199
5200 port_connection *conn = find_connection(src_compref, src_port,
5201 SYSTEM_COMPREF, system_port);
5202 if (conn == NULL) {
5203 send_error(tc->tc_fd, "The MAPPED message refers to a "
5204 "non-existent port mapping %d:%s - system:%s.",
5205 src_compref, src_port, system_port);
5206 } else if (conn->conn_state != CONN_MAPPING) {
5207 send_error(tc->tc_fd, "Unexpected MAPPED message was "
5208 "received for port mapping %d:%s - system:%s.",
5209 src_compref, src_port, system_port);
5210 } else {
5211 for (int i = 0; ; i++) {
5212 component_struct *comp = get_requestor(&conn->requestors, i);
5213 if (comp == NULL) break;
5214 if (comp->tc_state == TC_MAP) {
5215 send_map_ack(comp);
5216 if (comp == mtc) comp->tc_state = MTC_TESTCASE;
5217 else comp->tc_state = PTC_FUNCTION;
5218 }
5219 }
5220 free_requestors(&conn->requestors);
5221 conn->conn_state = CONN_MAPPED;
5222 status_change();
5223 }
5224
5225 delete [] src_port;
5226 delete [] system_port;
5227 }
5228
5229 void MainController::process_unmap_req(component_struct *tc)
5230 {
5231 if (!request_allowed(tc, "UNMAP_REQ")) return;
5232
5233 Text_Buf& text_buf = *tc->text_buf;
5234 component src_compref = text_buf.pull_int().get_val();
5235 char *src_port = text_buf.pull_string();
5236 char *system_port = text_buf.pull_string();
5237
5238 if (!valid_endpoint(src_compref, FALSE, tc, "unmap")) {
5239 delete [] src_port;
5240 delete [] system_port;
5241 return;
5242 }
5243
5244 port_connection *conn = find_connection(src_compref, src_port,
5245 SYSTEM_COMPREF, system_port);
5246 if (conn == NULL) {
5247 send_unmap_ack(tc);
5248 } else {
5249 switch (conn->conn_state) {
5250 case CONN_MAPPED:
5251 send_unmap(components[src_compref], src_port, system_port);
5252 conn->conn_state = CONN_UNMAPPING;
5253 case CONN_UNMAPPING:
5254 add_requestor(&conn->requestors, tc);
5255 tc->tc_state = TC_UNMAP;
5256 status_change();
5257 break;
5258 case CONN_MAPPING:
5259 send_error(tc->tc_fd, "The port mapping %d:%s - system:%s cannot "
5260 "be destroyed because a map operation is in progress "
5261 "on it.", src_compref, src_port, system_port);
5262 break;
5263 default:
5264 send_error(tc->tc_fd, "The port mapping %d:%s - system:%s is in "
5265 "invalid state.", src_compref, src_port, system_port);
5266 }
5267 }
5268
5269 delete [] src_port;
5270 delete [] system_port;
5271 }
5272
5273 void MainController::process_unmapped(component_struct *tc)
5274 {
5275 if (!message_expected(tc, "UNMAPPED")) return;
5276
5277 Text_Buf& text_buf = *tc->text_buf;
5278 component src_compref = tc->comp_ref;
5279 char *src_port = text_buf.pull_string();
5280 char *system_port = text_buf.pull_string();
5281
5282 port_connection *conn = find_connection(src_compref, src_port,
5283 SYSTEM_COMPREF, system_port);
5284 if (conn != NULL) {
5285 switch (conn->conn_state) {
5286 case CONN_MAPPING:
5287 case CONN_MAPPED:
5288 case CONN_UNMAPPING:
5289 destroy_mapping(conn);
5290 break;
5291 default:
5292 send_error(tc->tc_fd, "Unexpected UNMAPPED message was "
5293 "received for port mapping %d:%s - system:%s.",
5294 src_compref, src_port, system_port);
5295 }
5296 }
5297
5298 delete [] src_port;
5299 delete [] system_port;
5300 status_change();
5301 }
5302
5303 void MainController::process_testcase_started()
5304 {
5305 if (mc_state != MC_EXECUTING_CONTROL) {
5306 send_error_str(mtc->tc_fd, "Unexpected message TESTCASE_STARTED "
5307 "was received.");
5308 return;
5309 }
5310
5311 Text_Buf& text_buf = *mtc->text_buf;
5312 text_buf.pull_qualified_name(mtc->tc_fn_name);
5313 text_buf.pull_qualified_name(mtc->comp_type);
5314 text_buf.pull_qualified_name(system->comp_type);
5315
5316 mtc->tc_state = MTC_TESTCASE;
5317 mc_state = MC_EXECUTING_TESTCASE;
5318 tc_first_comp_ref = next_comp_ref;
5319 any_component_done_requested = FALSE;
5320 any_component_done_sent = FALSE;
5321 all_component_done_requested = FALSE;
5322 any_component_killed_requested = FALSE;
5323 all_component_killed_requested = FALSE;
5324
5325 status_change();
5326 }
5327
5328 void MainController::process_testcase_finished()
5329 {
5330 if (mc_state != MC_EXECUTING_TESTCASE) {
5331 send_error_str(mtc->tc_fd, "Unexpected message TESTCASE_FINISHED "
5332 "was received.");
5333 return;
5334 }
5335
5336 boolean ready_to_finish = kill_all_components(TRUE);
5337
5338 mc_state = MC_TERMINATING_TESTCASE;
5339 mtc->tc_state = MTC_TERMINATING_TESTCASE;
5340 mtc->local_verdict = (verdicttype)mtc->text_buf->pull_int().get_val();
5341 mtc->verdict_reason = mtc->text_buf->pull_string();
5342 mtc->stop_requested = FALSE;
5343 if (mtc->kill_timer != NULL) {
5344 cancel_timer(mtc->kill_timer);
5345 mtc->kill_timer = NULL;
5346 }
5347 any_component_done_requested = FALSE;
5348 any_component_done_sent = FALSE;
5349 all_component_done_requested = FALSE;
5350 any_component_killed_requested = FALSE;
5351 all_component_killed_requested = FALSE;
5352
5353 if (ready_to_finish) finish_testcase();
5354
5355 status_change();
5356 }
5357
5358 void MainController::process_mtc_ready()
5359 {
5360 if (mc_state != MC_EXECUTING_CONTROL || mtc->tc_state != MTC_CONTROLPART) {
5361 send_error_str(mtc->tc_fd, "Unexpected message MTC_READY was "
5362 "received.");
5363 return;
5364 }
5365 mc_state = MC_READY;
5366 mtc->tc_state = TC_IDLE;
5367 mtc->stop_requested = FALSE;
5368 if (mtc->kill_timer != NULL) {
5369 cancel_timer(mtc->kill_timer);
5370 mtc->kill_timer = NULL;
5371 }
5372 stop_requested = FALSE;
5373 notify("Test execution finished.");
5374 status_change();
5375 }
5376
5377 void MainController::process_stopped(component_struct *tc, int message_end)
5378 {
5379 switch (tc->tc_state) {
5380 case TC_STOPPING:
5381 case PTC_FUNCTION:
5382 case PTC_STOPPING_KILLING:
5383 // only alive PTCs are allowed to send STOPPED
5384 if (tc->is_alive) break;
5385 default:
5386 send_error_str(tc->tc_fd, "Unexpected message STOPPED was received.");
5387 return;
5388 }
5389 Text_Buf& text_buf = *tc->text_buf;
5390 delete [] tc->return_type;
5391 tc->return_type = text_buf.pull_string();
5392 tc->return_value_len = message_end - text_buf.get_pos();
5393 Free(tc->return_value);
5394 tc->return_value = Malloc(tc->return_value_len);
5395 text_buf.pull_raw(tc->return_value_len, tc->return_value);
5396 free_qualified_name(&tc->tc_fn_name);
5397 component_stopped(tc);
5398 status_change();
5399 }
5400
5401 void MainController::process_stopped_killed(component_struct *tc,
5402 int message_end)
5403 {
5404 switch (tc->tc_state) {
5405 case TC_CREATE:
5406 case TC_START:
5407 case TC_STOP:
5408 case TC_KILL:
5409 case TC_CONNECT:
5410 case TC_DISCONNECT:
5411 case TC_MAP:
5412 case TC_UNMAP:
5413 case TC_STOPPING:
5414 case PTC_FUNCTION:
5415 case PTC_STOPPING_KILLING:
5416 break;
5417 default:
5418 send_error_str(tc->tc_fd, "Unexpected message STOPPED_KILLED was "
5419 "received.");
5420 // also notify the user because the above message may get lost
5421 notify("Unexpected message STOPPED_KILLED was received from PTC %d.",
5422 tc->comp_ref);
5423 return;
5424 }
5425 Text_Buf& text_buf = *tc->text_buf;
5426 tc->local_verdict = (verdicttype)text_buf.pull_int().get_val();
5427 tc->verdict_reason = text_buf.pull_string();
5428 tc->return_type = text_buf.pull_string();
5429 tc->return_value_len = message_end - text_buf.get_pos();
5430 tc->return_value = Malloc(tc->return_value_len);
5431 text_buf.pull_raw(tc->return_value_len, tc->return_value);
5432 // start a guard timer to detect whether the control connection is closed
5433 // in time
5434 if (tc->tc_state != PTC_STOPPING_KILLING) start_kill_timer(tc);
5435 component_terminated(tc);
5436 status_change();
5437 }
5438
5439 void MainController::process_killed(component_struct *tc)
5440 {
5441 switch (tc->tc_state) {
5442 case TC_IDLE:
5443 case PTC_STOPPED:
5444 case PTC_KILLING:
5445 break;
5446 default:
5447 send_error_str(tc->tc_fd, "Unexpected message KILLED was received.");
5448 // also notify the user because the above message may get lost
5449 notify("Unexpected message KILLED was received from PTC %d.",
5450 tc->comp_ref);
5451 return;
5452 }
5453 tc->local_verdict = (verdicttype)tc->text_buf->pull_int().get_val();
5454 tc->verdict_reason = tc->text_buf->pull_string();
5455 // start a guard timer to detect whether the control connection is closed
5456 // in time
5457 if (tc->tc_state != PTC_KILLING) start_kill_timer(tc);
5458 component_terminated(tc);
5459 status_change();
5460 }
5461
5462 void MainController::initialize(UserInterface& par_ui, int par_max_ptcs)
5463 {
5464 ui = &par_ui;
5465
5466 max_ptcs = par_max_ptcs;
5467
5468 mc_state = MC_INACTIVE;
5469
5470 struct utsname buf;
5471 if (uname(&buf) < 0) fatal_error("MainController::initialize: "
5472 "uname() system call failed.");
5473 mc_hostname = mprintf("MC@%s", buf.nodename);
5474
5475 server_fd = -1;
5476
5477 if (pthread_mutex_init(&mutex, NULL))
5478 fatal_error("MainController::initialize: pthread_mutex_init failed.");
5479
5480 #ifdef USE_EPOLL
5481 epoll_events = NULL;
5482 epfd = -1;
5483 #else
5484 nfds = 0;
5485 ufds = NULL;
5486 new_nfds = 0;
5487 new_ufds = NULL;
5488 pollfds_modified = FALSE;
5489 #endif
5490
5491 fd_table_size = 0;
5492 fd_table = NULL;
5493
5494 unknown_head = NULL;
5495 unknown_tail = NULL;
5496
5497 n_host_groups = 0;
5498 host_groups = NULL;
5499 init_string_set(&assigned_components);
5500 all_components_assigned = FALSE;
5501
5502 n_hosts = 0;
5503 hosts = NULL;
5504 config_str = NULL;
5505
5506 version_known = FALSE;
5507 n_modules = 0;
5508 modules = NULL;
5509
5510 n_components = 0;
5511 n_active_ptcs = 0;
5512 components = NULL;
5513 mtc = NULL;
5514 system = NULL;
5515 next_comp_ref = FIRST_PTC_COMPREF;
5516
5517 stop_after_tc = FALSE;
5518 stop_requested = FALSE;
5519
5520 kill_timer = 10.0;
5521
5522 timer_head = NULL;
5523 timer_tail = NULL;
5524
5525 pipe_fd[0] = -1;
5526 pipe_fd[1] = -1;
5527 wakeup_reason = REASON_NOTHING;
5528
5529 register_termination_handlers();
5530 }
5531
5532 void MainController::terminate()
5533 {
5534 clean_up();
5535 destroy_host_groups();
5536 Free(mc_hostname);
5537 pthread_mutex_destroy(&mutex);
5538 }
5539
5540 void MainController::add_host(const char *group_name, const char *host_name)
5541 {
5542 lock();
5543 if (mc_state != MC_INACTIVE) {
5544 error("MainController::add_host: called in wrong state.");
5545 unlock();
5546 return;
5547 }
5548 host_group_struct *group = add_host_group(group_name);
5549 if (host_name != NULL) {
5550 if (group->has_all_hosts) error("Redundant member `%s' was ignored in "
5551 "host group `%s'. All hosts (`*') are already the members of the "
5552 "group.", host_name, group_name);
5553 else {
5554 if (set_has_string(&group->host_members, host_name)) {
5555 error("Duplicate member `%s' was ignored in host group "
5556 "`%s'.", host_name, group_name);
5557 } else add_string_to_set(&group->host_members, host_name);
5558 }
5559 } else {
5560 if (group->has_all_hosts) error("Duplicate member `*' was ignored in "
5561 "host group `%s'.", group_name);
5562 else {
5563 for (int i = 0; ; i++) {
5564 const char *group_member =
5565 get_string_from_set(&group->host_members, i);
5566 if (group_member == NULL) break;
5567 error("Redundant member `%s' was ignored in host group `%s'. "
5568 "All hosts (`*') are already the members of the group.",
5569 group_member, group_name);
5570 }
5571 free_string_set(&group->host_members);
5572 group->has_all_hosts = TRUE;
5573 }
5574 }
5575 unlock();
5576 }
5577
5578 void MainController::assign_component(const char *host_or_group,
5579 const char *component_id)
5580 {
5581 lock();
5582 if (mc_state != MC_INACTIVE) {
5583 error("MainController::assign_component: called in wrong state.");
5584 unlock();
5585 return;
5586 }
5587 host_group_struct *group = add_host_group(host_or_group);
5588 if (component_id == NULL) {
5589 if (all_components_assigned) {
5590 for (int i = 0; i < n_host_groups; i++) {
5591 if (host_groups[i].has_all_components) {
5592 error("Duplicate assignment of all components (*) to host "
5593 "group `%s'. Previous assignment to group `%s' is "
5594 "ignored.", host_or_group, host_groups[i].group_name);
5595 host_groups[i].has_all_components = FALSE;
5596 }
5597 }
5598 } else all_components_assigned = TRUE;
5599 group->has_all_components = TRUE;
5600 } else {
5601 if (set_has_string(&assigned_components, component_id)) {
5602 for (int i = 0; i < n_host_groups; i++) {
5603 if (set_has_string(&host_groups[i].assigned_components,
5604 component_id)) {
5605 error("Duplicate assignment of component `%s' to host "
5606 "group `%s'. Previous assignment to group `%s' is "
5607 "ignored.", component_id, host_or_group,
5608 host_groups[i].group_name);
5609 remove_string_from_set(&host_groups[i].assigned_components,
5610 component_id);
5611 }
5612 }
5613 } else add_string_to_set(&assigned_components, component_id);
5614 add_string_to_set(&group->assigned_components, component_id);
5615 }
5616 unlock();
5617 }
5618
5619 void MainController::destroy_host_groups()
5620 {
5621 lock();
5622 if (mc_state != MC_INACTIVE)
5623 error("MainController::destroy_host_groups: called in wrong state.");
5624 else {
5625 for (int i = 0; i < n_host_groups; i++) {
5626 host_group_struct *group = host_groups + i;
5627 Free(group->group_name);
5628 free_string_set(&group->host_members);
5629 free_string_set(&group->assigned_components);
5630 }
5631 Free(host_groups);
5632 n_host_groups = 0;
5633 host_groups = NULL;
5634 free_string_set(&assigned_components);
5635 all_components_assigned = FALSE;
5636 }
5637 unlock();
5638 }
5639
5640 void MainController::set_kill_timer(double timer_val)
5641 {
5642 lock();
5643 if (mc_state != MC_INACTIVE)
5644 error("MainController::set_kill_timer: called in wrong state.");
5645 else if (timer_val < 0.0)
5646 error("MainController::set_kill_timer: setting a negative kill timer "
5647 "value.");
5648 else kill_timer = timer_val;
5649 unlock();
5650 }
5651
5652 unsigned short MainController::start_session(const char *local_address,
5653 unsigned short tcp_port, bool unix_sockets_enabled)
5654 {
5655 lock();
5656
5657 if (mc_state != MC_INACTIVE) {
5658 error("MainController::start_session: called in wrong state.");
5659 unlock();
5660 return 0;
5661 }
5662
5663 #ifdef USE_EPOLL
5664 epoll_events = (epoll_event *)Malloc(EPOLL_MAX_EVENTS * sizeof(*epoll_events));
5665 epfd = epoll_create(EPOLL_SIZE_HINT);
5666 if (epfd < 0) {
5667 error("System call epoll_create failed: %s", strerror(errno));
5668 clean_up();
5669 unlock();
5670 return 0;
5671 }
5672 set_close_on_exec(epfd);
5673 #endif //USE_EPOLL
5674
5675 nh.set_family(local_address);
5676 server_fd = nh.socket();
5677 if (server_fd < 0) {
5678 error("Server socket creation failed: %s", strerror(errno));
5679 clean_up();
5680 unlock();
5681 return 0;
5682 }
5683
5684 const int on = 1;
5685 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on,
5686 sizeof(on))) {
5687 error("System call setsockopt (SO_REUSEADDR) failed on server socket: "
5688 "%s", strerror(errno));
5689 clean_up();
5690 unlock();
5691 return 0;
5692 }
5693
5694 if (setsockopt(server_fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on,
5695 sizeof(on))) {
5696 error("System call setsockopt (TCP_NODELAY) failed on server socket: "
5697 "%s", strerror(errno));
5698 clean_up();
5699 unlock();
5700 return 0;
5701 }
5702
5703 IPAddress *localaddr = IPAddress::create_addr(nh.get_family());
5704 if (localaddr) localaddr->set_port(tcp_port);
5705
5706 if (local_address != NULL) {
5707 if (!localaddr || !localaddr->set_addr(local_address, tcp_port)) {
5708 error("Cannot resolve host name `%s' to a local IP address: "
5709 "Host name lookup failure", local_address);
5710 clean_up();
5711 unlock();
5712 delete localaddr;
5713 return 0;
5714 }
5715 }
5716
5717 if (bind(server_fd, localaddr->get_addr(), localaddr->get_addr_len())) {
5718 if (local_address != NULL) {
5719 if (tcp_port != 0) error("Binding server socket to IP address "
5720 "%s and TCP port %d failed: %s", localaddr->get_addr_str(),
5721 tcp_port, strerror(errno));
5722 else error("Binding server socket to IP address %s failed: %s",
5723 localaddr->get_addr_str(), strerror(errno));
5724 } else {
5725 if (tcp_port != 0) error("Binding server socket to TCP port %d "
5726 "failed: %s", tcp_port, strerror(errno));
5727 else error("Binding server socket to an ephemeral TCP port "
5728 "failed: %s", strerror(errno));
5729 }
5730 clean_up();
5731 unlock();
5732 delete localaddr;
5733 return 0;
5734 }
5735
5736 if (listen(server_fd, 10)) {
5737 if (local_address != NULL) {
5738 if (tcp_port != 0) error("Listening on IP address %s and TCP port "
5739 "%d failed: %s", localaddr->get_addr_str(), tcp_port,
5740 strerror(errno));
5741 else error("Listening on IP address %s failed: %s",
5742 localaddr->get_addr_str(), strerror(errno));
5743 } else {
5744 if (tcp_port != 0) error("Listening on TCP port %d failed: %s",
5745 tcp_port, strerror(errno));
5746 else error("Listening on an ephemeral TCP port failed: %s",
5747 strerror(errno));
5748 }
5749 clean_up();
5750 unlock();
5751 delete localaddr;
5752 return 0;
5753 }
5754
5755 if (localaddr->getsockname(server_fd)) {
5756 error("System call getsockname() failed on server socket: %s",
5757 strerror(errno));
5758 clean_up();
5759 unlock();
5760 delete localaddr;
5761 return 0;
5762 }
5763 tcp_port = localaddr->get_port();
5764
5765 set_close_on_exec(server_fd);
5766
5767 // Trying to open a unix socket for local communication
5768 if (unix_sockets_enabled) {
5769
5770 server_fd_unix = socket(PF_UNIX, SOCK_STREAM, 0);
5771 if (server_fd_unix < 0) {
5772 notify("Unix server socket creation failed: %s", strerror(errno));
5773 errno = 0;
5774 goto unix_end;
5775 }
5776
5777 struct sockaddr_un localaddr_unix;
5778 memset(&localaddr_unix, 0, sizeof(localaddr_unix));
5779 localaddr_unix.sun_family = AF_UNIX;
5780 snprintf(localaddr_unix.sun_path, sizeof(localaddr_unix.sun_path),
5781 "/tmp/ttcn3-mctr-%u", tcp_port);
5782 if (unlink(localaddr_unix.sun_path))
5783 errno = 0; // silently ignore, error handling below
5784
5785 if (bind(server_fd_unix, (struct sockaddr *)&localaddr_unix,
5786 sizeof(localaddr_unix)) != 0) {
5787 if (errno == EADDRINUSE) {
5788 // the temporary file name is already used by someone else
5789 close(server_fd_unix);
5790 notify("Could not create Unix server socket: '%s' is already existed "
5791 "and cannot be removed.", localaddr_unix.sun_path);
5792 errno = 0;
5793 goto unix_end;
5794 } else {
5795 close(server_fd_unix);
5796 notify("Binding of Unix server socket to pathname %s failed. (%s)",
5797 localaddr_unix.sun_path, strerror(errno));
5798 errno = 0;
5799 goto unix_end;
5800 }
5801 }
5802
5803 if (listen(server_fd_unix, 10)) {
5804 notify("Could not listen on the given socket. Unix domain socket "
5805 "communication will not be used.");
5806 close(server_fd_unix);
5807 errno = 0;
5808 goto unix_end;
5809 }
5810
5811 set_close_on_exec(server_fd_unix);
5812
5813 add_fd_to_table(server_fd_unix);
5814 fd_table[server_fd_unix].fd_type = FD_SERVER;
5815 add_poll_fd(server_fd_unix);
5816
5817 notify("Unix server socket created successfully.");
5818 }
5819 unix_end:
5820
5821 if (pipe(pipe_fd) < 0) {
5822 error("System call pipe failed: %s", strerror(errno));
5823 clean_up();
5824 unlock();
5825 delete localaddr;
5826 return 0;
5827 }
5828 set_close_on_exec(pipe_fd[0]);
5829 set_close_on_exec(pipe_fd[1]);
5830
5831 wakeup_reason = REASON_NOTHING;
5832
5833 mc_state = MC_LISTENING;
5834
5835 add_fd_to_table(server_fd);
5836 fd_table[server_fd].fd_type = FD_SERVER;
5837 add_poll_fd(server_fd);
5838 server_fd_disabled = FALSE;
5839
5840 add_fd_to_table(pipe_fd[0]);
5841 fd_table[pipe_fd[0]].fd_type = FD_PIPE;
5842 add_poll_fd(pipe_fd[0]);
5843
5844 pthread_attr_t attr;
5845 if (pthread_attr_init(&attr))
5846 fatal_error("MainController::start_session: pthread_attr_init failed.");
5847 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
5848 fatal_error("MainController::start_session: "
5849 "pthread_attr_setdetachstate failed.");
5850
5851 pthread_t thread;
5852 if (pthread_create(&thread, &attr, thread_main, NULL))
5853 fatal_error("MainController::start_session: pthread_create failed.");
5854
5855 if (pthread_attr_destroy(&attr))
5856 fatal_error("MainController::start_session: pthread_attr_destroy "
5857 "failed.");
5858 if (local_address != NULL)
5859 notify("Listening on IP address %s and TCP port %d.", localaddr->get_addr_str(), tcp_port);
5860 else notify("Listening on TCP port %d.", tcp_port);
5861 delete localaddr;
5862 status_change();
5863 unlock();
5864 return tcp_port;
5865 }
5866
5867 void MainController::shutdown_session()
5868 {
5869 lock();
5870 switch (mc_state) {
5871 case MC_INACTIVE:
5872 status_change();
5873 break;
5874 case MC_SHUTDOWN:
5875 break;
5876 case MC_LISTENING:
5877 case MC_LISTENING_CONFIGURED:
5878 case MC_HC_CONNECTED:
5879 case MC_ACTIVE:
5880 notify("Shutting down session.");
5881 wakeup_thread(REASON_SHUTDOWN);
5882 break;
5883 default:
5884 error("MainController::shutdown_session: called in wrong state.");
5885 }
5886 unlock();
5887 }
5888
5889 char *MainController::config_str;
5890
5891 void MainController::configure(const char *config_file)
5892 {
5893 lock();
5894 switch (mc_state) {
5895 case MC_HC_CONNECTED:
5896 case MC_ACTIVE:
5897 mc_state = MC_CONFIGURING;
5898 break;
5899 case MC_LISTENING:
5900 case MC_LISTENING_CONFIGURED:
5901 mc_state = MC_LISTENING_CONFIGURED;
5902 break;
5903 default:
5904 error("MainController::configure: called in wrong state.");
5905 unlock();
5906 return;
5907 }
5908 Free(config_str);
5909 config_str = mcopystr(config_file);
5910 if(mc_state == MC_CONFIGURING) {
5911 notify("Downloading configuration file to all HCs.");
5912 for (int i = 0; i < n_hosts; i++) configure_host(hosts[i], FALSE);
5913 }
5914 status_change();
5915 unlock();
5916 }
5917
5918 void MainController::create_mtc(int host_index)
5919 {
5920 lock();
5921 if (mc_state != MC_ACTIVE) {
5922 error("MainController::create_mtc: called in wrong state.");
5923 unlock();
5924 return;
5925 }
5926 if (host_index < 0 || host_index >= n_hosts) {
5927 error("MainController::create_mtc: host index (%d) is out of range.",
5928 host_index);
5929 unlock();
5930 return;
5931 }
5932 host_struct *host = hosts[host_index];
5933 switch (host->hc_state) {
5934 case HC_OVERLOADED:
5935 notify("HC on host %s reported overload. Trying to create MTC there "
5936 "anyway.", host->hostname);
5937 case HC_ACTIVE:
5938 break;
5939 default:
5940 error("MTC cannot be created on %s: HC is not active.", host->hostname);
5941 unlock();
5942 return;
5943 }
5944 notify("Creating MTC on host %s.", host->hostname);
5945 send_create_mtc(host);
5946
5947 mtc = new component_struct;
5948 mtc->comp_ref = MTC_COMPREF;
5949 init_qualified_name(&mtc->comp_type);
5950 mtc->comp_name = new char[4];
5951 strcpy(mtc->comp_name, "MTC");
5952 mtc->tc_state = TC_INITIAL;
5953 mtc->local_verdict = NONE;
5954 mtc->verdict_reason = NULL;
5955 mtc->tc_fd = -1;
5956 mtc->text_buf = NULL;
5957 init_qualified_name(&mtc->tc_fn_name);
5958 mtc->return_type = NULL;
5959 mtc->return_value_len = 0;
5960 mtc->return_value = NULL;
5961 mtc->is_alive = FALSE;
5962 mtc->stop_requested = FALSE;
5963 mtc->process_killed = FALSE;
5964 mtc->initial.create_requestor = NULL;
5965 mtc->initial.location_str = NULL;
5966 init_requestors(&mtc->done_requestors, NULL);
5967 init_requestors(&mtc->killed_requestors, NULL);
5968 init_requestors(&mtc->cancel_done_sent_for, NULL);
5969 mtc->kill_timer = NULL;
5970 init_connections(mtc);
5971 add_component(mtc);
5972 add_component_to_host(host, mtc);
5973 host->n_active_components++;
5974
5975 system = new component_struct;
5976 system->comp_ref = SYSTEM_COMPREF;
5977 init_qualified_name(&system->comp_type);
5978 system->comp_name = new char[7];
5979 strcpy(system->comp_name, "SYSTEM");
5980 system->log_source = NULL;
5981 system->comp_location = NULL;
5982 system->tc_state = TC_SYSTEM;
5983 system->local_verdict = NONE;
5984 system->verdict_reason = NULL;
5985 system->tc_fd = -1;
5986 system->text_buf = NULL;
5987 init_qualified_name(&system->tc_fn_name);
5988 system->return_type = NULL;
5989 system->return_value_len = 0;
5990 system->return_value = NULL;
5991 system->is_alive = FALSE;
5992 system->stop_requested = FALSE;
5993 system->process_killed = FALSE;
5994 init_requestors(&system->done_requestors, NULL);
5995 init_requestors(&system->killed_requestors, NULL);
5996 init_requestors(&system->cancel_done_sent_for, NULL);
5997 system->kill_timer = NULL;
5998 init_connections(system);
5999 add_component(system);
6000
6001 mc_state = MC_CREATING_MTC;
6002 status_change();
6003 unlock();
6004 }
6005
6006 void MainController::exit_mtc()
6007 {
6008 lock();
6009 if (mc_state != MC_READY) {
6010 error("MainController::exit_mtc: called in wrong state.");
6011 unlock();
6012 return;
6013 }
6014 notify("Terminating MTC.");
6015 send_exit_mtc();
6016 mtc->tc_state = TC_EXITING;
6017 mtc->comp_location->n_active_components--;
6018 mc_state = MC_TERMINATING_MTC;
6019 start_kill_timer(mtc);
6020 status_change();
6021 unlock();
6022 }
6023
6024 void MainController::execute_control(const char *module_name)
6025 {
6026 lock();
6027 if (mc_state != MC_READY) {
6028 error("MainController::execute_control: called in wrong state.");
6029 unlock();
6030 return;
6031 }
6032 send_execute_control(module_name);
6033 mtc->tc_state = MTC_CONTROLPART;
6034 mc_state = MC_EXECUTING_CONTROL;
6035 status_change();
6036 unlock();
6037 }
6038
6039 void MainController::execute_testcase(const char *module_name,
6040 const char *testcase_name)
6041 {
6042 lock();
6043 if (mc_state != MC_READY) {
6044 error("MainController::execute_testcase: called in wrong state.");
6045 unlock();
6046 return;
6047 }
6048 send_execute_testcase(module_name, testcase_name);
6049 mtc->tc_state = MTC_CONTROLPART;
6050 mc_state = MC_EXECUTING_CONTROL;
6051 status_change();
6052 unlock();
6053 }
6054
6055 void MainController::stop_after_testcase(boolean new_state)
6056 {
6057 lock();
6058 stop_after_tc = new_state;
6059 if (mc_state == MC_PAUSED && !stop_after_tc) {
6060 unlock();
6061 continue_testcase();
6062 } else unlock();
6063 }
6064
6065 void MainController::continue_testcase()
6066 {
6067 lock();
6068 if (mc_state == MC_PAUSED) {
6069 notify("Resuming execution.");
6070 send_continue();
6071 mtc->tc_state = MTC_CONTROLPART;
6072 mc_state = MC_EXECUTING_CONTROL;
6073 status_change();
6074 } else error("MainController::continue_testcase: called in wrong state.");
6075 unlock();
6076 }
6077
6078 void MainController::stop_execution()
6079 {
6080 lock();
6081 if (!stop_requested) {
6082 notify("Stopping execution.");
6083 switch (mc_state) {
6084 case MC_PAUSED:
6085 mc_state = MC_EXECUTING_CONTROL;
6086 mtc->tc_state = MTC_CONTROLPART;
6087 case MC_EXECUTING_CONTROL:
6088 send_stop(mtc);
6089 mtc->stop_requested = TRUE;
6090 start_kill_timer(mtc);
6091 wakeup_thread(REASON_MTC_KILL_TIMER);
6092 break;
6093 case MC_EXECUTING_TESTCASE:
6094 if (!mtc->stop_requested) {
6095 send_stop(mtc);
6096 kill_all_components(TRUE);
6097 mtc->stop_requested = TRUE;
6098 start_kill_timer(mtc);
6099 wakeup_thread(REASON_MTC_KILL_TIMER);
6100 }
6101 case MC_TERMINATING_TESTCASE:
6102 // MTC will be stopped later in finish_testcase()
6103 case MC_READY:
6104 // do nothing
6105 break;
6106 default:
6107 error("MainController::stop_execution: called in wrong state.");
6108 unlock();
6109 return;
6110 }
6111 stop_requested = TRUE;
6112 status_change();
6113 } else notify("Stop was already requested. Operation ignored.");
6114 unlock();
6115 }
6116
6117 mc_state_enum MainController::get_state()
6118 {
6119 lock();
6120 mc_state_enum ret_val = mc_state;
6121 unlock();
6122 return ret_val;
6123 }
6124
6125 boolean MainController::get_stop_after_testcase()
6126 {
6127 lock();
6128 boolean ret_val = stop_after_tc;
6129 unlock();
6130 return ret_val;
6131 }
6132
6133 int MainController::get_nof_hosts()
6134 {
6135 lock();
6136 int ret_val = n_hosts;
6137 unlock();
6138 return ret_val;
6139 }
6140
6141 host_struct *MainController::get_host_data(int host_index)
6142 {
6143 lock();
6144 if (host_index >= 0 && host_index < n_hosts) return hosts[host_index];
6145 else return NULL;
6146 }
6147
6148 component_struct *MainController::get_component_data(int component_reference)
6149 {
6150 lock();
6151 return lookup_component(component_reference);
6152 }
6153
6154 void MainController::release_data()
6155 {
6156 unlock();
6157 }
6158
6159 const char *MainController::get_mc_state_name(mc_state_enum state)
6160 {
6161 switch (state) {
6162 case MC_INACTIVE:
6163 return "inactive";
6164 case MC_LISTENING:
6165 return "listening";
6166 case MC_LISTENING_CONFIGURED:
6167 return "listening (configured)";
6168 case MC_HC_CONNECTED:
6169 return "HC connected";
6170 case MC_CONFIGURING:
6171 return "configuring...";
6172 case MC_ACTIVE:
6173 return "active";
6174 case MC_CREATING_MTC:
6175 return "creating MTC...";
6176 case MC_TERMINATING_MTC:
6177 return "terminating MTC...";
6178 case MC_READY:
6179 return "ready";
6180 case MC_EXECUTING_CONTROL:
6181 return "executing control part";
6182 case MC_EXECUTING_TESTCASE:
6183 return "executing testcase";
6184 case MC_TERMINATING_TESTCASE:
6185 return "terminating testcase...";
6186 case MC_PAUSED:
6187 return "paused after testcase";
6188 case MC_SHUTDOWN:
6189 return "shutting down...";
6190 default:
6191 return "unknown/transient";
6192 }
6193 }
6194
6195 const char *MainController::get_hc_state_name(hc_state_enum state)
6196 {
6197 switch (state) {
6198 case HC_IDLE:
6199 return "not configured";
6200 case HC_CONFIGURING:
6201 case HC_CONFIGURING_OVERLOADED:
6202 return "being configured";
6203 case HC_ACTIVE:
6204 return "ready";
6205 case HC_OVERLOADED:
6206 return "overloaded";
6207 case HC_DOWN:
6208 return "down";
6209 default:
6210 return "unknown/transient";
6211 }
6212 }
6213
6214 const char *MainController::get_tc_state_name(tc_state_enum state)
6215 {
6216 switch (state) {
6217 case TC_INITIAL:
6218 return "being created";
6219 case TC_IDLE:
6220 return "inactive - waiting for start";
6221 case TC_CREATE:
6222 return "executing create operation";
6223 case TC_START:
6224 return "executing component start operation";
6225 case TC_STOP:
6226 case MTC_ALL_COMPONENT_STOP:
6227 return "executing component stop operation";
6228 case TC_KILL:
6229 case MTC_ALL_COMPONENT_KILL:
6230 return "executing kill operation";
6231 case TC_CONNECT:
6232 return "executing connect operation";
6233 case TC_DISCONNECT:
6234 return "executing disconnect operation";
6235 case TC_MAP:
6236 return "executing map operation";
6237 case TC_UNMAP:
6238 return "executing unmap operation";
6239 case TC_STOPPING:
6240 return "being stopped";
6241 case TC_EXITING:
6242 return "terminated";
6243 case TC_EXITED:
6244 return "exited";
6245 case MTC_CONTROLPART:
6246 return "executing control part";
6247 case MTC_TESTCASE:
6248 return "executing testcase";
6249 case MTC_TERMINATING_TESTCASE:
6250 return "terminating testcase";
6251 case MTC_PAUSED:
6252 return "paused";
6253 case PTC_FUNCTION:
6254 return "executing function";
6255 case PTC_STARTING:
6256 return "being started";
6257 case PTC_STOPPED:
6258 return "stopped - waiting for re-start";
6259 case PTC_KILLING:
6260 case PTC_STOPPING_KILLING:
6261 return "being killed";
6262 default:
6263 return "unknown/transient";
6264 }
6265 }
6266
6267 const char *MainController::get_transport_name(transport_type_enum transport)
6268 {
6269 switch (transport) {
6270 case TRANSPORT_LOCAL:
6271 return "LOCAL (software loop)";
6272 case TRANSPORT_INET_STREAM:
6273 return "INET_STREAM (TCP over IPv4)";
6274 case TRANSPORT_UNIX_STREAM:
6275 return "UNIX_STREAM (UNIX domain socket)";
6276 default:
6277 return "unknown";
6278 }
6279 }
6280
6281 //----------------------------------------------------------------------------
6282
6283 } /* namespace mctr */
6284
6285 //----------------------------------------------------------------------------
6286
6287 // Local Variables:
6288 // mode: C++
6289 // indent-tabs-mode: nil
6290 // c-basic-offset: 2
6291 // End:
This page took 0.17494 seconds and 5 git commands to generate.