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